Narrow the type for configuration option 'rebuild' values

This commit is contained in:
Adam Turner 2024-01-03 04:17:46 +00:00
parent cb9656f654
commit 19b2950511
17 changed files with 107 additions and 101 deletions

View File

@ -22,7 +22,7 @@ from pygments.lexer import Lexer # NoQA: TCH002
import sphinx
from sphinx import locale, package_dir
from sphinx.config import Config
from sphinx.config import Config, _ConfigRebuild
from sphinx.environment import BuildEnvironment
from sphinx.errors import ApplicationError, ConfigError, VersionRequirementError
from sphinx.events import EventManager
@ -507,7 +507,7 @@ class Sphinx:
self.registry.add_builder(builder, override=override)
# TODO(stephenfin): Describe 'types' parameter
def add_config_value(self, name: str, default: Any, rebuild: bool | str,
def add_config_value(self, name: str, default: Any, rebuild: _ConfigRebuild,
types: Any = ()) -> None:
"""Register a configuration value.

View File

@ -260,7 +260,7 @@ def setup(app: Sphinx) -> dict[str, Any]:
app.add_builder(Epub3Builder)
# config values
app.add_config_value('epub_basename', lambda self: make_filename(self.project), False)
app.add_config_value('epub_basename', lambda self: make_filename(self.project), '')
app.add_config_value('epub_version', 3.0, 'epub') # experimental
app.add_config_value('epub_theme', 'epub', 'epub')
app.add_config_value('epub_theme_options', {}, 'epub')

View File

@ -526,26 +526,26 @@ def setup(app: Sphinx) -> dict[str, Any]:
app.connect('config-inited', validate_latex_theme_options, priority=800)
app.connect('builder-inited', install_packages_for_ja)
app.add_config_value('latex_engine', default_latex_engine, False,
app.add_config_value('latex_engine', default_latex_engine, '',
ENUM('pdflatex', 'xelatex', 'lualatex', 'platex', 'uplatex'))
app.add_config_value('latex_documents', default_latex_documents, False)
app.add_config_value('latex_logo', None, False, [str])
app.add_config_value('latex_appendices', [], False)
app.add_config_value('latex_use_latex_multicolumn', False, False)
app.add_config_value('latex_use_xindy', default_latex_use_xindy, False, [bool])
app.add_config_value('latex_toplevel_sectioning', None, False,
app.add_config_value('latex_documents', default_latex_documents, '')
app.add_config_value('latex_logo', None, '', [str])
app.add_config_value('latex_appendices', [], '')
app.add_config_value('latex_use_latex_multicolumn', False, '')
app.add_config_value('latex_use_xindy', default_latex_use_xindy, '', [bool])
app.add_config_value('latex_toplevel_sectioning', None, '',
ENUM(None, 'part', 'chapter', 'section'))
app.add_config_value('latex_domain_indices', True, False, [list])
app.add_config_value('latex_show_urls', 'no', False)
app.add_config_value('latex_show_pagerefs', False, False)
app.add_config_value('latex_elements', {}, False)
app.add_config_value('latex_additional_files', [], False)
app.add_config_value('latex_table_style', ['booktabs', 'colorrows'], False, [list])
app.add_config_value('latex_theme', 'manual', False, [str])
app.add_config_value('latex_theme_options', {}, False)
app.add_config_value('latex_theme_path', [], False, [list])
app.add_config_value('latex_domain_indices', True, '', [list])
app.add_config_value('latex_show_urls', 'no', '')
app.add_config_value('latex_show_pagerefs', False, '')
app.add_config_value('latex_elements', {}, '')
app.add_config_value('latex_additional_files', [], '')
app.add_config_value('latex_table_style', ['booktabs', 'colorrows'], '', [list])
app.add_config_value('latex_theme', 'manual', '', [str])
app.add_config_value('latex_theme_options', {}, '')
app.add_config_value('latex_theme_path', [], '', [list])
app.add_config_value('latex_docclass', default_latex_docclass, False)
app.add_config_value('latex_docclass', default_latex_docclass, '')
return {
'version': 'builtin',

View File

@ -611,20 +611,20 @@ def setup(app: Sphinx) -> dict[str, Any]:
app.add_builder(CheckExternalLinksBuilder)
app.add_post_transform(HyperlinkCollector)
app.add_config_value('linkcheck_ignore', [], False)
app.add_config_value('linkcheck_exclude_documents', [], False)
app.add_config_value('linkcheck_allowed_redirects', {}, False)
app.add_config_value('linkcheck_auth', [], False)
app.add_config_value('linkcheck_request_headers', {}, False)
app.add_config_value('linkcheck_retries', 1, False)
app.add_config_value('linkcheck_timeout', None, False, [int, float])
app.add_config_value('linkcheck_workers', 5, False)
app.add_config_value('linkcheck_anchors', True, False)
app.add_config_value('linkcheck_ignore', [], '')
app.add_config_value('linkcheck_exclude_documents', [], '')
app.add_config_value('linkcheck_allowed_redirects', {}, '')
app.add_config_value('linkcheck_auth', [], '')
app.add_config_value('linkcheck_request_headers', {}, '')
app.add_config_value('linkcheck_retries', 1, '')
app.add_config_value('linkcheck_timeout', None, '', (int, float))
app.add_config_value('linkcheck_workers', 5, '')
app.add_config_value('linkcheck_anchors', True, '')
# Anchors starting with ! are ignored since they are
# commonly used for dynamic pages
app.add_config_value('linkcheck_anchors_ignore', ['^!'], False)
app.add_config_value('linkcheck_anchors_ignore_for_url', (), False, (tuple, list))
app.add_config_value('linkcheck_rate_limit_timeout', 300.0, False)
app.add_config_value('linkcheck_anchors_ignore', ['^!'], '')
app.add_config_value('linkcheck_anchors_ignore_for_url', (), '', (tuple, list))
app.add_config_value('linkcheck_rate_limit_timeout', 300.0, '')
app.add_event('linkcheck-process-uri')

View File

@ -116,9 +116,9 @@ def default_man_pages(config: Config) -> list[tuple[str, str, str, list[str], in
def setup(app: Sphinx) -> dict[str, Any]:
app.add_builder(ManualPageBuilder)
app.add_config_value('man_pages', default_man_pages, False)
app.add_config_value('man_show_urls', False, False)
app.add_config_value('man_make_section_directory', False, False)
app.add_config_value('man_pages', default_man_pages, '')
app.add_config_value('man_show_urls', False, '')
app.add_config_value('man_make_section_directory', False, '')
return {
'version': 'builtin',

View File

@ -214,13 +214,13 @@ def default_texinfo_documents(
def setup(app: Sphinx) -> dict[str, Any]:
app.add_builder(TexinfoBuilder)
app.add_config_value('texinfo_documents', default_texinfo_documents, False)
app.add_config_value('texinfo_appendices', [], False)
app.add_config_value('texinfo_elements', {}, False)
app.add_config_value('texinfo_domain_indices', True, False, [list])
app.add_config_value('texinfo_show_urls', 'footnote', False)
app.add_config_value('texinfo_no_detailmenu', False, False)
app.add_config_value('texinfo_cross_references', True, False)
app.add_config_value('texinfo_documents', default_texinfo_documents, '')
app.add_config_value('texinfo_appendices', [], '')
app.add_config_value('texinfo_elements', {}, '')
app.add_config_value('texinfo_domain_indices', True, '', [list])
app.add_config_value('texinfo_show_urls', 'footnote', '')
app.add_config_value('texinfo_no_detailmenu', False, '')
app.add_config_value('texinfo_cross_references', True, '')
return {
'version': 'builtin',

View File

@ -7,7 +7,7 @@ import time
import traceback
import types
from os import getenv, path
from typing import TYPE_CHECKING, Any, Callable, NamedTuple
from typing import TYPE_CHECKING, Any, Callable, Literal, NamedTuple
from sphinx.errors import ConfigError, ExtensionError
from sphinx.locale import _, __
@ -30,6 +30,8 @@ if TYPE_CHECKING:
logger = logging.getLogger(__name__)
_ConfigRebuild = Literal['', 'env', 'epub', 'gettext', 'html']
CONFIG_FILENAME = 'conf.py'
UNSERIALIZABLE_TYPES = (type, types.ModuleType, types.FunctionType)
@ -37,7 +39,7 @@ UNSERIALIZABLE_TYPES = (type, types.ModuleType, types.FunctionType)
class ConfigValue(NamedTuple):
name: str
value: Any
rebuild: bool | str
rebuild: _ConfigRebuild
def is_serializable(obj: Any) -> bool:
@ -89,7 +91,7 @@ class Config:
# If you add a value here, remember to include it in the docs!
config_values: dict[str, tuple] = {
config_values: dict[str, tuple[Any, _ConfigRebuild, Sequence[type] | ENUM | Any]] = {
# general options
'project': ('Python', 'env', []),
'author': ('unknown', 'env', []),
@ -134,12 +136,12 @@ class Config:
'rst_prolog': (None, 'env', [str]),
'trim_doctest_flags': (True, 'env', []),
'primary_domain': ('py', 'env', [NoneType]),
'needs_sphinx': (None, None, [str]),
'needs_extensions': ({}, None, []),
'needs_sphinx': (None, '', [str]),
'needs_extensions': ({}, '', []),
'manpages_url': (None, 'env', []),
'nitpicky': (False, None, []),
'nitpick_ignore': ([], None, [set, list, tuple]),
'nitpick_ignore_regex': ([], None, [set, list, tuple]),
'nitpicky': (False, '', []),
'nitpick_ignore': ([], '', [set, list, tuple]),
'nitpick_ignore_regex': ([], '', [set, list, tuple]),
'numfig': (False, 'env', []),
'numfig_secnum_depth': (1, 'env', []),
'numfig_format': ({}, 'env', []), # will be initialized in init_numfig_format()
@ -321,7 +323,8 @@ class Config:
for name, (_default, rebuild, _valid_types) in self.values.items():
yield ConfigValue(name, getattr(self, name), rebuild)
def add(self, name: str, default: Any, rebuild: bool | str, types: Any) -> None:
def add(self, name: str, default: Any, rebuild: _ConfigRebuild,
types: Sequence[type] | ENUM | Any) -> None:
valid_types = types
if name in self.values:
raise ExtensionError(__('Config value %r already present') % name)

View File

@ -2821,22 +2821,22 @@ def setup(app: Sphinx) -> dict[str, Any]:
app.add_autodocumenter(AttributeDocumenter)
app.add_autodocumenter(PropertyDocumenter)
app.add_config_value('autoclass_content', 'class', True, ENUM('both', 'class', 'init'))
app.add_config_value('autodoc_member_order', 'alphabetical', True,
app.add_config_value('autoclass_content', 'class', 'env', ENUM('both', 'class', 'init'))
app.add_config_value('autodoc_member_order', 'alphabetical', 'env',
ENUM('alphabetical', 'bysource', 'groupwise'))
app.add_config_value('autodoc_class_signature', 'mixed', True, ENUM('mixed', 'separated'))
app.add_config_value('autodoc_default_options', {}, True)
app.add_config_value('autodoc_docstring_signature', True, True)
app.add_config_value('autodoc_mock_imports', [], True)
app.add_config_value('autodoc_typehints', "signature", True,
app.add_config_value('autodoc_class_signature', 'mixed', 'env', ENUM('mixed', 'separated'))
app.add_config_value('autodoc_default_options', {}, 'env')
app.add_config_value('autodoc_docstring_signature', True, 'env')
app.add_config_value('autodoc_mock_imports', [], 'env')
app.add_config_value('autodoc_typehints', "signature", 'env',
ENUM("signature", "description", "none", "both"))
app.add_config_value('autodoc_typehints_description_target', 'all', True,
app.add_config_value('autodoc_typehints_description_target', 'all', 'env',
ENUM('all', 'documented', 'documented_params'))
app.add_config_value('autodoc_type_aliases', {}, True)
app.add_config_value('autodoc_type_aliases', {}, 'env')
app.add_config_value('autodoc_typehints_format', "short", 'env',
ENUM("fully-qualified", "short"))
app.add_config_value('autodoc_warningiserror', True, True)
app.add_config_value('autodoc_inherit_docstrings', True, True)
app.add_config_value('autodoc_warningiserror', True, 'env')
app.add_config_value('autodoc_inherit_docstrings', True, 'env')
app.add_event('autodoc-before-process-signature')
app.add_event('autodoc-process-docstring')
app.add_event('autodoc-process-signature')

View File

@ -190,7 +190,7 @@ def update_defvalue(app: Sphinx, obj: Any, bound_method: bool) -> None:
def setup(app: Sphinx) -> dict[str, Any]:
app.add_config_value('autodoc_preserve_defaults', False, True)
app.add_config_value('autodoc_preserve_defaults', False, 'env')
app.connect('autodoc-before-process-signature', update_defvalue)
return {

View File

@ -162,7 +162,7 @@ class FakeDirective(DocumenterBridge):
settings = Struct(tab_width=8)
document = Struct(settings=settings)
app = FakeApplication()
app.config.add('autodoc_class_signature', 'mixed', True, None)
app.config.add('autodoc_class_signature', 'mixed', 'env', None)
env = BuildEnvironment(app) # type: ignore[arg-type]
state = Struct(document=document)
super().__init__(env, None, Options(), 0, state)
@ -835,13 +835,13 @@ def setup(app: Sphinx) -> dict[str, Any]:
app.add_directive('autosummary', Autosummary)
app.add_role('autolink', AutoLink())
app.connect('builder-inited', process_generate_options)
app.add_config_value('autosummary_context', {}, True)
app.add_config_value('autosummary_context', {}, 'env')
app.add_config_value('autosummary_filename_map', {}, 'html')
app.add_config_value('autosummary_generate', True, True, [bool, list])
app.add_config_value('autosummary_generate_overwrite', True, False)
app.add_config_value('autosummary_generate', True, 'env', [bool, list])
app.add_config_value('autosummary_generate_overwrite', True, '')
app.add_config_value('autosummary_mock_imports',
lambda config: config.autodoc_mock_imports, 'env')
app.add_config_value('autosummary_imported_members', [], False, [bool])
app.add_config_value('autosummary_imported_members', [], '', [bool])
app.add_config_value('autosummary_ignore_module_all', True, 'env', bool)
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}

View File

@ -71,8 +71,8 @@ class DummyApplication:
self._warncount = 0
self.warningiserror = False
self.config.add('autosummary_context', {}, True, None)
self.config.add('autosummary_filename_map', {}, True, None)
self.config.add('autosummary_context', {}, 'env', None)
self.config.add('autosummary_filename_map', {}, 'env', None)
self.config.add('autosummary_ignore_module_all', True, 'env', bool)
self.config.init_values()

View File

@ -389,16 +389,16 @@ class CoverageBuilder(Builder):
def setup(app: Sphinx) -> dict[str, Any]:
app.add_builder(CoverageBuilder)
app.add_config_value('coverage_ignore_modules', [], False)
app.add_config_value('coverage_ignore_functions', [], False)
app.add_config_value('coverage_ignore_classes', [], False)
app.add_config_value('coverage_ignore_pyobjects', [], False)
app.add_config_value('coverage_c_path', [], False)
app.add_config_value('coverage_c_regexes', {}, False)
app.add_config_value('coverage_ignore_c_items', {}, False)
app.add_config_value('coverage_write_headline', True, False)
app.add_config_value('coverage_statistics_to_report', True, False, (bool,))
app.add_config_value('coverage_statistics_to_stdout', True, False, (bool,))
app.add_config_value('coverage_skip_undoc_in_source', False, False)
app.add_config_value('coverage_show_missing_items', False, False)
app.add_config_value('coverage_ignore_modules', [], '')
app.add_config_value('coverage_ignore_functions', [], '')
app.add_config_value('coverage_ignore_classes', [], '')
app.add_config_value('coverage_ignore_pyobjects', [], '')
app.add_config_value('coverage_c_path', [], '')
app.add_config_value('coverage_c_regexes', {}, '')
app.add_config_value('coverage_ignore_c_items', {}, '')
app.add_config_value('coverage_write_headline', True, '')
app.add_config_value('coverage_statistics_to_report', True, '', (bool,))
app.add_config_value('coverage_statistics_to_stdout', True, '', (bool,))
app.add_config_value('coverage_skip_undoc_in_source', False, '')
app.add_config_value('coverage_show_missing_items', False, '')
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}

View File

@ -563,13 +563,13 @@ def setup(app: Sphinx) -> dict[str, Any]:
app.add_directive('testoutput', TestoutputDirective)
app.add_builder(DocTestBuilder)
# this config value adds to sys.path
app.add_config_value('doctest_show_successes', True, False, (bool,))
app.add_config_value('doctest_path', [], False)
app.add_config_value('doctest_test_doctest_blocks', 'default', False)
app.add_config_value('doctest_global_setup', '', False)
app.add_config_value('doctest_global_cleanup', '', False)
app.add_config_value('doctest_show_successes', True, '', (bool,))
app.add_config_value('doctest_path', [], '')
app.add_config_value('doctest_test_doctest_blocks', 'default', '')
app.add_config_value('doctest_global_setup', '', '')
app.add_config_value('doctest_global_cleanup', '', '')
app.add_config_value(
'doctest_default_flags',
doctest.DONT_ACCEPT_TRUE_FOR_1 | doctest.ELLIPSIS | doctest.IGNORE_EXCEPTION_DETAIL,
False)
'')
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}

View File

@ -487,8 +487,8 @@ def setup(app: Sphinx) -> dict[str, Any]:
man=(skip, None),
texinfo=(texinfo_visit_inheritance_diagram, None))
app.add_directive('inheritance-diagram', InheritanceDiagram)
app.add_config_value('inheritance_graph_attrs', {}, False)
app.add_config_value('inheritance_node_attrs', {}, False)
app.add_config_value('inheritance_edge_attrs', {}, False)
app.add_config_value('inheritance_alias', {}, False)
app.add_config_value('inheritance_graph_attrs', {}, '')
app.add_config_value('inheritance_node_attrs', {}, '')
app.add_config_value('inheritance_edge_attrs', {}, '')
app.add_config_value('inheritance_alias', {}, '')
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}

View File

@ -682,10 +682,10 @@ def normalize_intersphinx_mapping(app: Sphinx, config: Config) -> None:
def setup(app: Sphinx) -> dict[str, Any]:
app.add_config_value('intersphinx_mapping', {}, True)
app.add_config_value('intersphinx_cache_limit', 5, False)
app.add_config_value('intersphinx_timeout', None, False)
app.add_config_value('intersphinx_disabled_reftypes', ['std:doc'], True)
app.add_config_value('intersphinx_mapping', {}, 'env')
app.add_config_value('intersphinx_cache_limit', 5, '')
app.add_config_value('intersphinx_timeout', None, '')
app.add_config_value('intersphinx_disabled_reftypes', ['std:doc'], 'env')
app.connect('config-inited', normalize_intersphinx_mapping, priority=800)
app.connect('builder-inited', load_mappings)
app.connect('source-read', install_dispatcher)

View File

@ -2,13 +2,16 @@
from __future__ import annotations
from typing import Any
from typing import TYPE_CHECKING, Any
import sphinx
from sphinx.application import Sphinx
from sphinx.ext.napoleon.docstring import GoogleDocstring, NumpyDocstring
from sphinx.util import inspect
if TYPE_CHECKING:
from sphinx.config import _ConfigRebuild
class Config:
"""Sphinx napoleon extension settings in `conf.py`.
@ -262,7 +265,7 @@ class Config:
but do not have a type in the docstring.
"""
_config_values = {
_config_values: dict[str, tuple[Any, _ConfigRebuild]] = {
'napoleon_google_docstring': (True, 'env'),
'napoleon_numpy_docstring': (True, 'env'),
'napoleon_include_init_with_doc': (False, 'env'),

View File

@ -341,9 +341,9 @@ def collect_pages(app: Sphinx) -> Generator[tuple[str, dict[str, Any], str], Non
def setup(app: Sphinx) -> dict[str, Any]:
app.add_config_value('viewcode_import', None, False)
app.add_config_value('viewcode_enable_epub', False, False)
app.add_config_value('viewcode_follow_imported_members', True, False)
app.add_config_value('viewcode_import', None, '')
app.add_config_value('viewcode_enable_epub', False, '')
app.add_config_value('viewcode_follow_imported_members', True, '')
app.add_config_value('viewcode_line_numbers', False, 'env', (bool,))
app.connect('doctree-read', doctree_read)
app.connect('env-merge-info', env_merge_info)