mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add optional description argument to app.add_config_value (#12549)
Sphinx (+ extensions) has a lot of available configuration variables for users, allowing for the co-location of a short description on the configuration value, can be utilised by external tools to provide better sphinx authoring support. Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -527,9 +527,11 @@ class Sphinx:
|
||||
"""
|
||||
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 @@ class Sphinx:
|
||||
: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 @@ class Sphinx:
|
||||
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*.
|
||||
|
||||
@@ -94,20 +94,23 @@ class ENUM:
|
||||
|
||||
|
||||
_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 @@ class _Opt:
|
||||
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 @@ class Config:
|
||||
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 @@ class Config:
|
||||
|
||||
# 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):
|
||||
|
||||
Reference in New Issue
Block a user