diff --git a/sphinx/ext/autodoc/_docstrings.py b/sphinx/ext/autodoc/_docstrings.py index 178b19fde6e..a1b1c84fd64 100644 --- a/sphinx/ext/autodoc/_docstrings.py +++ b/sphinx/ext/autodoc/_docstrings.py @@ -25,8 +25,8 @@ from sphinx.events import EventManager from sphinx.ext.autodoc._directive_options import _AutoDocumenterOptions - from sphinx.ext.autodoc._importer import _AttrGetter from sphinx.ext.autodoc._property_types import _ItemProperties + from sphinx.ext.autodoc._shared import _AttrGetter logger = logging.getLogger('sphinx.ext.autodoc') diff --git a/sphinx/ext/autodoc/_generate.py b/sphinx/ext/autodoc/_generate.py index 5e3d75b60da..6c47e811b9b 100644 --- a/sphinx/ext/autodoc/_generate.py +++ b/sphinx/ext/autodoc/_generate.py @@ -9,6 +9,7 @@ from sphinx.ext.autodoc._member_finder import _gather_members from sphinx.ext.autodoc._renderer import _add_content, _directive_header_lines from sphinx.ext.autodoc._sentinels import ALL +from sphinx.ext.autodoc._shared import _get_render_mode from sphinx.ext.autodoc.mock import ismock from sphinx.locale import _, __ from sphinx.pycode import ModuleAnalyzer @@ -17,14 +18,12 @@ if TYPE_CHECKING: from collections.abc import Iterator, Mapping, MutableSet - from typing import Literal - from sphinx.config import Config from sphinx.environment import _CurrentDocument from sphinx.events import EventManager from sphinx.ext.autodoc._directive_options import _AutoDocumenterOptions - from sphinx.ext.autodoc._importer import _AttrGetter from sphinx.ext.autodoc._property_types import _ItemProperties + from sphinx.ext.autodoc._shared import _AttrGetter, _AutodocConfig from sphinx.util.typing import _RestifyMode logger = logging.getLogger('sphinx.ext.autodoc') @@ -36,7 +35,7 @@ def _generate_directives( check_module: bool = False, all_members: bool = False, *, - config: Config, + config: _AutodocConfig, current_document: _CurrentDocument, events: EventManager, get_attr: _AttrGetter, @@ -154,7 +153,7 @@ def _add_directive_lines( *, more_content: StringList | None, is_final: bool, - config: Config, + config: _AutodocConfig, indent: str, options: _AutoDocumenterOptions, props: _ItemProperties, @@ -180,8 +179,8 @@ def _add_directive_lines( # add alias information, if applicable lines = _body_alias_lines( - typehints_format=config.autodoc_typehints_format, - python_display_short_literal_types=config.python_display_short_literal_types, + render_mode=_get_render_mode(config.autodoc_typehints_format), + short_literals=config.python_display_short_literal_types, props=props, ) alias_lines = StringList(list(lines), source='') @@ -204,7 +203,7 @@ def _document_members( all_members: bool, analyzer_order: dict[str, int], attr_docs: dict[tuple[str, str], list[str]], - config: Config, + config: _AutodocConfig, current_document: _CurrentDocument, events: EventManager, get_attr: _AttrGetter, @@ -276,10 +275,7 @@ def _document_members( def _body_alias_lines( - *, - props: _ItemProperties, - typehints_format: Literal['fully-qualified', 'short'], - python_display_short_literal_types: bool, + *, props: _ItemProperties, render_mode: _RestifyMode, short_literals: bool ) -> Iterator[str]: """Add content from docstrings, attribute documentation and user.""" if props.obj_type in {'data', 'attribute'}: @@ -287,11 +283,9 @@ def _body_alias_lines( assert isinstance(props, _AssignStatementProperties) - mode = _get_render_mode(typehints_format) - # Support for documenting GenericAliases if props._obj_is_generic_alias: - alias = restify(props._obj, mode=mode) + alias = restify(props._obj, mode=render_mode) yield _('alias of %s') % alias yield '' return @@ -303,27 +297,25 @@ def _body_alias_lines( assert isinstance(props, _ClassDefProperties) obj = props._obj - mode = _get_render_mode(typehints_format) if props._obj_is_new_type: - supertype = restify(obj.__supertype__, mode=mode) + supertype = restify(obj.__supertype__, mode=render_mode) yield _('alias of %s') % supertype yield '' return if props._obj_is_typevar: - short_literals = python_display_short_literal_types attrs = [ repr(obj.__name__), *( stringify_annotation( - constraint, mode, short_literals=short_literals + constraint, render_mode, short_literals=short_literals ) for constraint in obj.__constraints__ ), ] if obj.__bound__: - attrs.append(rf'bound=\ {restify(obj.__bound__, mode=mode)}') + attrs.append(rf'bound=\ {restify(obj.__bound__, mode=render_mode)}') if obj.__covariant__: attrs.append('covariant=True') if obj.__contravariant__: @@ -345,7 +337,7 @@ def _body_alias_lines( if class_var_doc_comment: return - alias = restify(obj, mode=mode) + alias = restify(obj, mode=render_mode) yield _('alias of %s') % alias return @@ -367,11 +359,3 @@ def _docstring_source_name(*, props: _ItemProperties, source: str) -> str: if source: return f'{source}:docstring of {fullname}' return f'docstring of {fullname}' - - -def _get_render_mode( - typehints_format: Literal['fully-qualified', 'short'], -) -> _RestifyMode: - if typehints_format == 'short': - return 'smart' - return 'fully-qualified-except-typing' diff --git a/sphinx/ext/autodoc/_importer.py b/sphinx/ext/autodoc/_importer.py index 0086d1deb91..8b7d49c76cb 100644 --- a/sphinx/ext/autodoc/_importer.py +++ b/sphinx/ext/autodoc/_importer.py @@ -23,7 +23,7 @@ from sphinx.util.typing import get_type_hints if TYPE_CHECKING: - from collections.abc import Sequence + from collections.abc import Mapping, Sequence from importlib.machinery import ModuleSpec from types import ModuleType from typing import Any, Protocol @@ -71,11 +71,11 @@ def __repr__(self) -> str: def _import_object( *, get_attr: _AttrGetter = safe_getattr, - mock_imports: list[str], + mock_imports: Sequence[str], module_name: str, obj_path: Sequence[str], obj_type: _AutodocObjType, - type_aliases: dict[str, Any] | None, + type_aliases: Mapping[str, str] | None, ) -> _ImportedObject | None: """Import the module and get the object to document.""" try: @@ -310,8 +310,8 @@ def _import_data_declaration( *, module_name: str, obj_path: Sequence[str], - mock_imports: list[str], - type_aliases: dict[str, Any] | None, + mock_imports: Sequence[str], + type_aliases: Mapping[str, str] | None, ) -> _ImportedObject | None: # annotation only instance variable (PEP-526) try: @@ -333,8 +333,8 @@ def _import_attribute_declaration( *, module_name: str, obj_path: Sequence[str], - mock_imports: list[str], - type_aliases: dict[str, Any] | None, + mock_imports: Sequence[str], + type_aliases: Mapping[str, str] | None, get_attr: _AttrGetter = safe_getattr, ) -> _ImportedObject | None: # Support runtime & uninitialized instance attributes. @@ -424,7 +424,7 @@ def _get_attribute_comment( def _is_uninitialized_instance_attribute( - *, parent: Any, obj_path: Sequence[str], type_aliases: dict[str, Any] | None + *, parent: Any, obj_path: Sequence[str], type_aliases: Mapping[str, str] | None ) -> bool: """Check the subject is an annotation only attribute.""" annotations = get_type_hints(parent, None, type_aliases, include_extras=True) diff --git a/sphinx/ext/autodoc/_loader.py b/sphinx/ext/autodoc/_loader.py index 5b5cd7ffe67..246293855fb 100644 --- a/sphinx/ext/autodoc/_loader.py +++ b/sphinx/ext/autodoc/_loader.py @@ -27,6 +27,7 @@ SLOTS_ATTR, UNINITIALIZED_ATTR, ) +from sphinx.ext.autodoc._shared import _get_render_mode from sphinx.ext.autodoc._signatures import _format_signatures from sphinx.ext.autodoc._type_comments import ( _ensure_annotations_from_type_comments, @@ -42,12 +43,12 @@ from collections.abc import Mapping, MutableSet, Sequence from typing import Any - from sphinx.config import Config from sphinx.environment import _CurrentDocument from sphinx.events import EventManager from sphinx.ext.autodoc._directive_options import _AutoDocumenterOptions - from sphinx.ext.autodoc._importer import _AttrGetter, _ImportedObject + from sphinx.ext.autodoc._importer import _ImportedObject from sphinx.ext.autodoc._property_types import _AutodocFuncProperty, _AutodocObjType + from sphinx.ext.autodoc._shared import _AttrGetter, _AutodocConfig logger = logging.getLogger(__name__) @@ -58,10 +59,8 @@ def _load_object_by_name( *, name: str, objtype: _AutodocObjType, - mock_imports: list[str], - type_aliases: dict[str, Any] | None, current_document: _CurrentDocument, - config: Config, + config: _AutodocConfig, events: EventManager, get_attr: _AttrGetter, options: _AutoDocumenterOptions, @@ -84,10 +83,10 @@ def _load_object_by_name( im = _import_object( module_name=module_name, obj_path=parts, - mock_imports=mock_imports, + mock_imports=config.autodoc_mock_imports, get_attr=get_attr, obj_type=objtype, - type_aliases=type_aliases, + type_aliases=config.autodoc_type_aliases, ) if im is None: # See BuildEnvironment.note_reread() @@ -164,7 +163,7 @@ def _load_object_by_name( def _make_props_from_imported_object( im: _ImportedObject, *, - config: Config, + config: _AutodocConfig, events: EventManager, get_attr: _AttrGetter, module_name: str, @@ -175,6 +174,7 @@ def _make_props_from_imported_object( object_name = im.object_name obj = im.obj obj_properties: set[_AutodocFuncProperty] = set() + render_mode = _get_render_mode(config.autodoc_typehints_format) if objtype == 'module': try: @@ -232,11 +232,7 @@ def _make_props_from_imported_object( SimpleNamespace(), obj_bases, ) - if config.autodoc_typehints_format == 'short': - mode = 'smart' - else: - mode = 'fully-qualified-except-typing' - base_classes = tuple(restify(cls, mode=mode) for cls in obj_bases) # type: ignore[arg-type] + base_classes = tuple(restify(cls, mode=render_mode) for cls in obj_bases) return _ClassDefProperties( obj_type=objtype, # type: ignore[arg-type] @@ -342,15 +338,11 @@ def _make_props_from_imported_object( except ValueError: pass else: - if config.autodoc_typehints_format == 'short': - mode = 'smart' - else: - mode = 'fully-qualified-except-typing' if signature.return_annotation is not Parameter.empty: short_literals = config.python_display_short_literal_types obj_property_type_annotation = stringify_annotation( signature.return_annotation, - mode, # type: ignore[arg-type] + render_mode, short_literals=short_literals, ) @@ -378,16 +370,10 @@ def _make_props_from_imported_object( config.autodoc_type_aliases, include_extras=True, ) - if config.autodoc_typehints_format == 'short': - mode = 'smart' - else: - mode = 'fully-qualified-except-typing' if parts[-1] in annotations: short_literals = config.python_display_short_literal_types type_annotation = stringify_annotation( - annotations[parts[-1]], - mode, # type: ignore[arg-type] - short_literals=short_literals, + annotations[parts[-1]], render_mode, short_literals=short_literals ) else: type_annotation = None @@ -436,16 +422,10 @@ def _make_props_from_imported_object( config.autodoc_type_aliases, include_extras=True, ) - if config.autodoc_typehints_format == 'short': - mode = 'smart' - else: - mode = 'fully-qualified-except-typing' if parts[-1] in annotations: short_literals = config.python_display_short_literal_types type_annotation = stringify_annotation( - annotations[parts[-1]], - mode, # type: ignore[arg-type] - short_literals=short_literals, + annotations[parts[-1]], render_mode, short_literals=short_literals ) else: type_annotation = None @@ -485,15 +465,9 @@ def _make_props_from_imported_object( parts = tuple(bases) + parts module_name = obj_module_name - if config.autodoc_typehints_format == 'short': - mode = 'smart' - else: - mode = 'fully-qualified-except-typing' short_literals = config.python_display_short_literal_types ann = stringify_annotation( - obj.__value__, - mode, # type: ignore[arg-type] - short_literals=short_literals, + obj.__value__, render_mode, short_literals=short_literals ) return _TypeStatementProperties( obj_type=objtype, diff --git a/sphinx/ext/autodoc/_member_finder.py b/sphinx/ext/autodoc/_member_finder.py index 2d7e240aa45..8130ee5b7c0 100644 --- a/sphinx/ext/autodoc/_member_finder.py +++ b/sphinx/ext/autodoc/_member_finder.py @@ -32,11 +32,9 @@ from collections.abc import Iterable, Iterator, Mapping, MutableSet, Sequence, Set from typing import Any, Literal - from sphinx.config import Config from sphinx.environment import _CurrentDocument from sphinx.events import EventManager from sphinx.ext.autodoc._directive_options import _AutoDocumenterOptions - from sphinx.ext.autodoc._importer import _AttrGetter from sphinx.ext.autodoc._property_types import _AutodocObjType, _ItemProperties from sphinx.ext.autodoc._sentinels import ( ALL_T, @@ -44,6 +42,7 @@ INSTANCE_ATTR_T, SLOTS_ATTR_T, ) + from sphinx.ext.autodoc._shared import _AttrGetter, _AutodocConfig logger = logging.getLogger('sphinx.ext.autodoc') special_member_re = re.compile(r'^__\S+__$') @@ -94,7 +93,7 @@ def _gather_members( indent: str, analyzer_order: dict[str, int], attr_docs: dict[tuple[str, str], list[str]], - config: Config, + config: _AutodocConfig, current_document: _CurrentDocument, events: EventManager, get_attr: _AttrGetter, @@ -176,8 +175,6 @@ def _gather_members( member_props = _load_object_by_name( name=full_name, objtype=obj_type, - mock_imports=config.autodoc_mock_imports, - type_aliases=config.autodoc_type_aliases, current_document=current_document, config=config, events=events, diff --git a/sphinx/ext/autodoc/_shared.py b/sphinx/ext/autodoc/_shared.py new file mode 100644 index 00000000000..18b0062a3ff --- /dev/null +++ b/sphinx/ext/autodoc/_shared.py @@ -0,0 +1,158 @@ +"""Shared utilities for autodoc that don't have a better home.""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +from sphinx.util.inspect import safe_getattr + +if TYPE_CHECKING: + from collections.abc import Callable, Mapping, Sequence + from typing import Any, Literal, NoReturn, Protocol + + from sphinx.config import Config + from sphinx.util.typing import _RestifyMode + + class _AttrGetter(Protocol): # NoQA: PYI046 + def __call__(self, obj: Any, name: str, default: Any = ..., /) -> Any: ... + + +class _AutodocConfig: + __slots__ = ( + 'autoclass_content', + 'autodoc_class_signature', + 'autodoc_default_options', + 'autodoc_docstring_signature', + 'autodoc_inherit_docstrings', + 'autodoc_member_order', + 'autodoc_mock_imports', + 'autodoc_preserve_defaults', + 'autodoc_type_aliases', + 'autodoc_typehints', + 'autodoc_typehints_description_target', + 'autodoc_typehints_format', + 'autodoc_use_type_comments', + # non-autodoc config + 'python_display_short_literal_types', + 'strip_signature_backslash', + ) + + autoclass_content: Literal['both', 'class', 'init'] + autodoc_class_signature: Literal['mixed', 'separated'] + autodoc_default_options: Mapping[str, str | bool] + autodoc_docstring_signature: bool + autodoc_inherit_docstrings: bool + autodoc_member_order: Literal['alphabetical', 'bysource', 'groupwise'] + autodoc_mock_imports: Sequence[str] + autodoc_preserve_defaults: bool + autodoc_type_aliases: Mapping[str, str] + autodoc_typehints: Literal['signature', 'description', 'none', 'both'] + autodoc_typehints_description_target: Literal[ + 'all', 'documented', 'documented_params' + ] + autodoc_typehints_format: Literal['fully-qualified', 'short'] + autodoc_use_type_comments: bool + # non-autodoc config + python_display_short_literal_types: bool + strip_signature_backslash: bool + + @classmethod + def from_config(cls, config: Config) -> _AutodocConfig: + return cls( + autoclass_content=config.autoclass_content, + autodoc_class_signature=config.autodoc_class_signature, + autodoc_default_options=config.autodoc_default_options, + autodoc_docstring_signature=config.autodoc_docstring_signature, + autodoc_inherit_docstrings=config.autodoc_inherit_docstrings, + autodoc_member_order=config.autodoc_member_order, + autodoc_mock_imports=config.autodoc_mock_imports, + autodoc_preserve_defaults=config.autodoc_preserve_defaults, + autodoc_type_aliases=config.autodoc_type_aliases, + autodoc_typehints=config.autodoc_typehints, + autodoc_typehints_description_target=config.autodoc_typehints_description_target, + autodoc_typehints_format=config.autodoc_typehints_format, + autodoc_use_type_comments=config.autodoc_use_type_comments, + python_display_short_literal_types=config.python_display_short_literal_types, + strip_signature_backslash=config.strip_signature_backslash, + ) + + def __init__( + self, + *, + autoclass_content: Literal['both', 'class', 'init'] = 'class', + autodoc_class_signature: Literal['mixed', 'separated'] = 'mixed', + autodoc_default_options: Mapping[str, str | bool] = {}.keys().mapping, + autodoc_docstring_signature: bool = True, + autodoc_inherit_docstrings: bool = True, + autodoc_member_order: Literal['alphabetical', 'bysource', 'groupwise'] = ( + 'alphabetical' + ), + autodoc_mock_imports: Sequence[str] = (), + autodoc_preserve_defaults: bool = False, + autodoc_type_aliases: Mapping[str, str] = {}.keys().mapping, + autodoc_typehints: Literal[ + 'signature', 'description', 'none', 'both' + ] = 'signature', + autodoc_typehints_description_target: Literal[ + 'all', 'documented', 'documented_params' + ] = 'all', + autodoc_typehints_format: Literal['fully-qualified', 'short'] = 'short', + autodoc_use_type_comments: bool = True, + python_display_short_literal_types: bool = False, + strip_signature_backslash: bool = False, + ) -> None: + for name in self.__slots__: + super().__setattr__(name, locals()[name]) + + def __repr__(self) -> str: + items = ((name, getattr(self, name)) for name in self.__slots__) + args = ', '.join(f'{name}={value!r}' for name, value in items) + return f'_AutodocConfig({args})' + + def __setattr__(self, key: str, value: Any) -> NoReturn: + msg = f'{self.__class__.__name__} is immutable' + raise AttributeError(msg) + + def __delattr__(self, key: str) -> NoReturn: + msg = f'{self.__class__.__name__} is immutable' + raise AttributeError(msg) + + +class _AutodocAttrGetter: + """getattr() override for types such as Zope interfaces.""" + + _attr_getters: Sequence[tuple[type, Callable[[Any, str, Any], Any]]] + + __slots__ = ('_attr_getters',) + + def __init__( + self, attr_getters: dict[type, Callable[[Any, str, Any], Any]], / + ) -> None: + super().__setattr__('_attr_getters', tuple(attr_getters.items())) + + def __call__(self, obj: Any, name: str, *defargs: Any) -> Any: + for typ, func in self._attr_getters: + if isinstance(obj, typ): + return func(obj, name, *defargs) + + return safe_getattr(obj, name, *defargs) + + def __repr__(self) -> str: + return f'_AutodocAttrGetter({dict(self._attr_getters)!r})' + + def __setattr__(self, key: str, value: Any) -> NoReturn: + msg = f'{self.__class__.__name__} is immutable' + raise AttributeError(msg) + + def __delattr__(self, key: str) -> NoReturn: + msg = f'{self.__class__.__name__} is immutable' + raise AttributeError(msg) + + +def _get_render_mode( + typehints_format: Literal['fully-qualified', 'short'], + /, +) -> _RestifyMode: + if typehints_format == 'short': + return 'smart' + return 'fully-qualified-except-typing' diff --git a/sphinx/ext/autodoc/_signatures.py b/sphinx/ext/autodoc/_signatures.py index c70d0485d94..0dcf669b09c 100644 --- a/sphinx/ext/autodoc/_signatures.py +++ b/sphinx/ext/autodoc/_signatures.py @@ -26,11 +26,10 @@ from collections.abc import Callable, Mapping from typing import Any, TypeAlias - from sphinx.config import Config from sphinx.events import EventManager from sphinx.ext.autodoc._directive_options import _AutoDocumenterOptions - from sphinx.ext.autodoc._importer import _AttrGetter from sphinx.ext.autodoc._property_types import _ItemProperties + from sphinx.ext.autodoc._shared import _AttrGetter, _AutodocConfig _FormattedSignature: TypeAlias = tuple[str, str] @@ -40,7 +39,7 @@ def _format_signatures( *, autodoc_annotations: dict[str, dict[str, str]], - config: Config, + config: _AutodocConfig, docstrings: list[list[str]] | None, events: EventManager, get_attr: _AttrGetter, @@ -110,9 +109,9 @@ def _format_signatures( autodoc_annotations=autodoc_annotations, name=props.full_name, obj=props._obj, - short_literals=config.python_display_short_literal_types, + short_literals=kwargs.get('short_literals', False), type_aliases=config.autodoc_type_aliases, - typehints_format=config.autodoc_typehints_format, + unqualified_typehints=kwargs.get('unqualified_typehints', False), ) if result := events.emit_firstresult( 'autodoc-process-signature', @@ -406,7 +405,7 @@ def _extract_signatures_from_docstrings( def _extract_signature_from_object( - config: Config, + config: _AutodocConfig, events: EventManager, get_attr: _AttrGetter, parent: Any, @@ -599,7 +598,11 @@ def get_user_defined_function_or_method(obj: Any, attr: str) -> Any: def _annotate_to_first_argument( - func: Callable[..., Any], typ: type, *, config: Config, props: _ItemProperties + func: Callable[..., Any], + typ: type, + *, + config: _AutodocConfig, + props: _ItemProperties, ) -> Callable[..., Any] | None: """Annotate type hint to the first argument of function if needed.""" try: diff --git a/sphinx/ext/autodoc/directive.py b/sphinx/ext/autodoc/directive.py index 90e7fc5da7b..d1d80f74b2b 100644 --- a/sphinx/ext/autodoc/directive.py +++ b/sphinx/ext/autodoc/directive.py @@ -10,14 +10,13 @@ ) from sphinx.ext.autodoc._generate import _generate_directives from sphinx.ext.autodoc._loader import _load_object_by_name +from sphinx.ext.autodoc._shared import _AutodocAttrGetter, _AutodocConfig from sphinx.util import logging from sphinx.util.docutils import SphinxDirective, switch_source_input -from sphinx.util.inspect import safe_getattr from sphinx.util.parsing import nested_parse_to_nodes if TYPE_CHECKING: - from collections.abc import Callable, Sequence - from typing import Any, NoReturn + from collections.abc import Callable from docutils.nodes import Node from docutils.parsers.rst.states import RSTState @@ -26,37 +25,6 @@ logger = logging.getLogger(__name__) -class _AutodocAttrGetter: - """getattr() override for types such as Zope interfaces.""" - - _attr_getters: Sequence[tuple[type, Callable[[Any, str, Any], Any]]] - - __slots__ = ('_attr_getters',) - - def __init__( - self, attr_getters: dict[type, Callable[[Any, str, Any], Any]], / - ) -> None: - super().__setattr__('_attr_getters', tuple(attr_getters.items())) - - def __call__(self, obj: Any, name: str, *defargs: Any) -> Any: - for typ, func in self._attr_getters: - if isinstance(obj, typ): - return func(obj, name, *defargs) - - return safe_getattr(obj, name, *defargs) - - def __repr__(self) -> str: - return f'_AutodocAttrGetter({dict(self._attr_getters)!r})' - - def __setattr__(self, key: str, value: Any) -> NoReturn: - msg = f'{self.__class__.__name__} is immutable' - raise AttributeError(msg) - - def __delattr__(self, key: str) -> NoReturn: - msg = f'{self.__class__.__name__} is immutable' - raise AttributeError(msg) - - class DummyOptionSpec(dict[str, 'Callable[[str], str]']): # NoQA: FURB189 """An option_spec allows any options.""" @@ -137,7 +105,7 @@ def run(self) -> list[Node]: get_attr = _AutodocAttrGetter(registry.autodoc_attrgetters) name = self.arguments[0] env = self.env - config = env.config + config = _AutodocConfig.from_config(env.config) current_document = env.current_document events = env.events ref_context = env.ref_context @@ -146,8 +114,6 @@ def run(self) -> list[Node]: props = _load_object_by_name( name=name, objtype=objtype, # type: ignore[arg-type] - mock_imports=config.autodoc_mock_imports, - type_aliases=config.autodoc_type_aliases, current_document=current_document, config=config, events=events, diff --git a/sphinx/ext/autodoc/mock.py b/sphinx/ext/autodoc/mock.py index 236174a62f9..11c30bcb88b 100644 --- a/sphinx/ext/autodoc/mock.py +++ b/sphinx/ext/autodoc/mock.py @@ -129,7 +129,7 @@ def exec_module(self, module: ModuleType) -> None: class MockFinder(MetaPathFinder): """A finder for mocking.""" - def __init__(self, modnames: list[str]) -> None: + def __init__(self, modnames: Sequence[str]) -> None: super().__init__() self.modnames = modnames self.loader = MockLoader(self) @@ -155,7 +155,7 @@ def invalidate_caches(self) -> None: @contextlib.contextmanager -def mock(modnames: list[str]) -> Iterator[None]: +def mock(modnames: Sequence[str]) -> Iterator[None]: """Insert mock modules during context:: with mock(['target.module.name']): diff --git a/sphinx/ext/autodoc/typehints.py b/sphinx/ext/autodoc/typehints.py index 2b58718d7ff..2b3c3e48e3c 100644 --- a/sphinx/ext/autodoc/typehints.py +++ b/sphinx/ext/autodoc/typehints.py @@ -13,7 +13,7 @@ if TYPE_CHECKING: from collections.abc import Iterable, Mapping - from typing import Any, Literal + from typing import Any from docutils.nodes import Element @@ -29,11 +29,11 @@ def _record_typehints( obj: Any, short_literals: bool, type_aliases: Mapping[str, str] | None, - typehints_format: Literal['fully-qualified', 'short'], + unqualified_typehints: bool, ) -> None: """Record type hints to env object.""" mode: _StringifyMode - if typehints_format == 'short': + if unqualified_typehints: mode = 'smart' else: mode = 'fully-qualified' diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 631d5b70a0d..dedc203d919 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -71,7 +71,7 @@ from sphinx.ext.autodoc._loader import _load_object_by_name from sphinx.ext.autodoc._member_finder import _best_object_type_for_member from sphinx.ext.autodoc._sentinels import INSTANCE_ATTR -from sphinx.ext.autodoc.directive import _AutodocAttrGetter +from sphinx.ext.autodoc._shared import _AutodocAttrGetter, _AutodocConfig from sphinx.ext.autodoc.mock import mock from sphinx.locale import __ from sphinx.pycode import ModuleAnalyzer @@ -303,7 +303,7 @@ def get_items(self, names: list[str]) -> list[tuple[str, str | None, str, str]]: document_settings = self.state.document.settings env = self.env - config = env.config + config = _AutodocConfig.from_config(env.config) current_document = env.current_document events = env.events get_attr = _AutodocAttrGetter(env._registry.autodoc_attrgetters) @@ -345,8 +345,6 @@ def get_items(self, names: list[str]) -> list[tuple[str, str | None, str, str]]: props = _load_object_by_name( name=full_name, objtype=obj_type, - mock_imports=config.autodoc_mock_imports, - type_aliases=config.autodoc_type_aliases, current_document=current_document, config=config, events=events, diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index 4530cbc5824..d824a44157a 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -772,7 +772,7 @@ def signature( def evaluate_signature( sig: Signature, globalns: dict[str, Any] | None = None, - localns: dict[str, Any] | None = None, + localns: Mapping[str, Any] | None = None, ) -> Signature: """Evaluate unresolved type annotations in a signature object.""" if globalns is None: @@ -796,7 +796,7 @@ def evaluate_signature( def _evaluate_forwardref( ref: ForwardRef, globalns: dict[str, Any] | None, - localns: dict[str, Any] | None, + localns: Mapping[str, Any] | None, ) -> Any: """Evaluate a forward reference.""" if sys.version_info[:2] >= (3, 14): @@ -818,7 +818,7 @@ def _evaluate_forwardref( def _evaluate( annotation: Any, globalns: dict[str, Any], - localns: dict[str, Any], + localns: Mapping[str, Any], ) -> Any: """Evaluate unresolved type annotation.""" try: diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py index 3d65cdd3b22..cedffb46a02 100644 --- a/sphinx/util/typing.py +++ b/sphinx/util/typing.py @@ -193,7 +193,7 @@ class ExtensionMetadata(typing.TypedDict, total=False): def get_type_hints( obj: Any, globalns: dict[str, Any] | None = None, - localns: dict[str, Any] | None = None, + localns: Mapping[str, Any] | None = None, include_extras: bool = False, ) -> dict[str, Any]: """Return a dictionary containing type hints for a function, method, module or class diff --git a/tests/test_ext_autodoc/autodoc_util.py b/tests/test_ext_autodoc/autodoc_util.py index 233ec1829dc..0a05893c778 100644 --- a/tests/test_ext_autodoc/autodoc_util.py +++ b/tests/test_ext_autodoc/autodoc_util.py @@ -9,6 +9,7 @@ ) from sphinx.ext.autodoc._generate import _generate_directives from sphinx.ext.autodoc._loader import _load_object_by_name +from sphinx.ext.autodoc._shared import _AutodocConfig from sphinx.util.inspect import safe_getattr if TYPE_CHECKING: @@ -33,7 +34,7 @@ def do_autodoc( options=options, ) - config = app.config + config = _AutodocConfig.from_config(app.config) current_document = app.env.current_document events = app.events ref_context = app.env.ref_context @@ -41,8 +42,6 @@ def do_autodoc( props = _load_object_by_name( name=name, objtype=obj_type, - mock_imports=config.autodoc_mock_imports, - type_aliases=config.autodoc_type_aliases, current_document=current_document, config=config, events=events, diff --git a/tests/test_ext_autodoc/test_ext_autodoc.py b/tests/test_ext_autodoc/test_ext_autodoc.py index 69a0ce9a38f..29381dec652 100644 --- a/tests/test_ext_autodoc/test_ext_autodoc.py +++ b/tests/test_ext_autodoc/test_ext_autodoc.py @@ -26,7 +26,7 @@ from sphinx.ext.autodoc._loader import _load_object_by_name from sphinx.ext.autodoc._property_types import _ItemProperties from sphinx.ext.autodoc._sentinels import ALL -from sphinx.ext.autodoc.directive import _AutodocAttrGetter +from sphinx.ext.autodoc._shared import _AutodocAttrGetter, _AutodocConfig from sphinx.util.inspect import safe_getattr from tests.test_ext_autodoc.autodoc_util import do_autodoc @@ -73,7 +73,7 @@ def get_docstring_lines(obj_type, obj, *, config): @pytest.mark.sphinx('html', testroot='root') def test_get_docstring_lines(app): - config = app.config + config = _AutodocConfig.from_config(app.config) # objects without docstring def f(): @@ -193,7 +193,7 @@ def _special_getattr(obj, attr_name, *defargs): def _assert_getter_works(app, get_attr, options, objtype, name, *attrs): env = app.env - config = app.config + config = _AutodocConfig.from_config(app.config) current_document = env.current_document events = app.events ref_context = env.ref_context @@ -203,8 +203,6 @@ def _assert_getter_works(app, get_attr, options, objtype, name, *attrs): props = _load_object_by_name( name=name, objtype=objtype, - mock_imports=config.autodoc_mock_imports, - type_aliases=config.autodoc_type_aliases, current_document=current_document, config=config, events=events, diff --git a/tests/test_ext_autodoc/test_ext_autodoc_signatures.py b/tests/test_ext_autodoc/test_ext_autodoc_signatures.py index 277aa71d83a..75402d03fb8 100644 --- a/tests/test_ext_autodoc/test_ext_autodoc_signatures.py +++ b/tests/test_ext_autodoc/test_ext_autodoc_signatures.py @@ -12,6 +12,7 @@ _ClassDefProperties, _FunctionDefProperties, ) +from sphinx.ext.autodoc._shared import _AutodocConfig from sphinx.ext.autodoc._signatures import _format_signatures from sphinx.util.inspect import safe_getattr @@ -41,7 +42,7 @@ def format_sig( args: str | None = None, retann: str | None = None, ) -> tuple[str, str] | tuple[()]: - config = app.config + config = _AutodocConfig.from_config(app.config) events = app.events options = _AutoDocumenterOptions() @@ -374,10 +375,11 @@ def func(x: int, y: int) -> int: # type: ignore[empty-body] properties=frozenset(), ) + config = _AutodocConfig.from_config(app.config) options = _AutoDocumenterOptions() _format_signatures( autodoc_annotations={}, - config=app.config, + config=config, docstrings=None, events=app.events, get_attr=safe_getattr,