mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2026-09-03 20:52:55 -05:00
Merge pull request #2746 from tk0miya/check_config_value_as_enum
Add sphinx.config.ENUM to check the config values is in candidates
This commit is contained in:
@@ -64,6 +64,7 @@ Features added
|
|||||||
* latex, make the use of ``\small`` for code listings customizable (ref #2721)
|
* latex, make the use of ``\small`` for code listings customizable (ref #2721)
|
||||||
* #2663: Add ``--warning-is-error`` option to setup.py command
|
* #2663: Add ``--warning-is-error`` option to setup.py command
|
||||||
* Show warnings if deprecated latex options are used
|
* Show warnings if deprecated latex options are used
|
||||||
|
* Add sphinx.config.ENUM to check the config values is in candidates
|
||||||
|
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
|
|||||||
+31
-11
@@ -28,10 +28,25 @@ if PY3:
|
|||||||
CONFIG_SYNTAX_ERROR += "\nDid you change the syntax from 2.x to 3.x?"
|
CONFIG_SYNTAX_ERROR += "\nDid you change the syntax from 2.x to 3.x?"
|
||||||
CONFIG_EXIT_ERROR = "The configuration file (or one of the modules it imports) " \
|
CONFIG_EXIT_ERROR = "The configuration file (or one of the modules it imports) " \
|
||||||
"called sys.exit()"
|
"called sys.exit()"
|
||||||
|
CONFIG_ENUM_WARNING = "The config value `{name}` has to be a one of {candidates}, " \
|
||||||
|
"but `{current}` is given."
|
||||||
CONFIG_TYPE_WARNING = "The config value `{name}' has type `{current.__name__}', " \
|
CONFIG_TYPE_WARNING = "The config value `{name}' has type `{current.__name__}', " \
|
||||||
"defaults to `{default.__name__}.'"
|
"defaults to `{default.__name__}.'"
|
||||||
|
|
||||||
|
|
||||||
|
class ENUM:
|
||||||
|
"""represents the config value should be a one of candidates.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
app.add_config_value('latex_show_urls', 'no', ENUM('no', 'footnote', 'inline'))
|
||||||
|
"""
|
||||||
|
def __init__(self, *candidates):
|
||||||
|
self.candidates = candidates
|
||||||
|
|
||||||
|
def match(self, value):
|
||||||
|
return value in self.candidates
|
||||||
|
|
||||||
|
|
||||||
string_classes = [text_type]
|
string_classes = [text_type]
|
||||||
if PY2:
|
if PY2:
|
||||||
string_classes.append(binary_type) # => [str, unicode]
|
string_classes.append(binary_type) # => [str, unicode]
|
||||||
@@ -150,19 +165,24 @@ class Config(object):
|
|||||||
if default is None and not permitted:
|
if default is None and not permitted:
|
||||||
continue # neither inferrable nor expliclitly permitted types
|
continue # neither inferrable nor expliclitly permitted types
|
||||||
current = self[name]
|
current = self[name]
|
||||||
if type(current) is type(default):
|
if isinstance(permitted, ENUM):
|
||||||
continue
|
if not permitted.match(current):
|
||||||
if type(current) in permitted:
|
warn(CONFIG_ENUM_WARNING.format(
|
||||||
continue
|
name=name, current=current, candidates=permitted.candidates))
|
||||||
|
else:
|
||||||
|
if type(current) is type(default):
|
||||||
|
continue
|
||||||
|
if type(current) in permitted:
|
||||||
|
continue
|
||||||
|
|
||||||
common_bases = (set(type(current).__bases__ + (type(current),)) &
|
common_bases = (set(type(current).__bases__ + (type(current),)) &
|
||||||
set(type(default).__bases__))
|
set(type(default).__bases__))
|
||||||
common_bases.discard(object)
|
common_bases.discard(object)
|
||||||
if common_bases:
|
if common_bases:
|
||||||
continue # at least we share a non-trivial base class
|
continue # at least we share a non-trivial base class
|
||||||
|
|
||||||
warn(CONFIG_TYPE_WARNING.format(
|
warn(CONFIG_TYPE_WARNING.format(
|
||||||
name=name, current=type(current), default=type(default)))
|
name=name, current=type(current), default=type(default)))
|
||||||
|
|
||||||
def check_unicode(self, warn):
|
def check_unicode(self, warn):
|
||||||
# check all string values for non-ASCII characters in bytestrings,
|
# check all string values for non-ASCII characters in bytestrings,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from sphinx.config import string_classes
|
from sphinx.config import string_classes, ENUM
|
||||||
|
|
||||||
value1 = 123 # wrong type
|
value1 = 123 # wrong type
|
||||||
value2 = 123 # lambda with wrong type
|
value2 = 123 # lambda with wrong type
|
||||||
@@ -45,3 +45,4 @@ def setup(app):
|
|||||||
app.add_config_value('value14', None, False, string_classes)
|
app.add_config_value('value14', None, False, string_classes)
|
||||||
app.add_config_value('value15', u'unicode', False)
|
app.add_config_value('value15', u'unicode', False)
|
||||||
app.add_config_value('value16', u'unicode', False)
|
app.add_config_value('value16', u'unicode', False)
|
||||||
|
app.add_config_value('value17', 'default', False, ENUM('default', 'one', 'two'))
|
||||||
|
|||||||
@@ -206,3 +206,15 @@ def test_gen_check_types(app, status, warning):
|
|||||||
'override on "%s" should%s raise a type warning' %
|
'override on "%s" should%s raise a type warning' %
|
||||||
(key, '' if should else ' NOT')
|
(key, '' if should else ' NOT')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@with_app(testroot='config')
|
||||||
|
def test_check_enum(app, status, warning):
|
||||||
|
assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
|
||||||
|
not in warning.getvalue()
|
||||||
|
|
||||||
|
|
||||||
|
@with_app(testroot='config', confoverrides={'value17': 'invalid'})
|
||||||
|
def test_check_enum_failed(app, status, warning):
|
||||||
|
assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \
|
||||||
|
"but `invalid` is given." in warning.getvalue()
|
||||||
|
|||||||
Reference in New Issue
Block a user