mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Enable automatic formatting for `sphinx/config.py
`
This commit is contained in:
parent
6e4c4f11eb
commit
9cb93aeb01
@ -394,7 +394,6 @@ preview = true
|
|||||||
quote-style = "single"
|
quote-style = "single"
|
||||||
exclude = [
|
exclude = [
|
||||||
"sphinx/builders/latex/constants.py",
|
"sphinx/builders/latex/constants.py",
|
||||||
"sphinx/config.py",
|
|
||||||
"sphinx/domains/__init__.py",
|
"sphinx/domains/__init__.py",
|
||||||
"sphinx/domains/c/_parser.py",
|
"sphinx/domains/c/_parser.py",
|
||||||
"sphinx/domains/c/_ids.py",
|
"sphinx/domains/c/_ids.py",
|
||||||
|
270
sphinx/config.py
270
sphinx/config.py
@ -29,7 +29,11 @@ if TYPE_CHECKING:
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
_ConfigRebuild: TypeAlias = Literal[
|
_ConfigRebuild: TypeAlias = Literal[
|
||||||
'', 'env', 'epub', 'gettext', 'html',
|
'',
|
||||||
|
'env',
|
||||||
|
'epub',
|
||||||
|
'gettext',
|
||||||
|
'html',
|
||||||
# sphinxcontrib-applehelp
|
# sphinxcontrib-applehelp
|
||||||
'applehelp',
|
'applehelp',
|
||||||
# sphinxcontrib-devhelp
|
# sphinxcontrib-devhelp
|
||||||
@ -130,15 +134,35 @@ class _Opt:
|
|||||||
|
|
||||||
def __eq__(self, other: object) -> bool:
|
def __eq__(self, other: object) -> bool:
|
||||||
if isinstance(other, _Opt):
|
if isinstance(other, _Opt):
|
||||||
self_tpl = (self.default, self.rebuild, self.valid_types, self.description)
|
self_tpl = (
|
||||||
other_tpl = (other.default, other.rebuild, other.valid_types, self.description)
|
self.default,
|
||||||
|
self.rebuild,
|
||||||
|
self.valid_types,
|
||||||
|
self.description,
|
||||||
|
)
|
||||||
|
other_tpl = (
|
||||||
|
other.default,
|
||||||
|
other.rebuild,
|
||||||
|
other.valid_types,
|
||||||
|
other.description,
|
||||||
|
)
|
||||||
return self_tpl == other_tpl
|
return self_tpl == other_tpl
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
def __lt__(self, other: _Opt) -> bool:
|
def __lt__(self, other: _Opt) -> bool:
|
||||||
if self.__class__ is other.__class__:
|
if self.__class__ is other.__class__:
|
||||||
self_tpl = (self.default, self.rebuild, self.valid_types, self.description)
|
self_tpl = (
|
||||||
other_tpl = (other.default, other.rebuild, other.valid_types, self.description)
|
self.default,
|
||||||
|
self.rebuild,
|
||||||
|
self.valid_types,
|
||||||
|
self.description,
|
||||||
|
)
|
||||||
|
other_tpl = (
|
||||||
|
other.default,
|
||||||
|
other.rebuild,
|
||||||
|
other.valid_types,
|
||||||
|
other.description,
|
||||||
|
)
|
||||||
return self_tpl > other_tpl
|
return self_tpl > other_tpl
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
@ -161,7 +185,8 @@ class _Opt:
|
|||||||
return self.default, self.rebuild, self.valid_types, self.description
|
return self.default, self.rebuild, self.valid_types, self.description
|
||||||
|
|
||||||
def __setstate__(
|
def __setstate__(
|
||||||
self, state: tuple[Any, _ConfigRebuild, _OptValidTypes, str]) -> None:
|
self, state: tuple[Any, _ConfigRebuild, _OptValidTypes, str]
|
||||||
|
) -> None:
|
||||||
default, rebuild, valid_types, description = state
|
default, rebuild, valid_types, description = state
|
||||||
super().__setattr__('default', default)
|
super().__setattr__('default', default)
|
||||||
super().__setattr__('rebuild', rebuild)
|
super().__setattr__('rebuild', rebuild)
|
||||||
@ -172,7 +197,9 @@ class _Opt:
|
|||||||
warnings.warn(
|
warnings.warn(
|
||||||
f'The {self.__class__.__name__!r} object tuple interface is deprecated, '
|
f'The {self.__class__.__name__!r} object tuple interface is deprecated, '
|
||||||
"use attribute access instead for 'default', 'rebuild', and 'valid_types'.",
|
"use attribute access instead for 'default', 'rebuild', and 'valid_types'.",
|
||||||
RemovedInSphinx90Warning, stacklevel=2)
|
RemovedInSphinx90Warning,
|
||||||
|
stacklevel=2,
|
||||||
|
)
|
||||||
return (self.default, self.rebuild, self.valid_types)[item]
|
return (self.default, self.rebuild, self.valid_types)[item]
|
||||||
|
|
||||||
|
|
||||||
@ -201,35 +228,39 @@ class Config:
|
|||||||
'author': _Opt('Author name not set', 'env', ()),
|
'author': _Opt('Author name not set', 'env', ()),
|
||||||
'project_copyright': _Opt('', 'html', frozenset((str, tuple, list))),
|
'project_copyright': _Opt('', 'html', frozenset((str, tuple, list))),
|
||||||
'copyright': _Opt(
|
'copyright': _Opt(
|
||||||
lambda config: config.project_copyright, 'html', frozenset((str, tuple, list))),
|
lambda config: config.project_copyright,
|
||||||
|
'html',
|
||||||
|
frozenset((str, tuple, list)),
|
||||||
|
),
|
||||||
'version': _Opt('', 'env', ()),
|
'version': _Opt('', 'env', ()),
|
||||||
'release': _Opt('', 'env', ()),
|
'release': _Opt('', 'env', ()),
|
||||||
'today': _Opt('', 'env', ()),
|
'today': _Opt('', 'env', ()),
|
||||||
# the real default is locale-dependent
|
# the real default is locale-dependent
|
||||||
'today_fmt': _Opt(None, 'env', frozenset((str,))),
|
'today_fmt': _Opt(None, 'env', frozenset((str,))),
|
||||||
|
|
||||||
'language': _Opt('en', 'env', frozenset((str,))),
|
'language': _Opt('en', 'env', frozenset((str,))),
|
||||||
'locale_dirs': _Opt(['locales'], 'env', ()),
|
'locale_dirs': _Opt(['locales'], 'env', ()),
|
||||||
'figure_language_filename': _Opt('{root}.{language}{ext}', 'env', frozenset((str,))),
|
'figure_language_filename': _Opt(
|
||||||
|
'{root}.{language}{ext}', 'env', frozenset((str,))
|
||||||
|
),
|
||||||
'gettext_allow_fuzzy_translations': _Opt(False, 'gettext', ()),
|
'gettext_allow_fuzzy_translations': _Opt(False, 'gettext', ()),
|
||||||
'translation_progress_classes': _Opt(
|
'translation_progress_classes': _Opt(
|
||||||
False, 'env', ENUM(True, False, 'translated', 'untranslated')),
|
False, 'env', ENUM(True, False, 'translated', 'untranslated')
|
||||||
|
),
|
||||||
'master_doc': _Opt('index', 'env', ()),
|
'master_doc': _Opt('index', 'env', ()),
|
||||||
'root_doc': _Opt(lambda config: config.master_doc, 'env', ()),
|
'root_doc': _Opt(lambda config: config.master_doc, 'env', ()),
|
||||||
# ``source_suffix`` type is actually ``dict[str, str | None]``:
|
# ``source_suffix`` type is actually ``dict[str, str | None]``:
|
||||||
# see ``convert_source_suffix()`` below.
|
# see ``convert_source_suffix()`` below.
|
||||||
'source_suffix': _Opt(
|
'source_suffix': _Opt({'.rst': 'restructuredtext'}, 'env', Any), # type: ignore[arg-type]
|
||||||
{'.rst': 'restructuredtext'}, 'env', Any), # type: ignore[arg-type]
|
|
||||||
'source_encoding': _Opt('utf-8-sig', 'env', ()),
|
'source_encoding': _Opt('utf-8-sig', 'env', ()),
|
||||||
'exclude_patterns': _Opt([], 'env', frozenset((str,))),
|
'exclude_patterns': _Opt([], 'env', frozenset((str,))),
|
||||||
'include_patterns': _Opt(["**"], 'env', frozenset((str,))),
|
'include_patterns': _Opt(['**'], 'env', frozenset((str,))),
|
||||||
'default_role': _Opt(None, 'env', frozenset((str,))),
|
'default_role': _Opt(None, 'env', frozenset((str,))),
|
||||||
'add_function_parentheses': _Opt(True, 'env', ()),
|
'add_function_parentheses': _Opt(True, 'env', ()),
|
||||||
'add_module_names': _Opt(True, 'env', ()),
|
'add_module_names': _Opt(True, 'env', ()),
|
||||||
'toc_object_entries': _Opt(True, 'env', frozenset((bool,))),
|
'toc_object_entries': _Opt(True, 'env', frozenset((bool,))),
|
||||||
'toc_object_entries_show_parents': _Opt(
|
'toc_object_entries_show_parents': _Opt(
|
||||||
'domain', 'env', ENUM('domain', 'all', 'hide')),
|
'domain', 'env', ENUM('domain', 'all', 'hide')
|
||||||
|
),
|
||||||
'trim_footnote_reference_space': _Opt(False, 'env', ()),
|
'trim_footnote_reference_space': _Opt(False, 'env', ()),
|
||||||
'show_authors': _Opt(False, 'env', ()),
|
'show_authors': _Opt(False, 'env', ()),
|
||||||
'pygments_style': _Opt(None, 'html', frozenset((str,))),
|
'pygments_style': _Opt(None, 'html', frozenset((str,))),
|
||||||
@ -253,9 +284,11 @@ class Config:
|
|||||||
'nitpick_ignore_regex': _Opt([], '', frozenset((set, list, tuple))),
|
'nitpick_ignore_regex': _Opt([], '', frozenset((set, list, tuple))),
|
||||||
'numfig': _Opt(False, 'env', ()),
|
'numfig': _Opt(False, 'env', ()),
|
||||||
'numfig_secnum_depth': _Opt(1, 'env', ()),
|
'numfig_secnum_depth': _Opt(1, 'env', ()),
|
||||||
'numfig_format': _Opt({}, 'env', ()), # will be initialized in init_numfig_format()
|
# numfig_format will be initialized in init_numfig_format()
|
||||||
|
'numfig_format': _Opt({}, 'env', ()),
|
||||||
'maximum_signature_line_length': _Opt(
|
'maximum_signature_line_length': _Opt(
|
||||||
None, 'env', frozenset((int, types.NoneType))),
|
None, 'env', frozenset((int, types.NoneType))
|
||||||
|
),
|
||||||
'math_number_all': _Opt(False, 'env', ()),
|
'math_number_all': _Opt(False, 'env', ()),
|
||||||
'math_eqref_format': _Opt(None, 'env', frozenset((str,))),
|
'math_eqref_format': _Opt(None, 'env', frozenset((str,))),
|
||||||
'math_numfig': _Opt(True, 'env', ()),
|
'math_numfig': _Opt(True, 'env', ()),
|
||||||
@ -266,12 +299,18 @@ class Config:
|
|||||||
'smartquotes': _Opt(True, 'env', ()),
|
'smartquotes': _Opt(True, 'env', ()),
|
||||||
'smartquotes_action': _Opt('qDe', 'env', ()),
|
'smartquotes_action': _Opt('qDe', 'env', ()),
|
||||||
'smartquotes_excludes': _Opt(
|
'smartquotes_excludes': _Opt(
|
||||||
{'languages': ['ja', 'zh_CN', 'zh_TW'], 'builders': ['man', 'text']}, 'env', ()),
|
{'languages': ['ja', 'zh_CN', 'zh_TW'], 'builders': ['man', 'text']},
|
||||||
|
'env',
|
||||||
|
(),
|
||||||
|
),
|
||||||
'option_emphasise_placeholders': _Opt(False, 'env', ()),
|
'option_emphasise_placeholders': _Opt(False, 'env', ()),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, config: dict[str, Any] | None = None,
|
def __init__(
|
||||||
overrides: dict[str, Any] | None = None) -> None:
|
self,
|
||||||
|
config: dict[str, Any] | None = None,
|
||||||
|
overrides: dict[str, Any] | None = None,
|
||||||
|
) -> None:
|
||||||
raw_config: dict[str, Any] = config or {}
|
raw_config: dict[str, Any] = config or {}
|
||||||
self._overrides = dict(overrides) if overrides is not None else {}
|
self._overrides = dict(overrides) if overrides is not None else {}
|
||||||
self._options = Config.config_values.copy()
|
self._options = Config.config_values.copy()
|
||||||
@ -301,24 +340,33 @@ class Config:
|
|||||||
return self._overrides
|
return self._overrides
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def read(cls: type[Config], confdir: str | os.PathLike[str], overrides: dict | None = None,
|
def read(
|
||||||
tags: Tags | None = None) -> Config:
|
cls: type[Config],
|
||||||
|
confdir: str | os.PathLike[str],
|
||||||
|
overrides: dict | None = None,
|
||||||
|
tags: Tags | None = None,
|
||||||
|
) -> Config:
|
||||||
"""Create a Config object from configuration file."""
|
"""Create a Config object from configuration file."""
|
||||||
filename = Path(confdir, CONFIG_FILENAME)
|
filename = Path(confdir, CONFIG_FILENAME)
|
||||||
if not filename.is_file():
|
if not filename.is_file():
|
||||||
raise ConfigError(__("config directory doesn't contain a conf.py file (%s)") %
|
raise ConfigError(
|
||||||
confdir)
|
__("config directory doesn't contain a conf.py file (%s)") % confdir
|
||||||
|
)
|
||||||
namespace = eval_config_file(filename, tags)
|
namespace = eval_config_file(filename, tags)
|
||||||
|
|
||||||
# Note: Old sphinx projects have been configured as "language = None" because
|
# Note: Old sphinx projects have been configured as "language = None" because
|
||||||
# sphinx-quickstart previously generated this by default.
|
# sphinx-quickstart previously generated this by default.
|
||||||
# To keep compatibility, they should be fallback to 'en' for a while
|
# To keep compatibility, they should be fallback to 'en' for a while
|
||||||
# (This conversion should not be removed before 2025-01-01).
|
# (This conversion should not be removed before 2025-01-01).
|
||||||
if namespace.get("language", ...) is None:
|
if namespace.get('language', ...) is None:
|
||||||
logger.warning(__("Invalid configuration value found: 'language = None'. "
|
logger.warning(
|
||||||
"Update your configuration to a valid language code. "
|
__(
|
||||||
"Falling back to 'en' (English)."))
|
"Invalid configuration value found: 'language = None'. "
|
||||||
namespace["language"] = "en"
|
'Update your configuration to a valid language code. '
|
||||||
|
"Falling back to 'en' (English)."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
namespace['language'] = 'en'
|
||||||
|
|
||||||
return cls(namespace, overrides)
|
return cls(namespace, overrides)
|
||||||
|
|
||||||
@ -328,9 +376,11 @@ class Config:
|
|||||||
valid_types = opt.valid_types
|
valid_types = opt.valid_types
|
||||||
if valid_types == Any:
|
if valid_types == Any:
|
||||||
return value
|
return value
|
||||||
if (type(default) is bool
|
if type(default) is bool or (
|
||||||
or (not isinstance(valid_types, ENUM)
|
not isinstance(valid_types, ENUM)
|
||||||
and len(valid_types) == 1 and bool in valid_types)):
|
and len(valid_types) == 1
|
||||||
|
and bool in valid_types
|
||||||
|
):
|
||||||
if isinstance(valid_types, ENUM) or len(valid_types) > 1:
|
if isinstance(valid_types, ENUM) or len(valid_types) > 1:
|
||||||
# if valid_types are given, and non-bool valid types exist,
|
# if valid_types are given, and non-bool valid types exist,
|
||||||
# return the value without coercing to a Boolean.
|
# return the value without coercing to a Boolean.
|
||||||
@ -338,23 +388,31 @@ class Config:
|
|||||||
# given falsy string from a command line option
|
# given falsy string from a command line option
|
||||||
return value not in {'0', ''}
|
return value not in {'0', ''}
|
||||||
if isinstance(default, dict):
|
if isinstance(default, dict):
|
||||||
raise ValueError(__('cannot override dictionary config setting %r, '
|
raise ValueError(
|
||||||
'ignoring (use %r to set individual elements)') %
|
__(
|
||||||
(name, f'{name}.key=value'))
|
'cannot override dictionary config setting %r, '
|
||||||
|
'ignoring (use %r to set individual elements)'
|
||||||
|
)
|
||||||
|
% (name, f'{name}.key=value')
|
||||||
|
)
|
||||||
if isinstance(default, list):
|
if isinstance(default, list):
|
||||||
return value.split(',')
|
return value.split(',')
|
||||||
if isinstance(default, int):
|
if isinstance(default, int):
|
||||||
try:
|
try:
|
||||||
return int(value)
|
return int(value)
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
raise ValueError(__('invalid number %r for config value %r, ignoring') %
|
raise ValueError(
|
||||||
(value, name)) from exc
|
__('invalid number %r for config value %r, ignoring')
|
||||||
|
% (value, name)
|
||||||
|
) from exc
|
||||||
if callable(default):
|
if callable(default):
|
||||||
return value
|
return value
|
||||||
if isinstance(default, str) or default is None:
|
if isinstance(default, str) or default is None:
|
||||||
return value
|
return value
|
||||||
raise ValueError(__('cannot override config setting %r with unsupported '
|
raise ValueError(
|
||||||
'type, ignoring') % name)
|
__('cannot override config setting %r with unsupported type, ignoring')
|
||||||
|
% name
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def pre_init_values() -> None:
|
def pre_init_values() -> None:
|
||||||
@ -374,7 +432,9 @@ class Config:
|
|||||||
def _report_override_warnings(self) -> None:
|
def _report_override_warnings(self) -> None:
|
||||||
for name in self._overrides:
|
for name in self._overrides:
|
||||||
if name not in self._options:
|
if name not in self._options:
|
||||||
logger.warning(__('unknown config value %r in override, ignoring'), name)
|
logger.warning(
|
||||||
|
__('unknown config value %r in override, ignoring'), name
|
||||||
|
)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
values = []
|
values = []
|
||||||
@ -383,7 +443,7 @@ class Config:
|
|||||||
opt_value = getattr(self, opt_name)
|
opt_value = getattr(self, opt_name)
|
||||||
except Exception:
|
except Exception:
|
||||||
opt_value = '<error!>'
|
opt_value = '<error!>'
|
||||||
values.append(f"{opt_name}={opt_value!r}")
|
values.append(f'{opt_name}={opt_value!r}')
|
||||||
return self.__class__.__qualname__ + '(' + ', '.join(values) + ')'
|
return self.__class__.__qualname__ + '(' + ', '.join(values) + ')'
|
||||||
|
|
||||||
def __setattr__(self, key: str, value: object) -> None:
|
def __setattr__(self, key: str, value: object) -> None:
|
||||||
@ -409,7 +469,7 @@ class Config:
|
|||||||
try:
|
try:
|
||||||
value = self.convert_overrides(name, value)
|
value = self.convert_overrides(name, value)
|
||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
logger.warning("%s", exc)
|
logger.warning('%s', exc)
|
||||||
else:
|
else:
|
||||||
self.__setattr__(name, value)
|
self.__setattr__(name, value)
|
||||||
return value
|
return value
|
||||||
@ -446,9 +506,14 @@ class Config:
|
|||||||
for name, opt in self._options.items():
|
for name, opt in self._options.items():
|
||||||
yield ConfigValue(name, getattr(self, name), opt.rebuild)
|
yield ConfigValue(name, getattr(self, name), opt.rebuild)
|
||||||
|
|
||||||
def add(self, name: str, default: Any, rebuild: _ConfigRebuild,
|
def add(
|
||||||
|
self,
|
||||||
|
name: str,
|
||||||
|
default: Any,
|
||||||
|
rebuild: _ConfigRebuild,
|
||||||
types: type | Collection[type] | ENUM,
|
types: type | Collection[type] | ENUM,
|
||||||
description: str = '') -> None:
|
description: str = '',
|
||||||
|
) -> None:
|
||||||
if name in self._options:
|
if name in self._options:
|
||||||
raise ExtensionError(__('Config value %r already present') % name)
|
raise ExtensionError(__('Config value %r already present') % name)
|
||||||
|
|
||||||
@ -486,8 +551,10 @@ class Config:
|
|||||||
# will always mark the config value as changed,
|
# will always mark the config value as changed,
|
||||||
# and thus always invalidate the cache and perform a rebuild.
|
# and thus always invalidate the cache and perform a rebuild.
|
||||||
logger.warning(
|
logger.warning(
|
||||||
__('cannot cache unpickable configuration value: %r '
|
__(
|
||||||
'(because it contains a function, class, or module object)'),
|
'cannot cache unpickable configuration value: %r '
|
||||||
|
'(because it contains a function, class, or module object)'
|
||||||
|
),
|
||||||
name,
|
name,
|
||||||
type='config',
|
type='config',
|
||||||
subtype='cache',
|
subtype='cache',
|
||||||
@ -510,7 +577,9 @@ class Config:
|
|||||||
self.__dict__.update(state)
|
self.__dict__.update(state)
|
||||||
|
|
||||||
|
|
||||||
def eval_config_file(filename: str | os.PathLike[str], tags: Tags | None) -> dict[str, Any]:
|
def eval_config_file(
|
||||||
|
filename: str | os.PathLike[str], tags: Tags | None
|
||||||
|
) -> dict[str, Any]:
|
||||||
"""Evaluate a config file."""
|
"""Evaluate a config file."""
|
||||||
filename = Path(filename)
|
filename = Path(filename)
|
||||||
|
|
||||||
@ -524,24 +593,26 @@ def eval_config_file(filename: str | os.PathLike[str], tags: Tags | None) -> dic
|
|||||||
code = compile(filename.read_bytes(), filename, 'exec')
|
code = compile(filename.read_bytes(), filename, 'exec')
|
||||||
exec(code, namespace) # NoQA: S102
|
exec(code, namespace) # NoQA: S102
|
||||||
except SyntaxError as err:
|
except SyntaxError as err:
|
||||||
msg = __("There is a syntax error in your configuration file: %s\n")
|
msg = __('There is a syntax error in your configuration file: %s\n')
|
||||||
raise ConfigError(msg % err) from err
|
raise ConfigError(msg % err) from err
|
||||||
except SystemExit as exc:
|
except SystemExit as exc:
|
||||||
msg = __("The configuration file (or one of the modules it imports) "
|
msg = __(
|
||||||
"called sys.exit()")
|
'The configuration file (or one of the modules it imports) '
|
||||||
|
'called sys.exit()'
|
||||||
|
)
|
||||||
raise ConfigError(msg) from exc
|
raise ConfigError(msg) from exc
|
||||||
except ConfigError:
|
except ConfigError:
|
||||||
# pass through ConfigError from conf.py as is. It will be shown in console.
|
# pass through ConfigError from conf.py as is. It will be shown in console.
|
||||||
raise
|
raise
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
msg = __("There is a programmable error in your configuration file:\n\n%s")
|
msg = __('There is a programmable error in your configuration file:\n\n%s')
|
||||||
raise ConfigError(msg % traceback.format_exc()) from exc
|
raise ConfigError(msg % traceback.format_exc()) from exc
|
||||||
|
|
||||||
return namespace
|
return namespace
|
||||||
|
|
||||||
|
|
||||||
def _validate_valid_types(
|
def _validate_valid_types(
|
||||||
valid_types: type | Collection[type] | ENUM, /,
|
valid_types: type | Collection[type] | ENUM, /
|
||||||
) -> tuple[()] | tuple[type, ...] | frozenset[type] | ENUM:
|
) -> tuple[()] | tuple[type, ...] | frozenset[type] | ENUM:
|
||||||
if not valid_types:
|
if not valid_types:
|
||||||
return ()
|
return ()
|
||||||
@ -578,16 +649,24 @@ def convert_source_suffix(app: Sphinx, config: Config) -> None:
|
|||||||
# The default filetype is determined on later step.
|
# The default filetype is determined on later step.
|
||||||
# By default, it is considered as restructuredtext.
|
# By default, it is considered as restructuredtext.
|
||||||
config.source_suffix = {source_suffix: 'restructuredtext'}
|
config.source_suffix = {source_suffix: 'restructuredtext'}
|
||||||
logger.info(__("Converting `source_suffix = %r` to `source_suffix = %r`."),
|
logger.info(
|
||||||
source_suffix, config.source_suffix)
|
__('Converting `source_suffix = %r` to `source_suffix = %r`.'),
|
||||||
|
source_suffix,
|
||||||
|
config.source_suffix,
|
||||||
|
)
|
||||||
elif isinstance(source_suffix, list | tuple):
|
elif isinstance(source_suffix, list | tuple):
|
||||||
# if list, considers as all of them are default filetype
|
# if list, considers as all of them are default filetype
|
||||||
config.source_suffix = dict.fromkeys(source_suffix, 'restructuredtext')
|
config.source_suffix = dict.fromkeys(source_suffix, 'restructuredtext')
|
||||||
logger.info(__("Converting `source_suffix = %r` to `source_suffix = %r`."),
|
logger.info(
|
||||||
source_suffix, config.source_suffix)
|
__('Converting `source_suffix = %r` to `source_suffix = %r`.'),
|
||||||
|
source_suffix,
|
||||||
|
config.source_suffix,
|
||||||
|
)
|
||||||
elif not isinstance(source_suffix, dict):
|
elif not isinstance(source_suffix, dict):
|
||||||
msg = __("The config value `source_suffix' expects a dictionary, "
|
msg = __(
|
||||||
"a string, or a list of strings. Got `%r' instead (type %s).")
|
"The config value `source_suffix' expects a dictionary, "
|
||||||
|
"a string, or a list of strings. Got `%r' instead (type %s)."
|
||||||
|
)
|
||||||
raise ConfigError(msg % (source_suffix, type(source_suffix)))
|
raise ConfigError(msg % (source_suffix, type(source_suffix)))
|
||||||
|
|
||||||
|
|
||||||
@ -605,10 +684,12 @@ def convert_highlight_options(app: Sphinx, config: Config) -> None:
|
|||||||
|
|
||||||
def init_numfig_format(app: Sphinx, config: Config) -> None:
|
def init_numfig_format(app: Sphinx, config: Config) -> None:
|
||||||
"""Initialize :confval:`numfig_format`."""
|
"""Initialize :confval:`numfig_format`."""
|
||||||
numfig_format = {'section': _('Section %s'),
|
numfig_format = {
|
||||||
|
'section': _('Section %s'),
|
||||||
'figure': _('Fig. %s'),
|
'figure': _('Fig. %s'),
|
||||||
'table': _('Table %s'),
|
'table': _('Table %s'),
|
||||||
'code-block': _('Listing %s')}
|
'code-block': _('Listing %s'),
|
||||||
|
}
|
||||||
|
|
||||||
# override default labels by configuration
|
# override default labels by configuration
|
||||||
numfig_format.update(config.numfig_format)
|
numfig_format.update(config.numfig_format)
|
||||||
@ -715,10 +796,14 @@ def check_confval_types(app: Sphinx | None, config: Config) -> None:
|
|||||||
|
|
||||||
if isinstance(valid_types, ENUM):
|
if isinstance(valid_types, ENUM):
|
||||||
if not valid_types.match(value):
|
if not valid_types.match(value):
|
||||||
msg = __("The config value `{name}` has to be a one of {candidates}, "
|
msg = __(
|
||||||
"but `{current}` is given.")
|
'The config value `{name}` has to be a one of {candidates}, '
|
||||||
|
'but `{current}` is given.'
|
||||||
|
)
|
||||||
logger.warning(
|
logger.warning(
|
||||||
msg.format(name=name, current=value, candidates=valid_types.candidates),
|
msg.format(
|
||||||
|
name=name, current=value, candidates=valid_types.candidates
|
||||||
|
),
|
||||||
once=True,
|
once=True,
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
@ -732,28 +817,33 @@ def check_confval_types(app: Sphinx | None, config: Config) -> None:
|
|||||||
if type_value in valid_types: # check explicitly listed types
|
if type_value in valid_types: # check explicitly listed types
|
||||||
continue
|
continue
|
||||||
|
|
||||||
common_bases = ({*type_value.__bases__, type_value}
|
common_bases = {*type_value.__bases__, type_value} & 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
|
||||||
|
|
||||||
if valid_types:
|
if valid_types:
|
||||||
msg = __("The config value `{name}' has type `{current.__name__}'; "
|
msg = __(
|
||||||
"expected {permitted}.")
|
"The config value `{name}' has type `{current.__name__}'; "
|
||||||
|
'expected {permitted}.'
|
||||||
|
)
|
||||||
wrapped_valid_types = sorted(f"`{c.__name__}'" for c in valid_types)
|
wrapped_valid_types = sorted(f"`{c.__name__}'" for c in valid_types)
|
||||||
if len(wrapped_valid_types) > 2:
|
if len(wrapped_valid_types) > 2:
|
||||||
permitted = (", ".join(wrapped_valid_types[:-1])
|
permitted = (
|
||||||
+ f", or {wrapped_valid_types[-1]}")
|
', '.join(wrapped_valid_types[:-1])
|
||||||
|
+ f', or {wrapped_valid_types[-1]}'
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
permitted = " or ".join(wrapped_valid_types)
|
permitted = ' or '.join(wrapped_valid_types)
|
||||||
logger.warning(
|
logger.warning(
|
||||||
msg.format(name=name, current=type_value, permitted=permitted),
|
msg.format(name=name, current=type_value, permitted=permitted),
|
||||||
once=True,
|
once=True,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
msg = __("The config value `{name}' has type `{current.__name__}', "
|
msg = __(
|
||||||
"defaults to `{default.__name__}'.")
|
"The config value `{name}' has type `{current.__name__}', "
|
||||||
|
"defaults to `{default.__name__}'."
|
||||||
|
)
|
||||||
logger.warning(
|
logger.warning(
|
||||||
msg.format(name=name, current=type_value, default=type_default),
|
msg.format(name=name, current=type_value, default=type_default),
|
||||||
once=True,
|
once=True,
|
||||||
@ -767,17 +857,27 @@ def check_primary_domain(app: Sphinx, config: Config) -> None:
|
|||||||
config.primary_domain = None
|
config.primary_domain = None
|
||||||
|
|
||||||
|
|
||||||
def check_root_doc(app: Sphinx, env: BuildEnvironment, added: Set[str],
|
def check_master_doc(
|
||||||
changed: Set[str], removed: Set[str]) -> Iterable[str]:
|
app: Sphinx,
|
||||||
"""Adjust root_doc to 'contents' to support an old project which does not have
|
env: BuildEnvironment,
|
||||||
any root_doc setting.
|
added: Set[str],
|
||||||
"""
|
changed: Set[str],
|
||||||
if (app.config.root_doc == 'index' and
|
removed: Set[str],
|
||||||
'index' not in app.project.docnames and
|
) -> Iterable[str]:
|
||||||
'contents' in app.project.docnames):
|
"""Sphinx 2.0 changed the default from 'contents' to 'index'."""
|
||||||
logger.warning(__('Since v2.0, Sphinx uses "index" as root_doc by default. '
|
docnames = app.project.docnames
|
||||||
'Please add "root_doc = \'contents\'" to your conf.py.'))
|
if (
|
||||||
app.config.root_doc = "contents"
|
app.config.master_doc == 'index'
|
||||||
|
and 'index' not in docnames
|
||||||
|
and 'contents' in docnames
|
||||||
|
):
|
||||||
|
logger.warning(
|
||||||
|
__(
|
||||||
|
'Sphinx now uses "index" as the master document by default. '
|
||||||
|
'To keep pre-2.0 behaviour, set "master_doc = \'contents\'".'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
app.config.master_doc = 'contents'
|
||||||
|
|
||||||
return changed
|
return changed
|
||||||
|
|
||||||
@ -790,7 +890,7 @@ def setup(app: Sphinx) -> ExtensionMetadata:
|
|||||||
app.connect('config-inited', correct_copyright_year, priority=800)
|
app.connect('config-inited', correct_copyright_year, priority=800)
|
||||||
app.connect('config-inited', check_confval_types, priority=800)
|
app.connect('config-inited', check_confval_types, priority=800)
|
||||||
app.connect('config-inited', check_primary_domain, priority=800)
|
app.connect('config-inited', check_primary_domain, priority=800)
|
||||||
app.connect('env-get-outdated', check_root_doc)
|
app.connect('env-get-outdated', check_master_doc)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'version': 'builtin',
|
'version': 'builtin',
|
||||||
|
Loading…
Reference in New Issue
Block a user