diff --git a/CHANGES.rst b/CHANGES.rst index ac7e8ce299a..54d18d53960 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -13,6 +13,9 @@ Deprecated Features added -------------- +* Add optional ``description`` argument to + :meth:`~sphinx.application.Sphinx.add_config_value`. + Patch by Chris Sewell. * #11165: Support the `officially recommended`_ ``.jinja`` suffix for template files. Patch by James Addison and Adam Turner diff --git a/sphinx/application.py b/sphinx/application.py index 5ab520b2d16..eb050e4062f 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -527,9 +527,11 @@ def add_builder(self, builder: type[Builder], override: bool = False) -> None: """ self.registry.add_builder(builder, override=override) - # TODO(stephenfin): Describe 'types' parameter - def add_config_value(self, name: str, default: Any, rebuild: _ConfigRebuild, - types: type | Collection[type] | ENUM = ()) -> None: + def add_config_value( + self, name: str, default: Any, rebuild: _ConfigRebuild, + types: type | Collection[type] | ENUM = (), + description: str | None = None, + ) -> None: """Register a configuration value. This is necessary for Sphinx to recognize new values and set default @@ -550,6 +552,7 @@ def add_config_value(self, name: str, default: Any, rebuild: _ConfigRebuild, :param types: The type of configuration value. A list of types can be specified. For example, ``[str]`` is used to describe a configuration that takes string value. + :param description: A short description of the configuration value. .. versionchanged:: 0.4 If the *default* value is a callable, it will be called with the @@ -561,9 +564,12 @@ def add_config_value(self, name: str, default: Any, rebuild: _ConfigRebuild, Changed *rebuild* from a simple boolean (equivalent to ``''`` or ``'env'``) to a string. However, booleans are still accepted and converted internally. + + .. versionadded:: 7.4 + The *description* parameter. """ logger.debug('[app] adding config value: %r', (name, default, rebuild, types)) - self.config.add(name, default, rebuild, types) + self.config.add(name, default, rebuild, types, description) def add_event(self, name: str) -> None: """Register an event called *name*. diff --git a/sphinx/config.py b/sphinx/config.py index 7f1138025bc..cd669033b01 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -94,20 +94,23 @@ def match(self, value: str | list | tuple) -> bool: _OptValidTypes = Union[tuple[()], tuple[type, ...], frozenset[type], ENUM] +_DescriptionType = Union[str, None] class _Opt: - __slots__ = 'default', 'rebuild', 'valid_types' + __slots__ = 'default', 'rebuild', 'valid_types', 'description' default: Any rebuild: _ConfigRebuild valid_types: _OptValidTypes + description: _DescriptionType def __init__( self, default: Any, rebuild: _ConfigRebuild, valid_types: _OptValidTypes, + description: _DescriptionType = None, ) -> None: """Configuration option type for Sphinx. @@ -120,52 +123,56 @@ def __init__( super().__setattr__('default', default) super().__setattr__('rebuild', rebuild) super().__setattr__('valid_types', valid_types) + super().__setattr__('description', description) def __repr__(self) -> str: return ( f'{self.__class__.__qualname__}(' f'default={self.default!r}, ' f'rebuild={self.rebuild!r}, ' - f'valid_types={self.valid_types!r})' + f'valid_types={self.rebuild!r}, ' + f'description={self.description!r})' ) def __eq__(self, other: object) -> bool: if isinstance(other, _Opt): - self_tpl = (self.default, self.rebuild, self.valid_types) - other_tpl = (other.default, other.rebuild, other.valid_types) + self_tpl = (self.default, self.rebuild, self.valid_types, self.description) + other_tpl = (other.default, other.rebuild, other.valid_types, self.description) return self_tpl == other_tpl return NotImplemented def __lt__(self, other: _Opt) -> bool: if self.__class__ is other.__class__: - self_tpl = (self.default, self.rebuild, self.valid_types) - other_tpl = (other.default, other.rebuild, other.valid_types) + self_tpl = (self.default, self.rebuild, self.valid_types, self.description) + other_tpl = (other.default, other.rebuild, other.valid_types, self.description) return self_tpl > other_tpl return NotImplemented def __hash__(self) -> int: - return hash((self.default, self.rebuild, self.valid_types)) + return hash((self.default, self.rebuild, self.valid_types, self.description)) def __setattr__(self, key: str, value: Any) -> None: - if key in {'default', 'rebuild', 'valid_types'}: + if key in {'default', 'rebuild', 'valid_types', 'description'}: msg = f'{self.__class__.__name__!r} object does not support assignment to {key!r}' raise TypeError(msg) super().__setattr__(key, value) def __delattr__(self, key: str) -> None: - if key in {'default', 'rebuild', 'valid_types'}: + if key in {'default', 'rebuild', 'valid_types', 'description'}: msg = f'{self.__class__.__name__!r} object does not support deletion of {key!r}' raise TypeError(msg) super().__delattr__(key) - def __getstate__(self) -> tuple[Any, _ConfigRebuild, _OptValidTypes]: - return self.default, self.rebuild, self.valid_types + def __getstate__(self) -> tuple[Any, _ConfigRebuild, _OptValidTypes, _DescriptionType]: + return self.default, self.rebuild, self.valid_types, self.description - def __setstate__(self, state: tuple[Any, _ConfigRebuild, _OptValidTypes]) -> None: - default, rebuild, valid_types = state + def __setstate__( + self, state: tuple[Any, _ConfigRebuild, _OptValidTypes, _DescriptionType]) -> None: + default, rebuild, valid_types, description = state super().__setattr__('default', default) super().__setattr__('rebuild', rebuild) super().__setattr__('valid_types', valid_types) + super().__setattr__('description', description) def __getitem__(self, item: int | slice) -> Any: warnings.warn( @@ -445,7 +452,8 @@ def __iter__(self) -> Iterator[ConfigValue]: yield ConfigValue(name, getattr(self, name), opt.rebuild) def add(self, name: str, default: Any, rebuild: _ConfigRebuild, - types: type | Collection[type] | ENUM) -> None: + types: type | Collection[type] | ENUM, + description: str | None = None) -> None: if name in self._options: raise ExtensionError(__('Config value %r already present') % name) @@ -455,7 +463,7 @@ def add(self, name: str, default: Any, rebuild: _ConfigRebuild, # standardise valid_types valid_types = _validate_valid_types(types) - self._options[name] = _Opt(default, rebuild, valid_types) + self._options[name] = _Opt(default, rebuild, valid_types, description) def filter(self, rebuild: Set[_ConfigRebuild]) -> Iterator[ConfigValue]: if isinstance(rebuild, str):