diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 103537afa..3ce703b72 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -10,7 +10,6 @@ :license: BSD, see LICENSE for details. """ -import importlib import re import warnings from inspect import Parameter, Signature @@ -27,7 +26,7 @@ from sphinx.deprecation import (RemovedInSphinx40Warning, RemovedInSphinx50Warni RemovedInSphinx60Warning) from sphinx.environment import BuildEnvironment from sphinx.ext.autodoc.importer import (get_class_members, get_module_members, - get_object_members, import_object) + get_object_members, import_module, import_object) from sphinx.ext.autodoc.mock import mock from sphinx.locale import _, __ from sphinx.pycode import ModuleAnalyzer, PycodeError @@ -1809,12 +1808,14 @@ class UninitializedGlobalVariableMixin(DataDocumenterMixinBase): except ImportError as exc: # annotation only instance variable (PEP-526) try: - self.parent = importlib.import_module(self.modname) - annotations = get_type_hints(self.parent, None, - self.config.autodoc_type_aliases) - if self.objpath[-1] in annotations: - self.object = UNINITIALIZED_ATTR - return True + with mock(self.config.autodoc_mock_imports): + parent = import_module(self.modname, self.config.autodoc_warningiserror) + annotations = get_type_hints(parent, None, + self.config.autodoc_type_aliases) + if self.objpath[-1] in annotations: + self.object = UNINITIALIZED_ATTR + self.parent = parent + return True except ImportError: pass @@ -2148,9 +2149,9 @@ class SlotsMixin(DataDocumenterMixinBase): return super().get_doc(encoding, ignore) # type: ignore -class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase): +class RuntimeInstanceAttributeMixin(DataDocumenterMixinBase): """ - Mixin for AttributeDocumenter to provide the feature for supporting uninitialized + Mixin for AttributeDocumenter to provide the feature for supporting runtime instance attributes (that are defined in __init__() methods with doc-comments). Example: @@ -2160,6 +2161,8 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase): self.attr = None #: This is a target of this mix-in. """ + RUNTIME_INSTANCE_ATTRIBUTE = object() + def get_attribute_comment(self, parent: Any) -> Optional[List[str]]: try: for cls in inspect.getmro(parent): @@ -2180,7 +2183,7 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase): return None - def is_uninitialized_instance_attribute(self, parent: Any) -> bool: + def is_runtime_instance_attribute(self, parent: Any) -> bool: """Check the subject is an attribute defined in __init__().""" # An instance variable defined in __init__(). if self.get_attribute_comment(parent): @@ -2189,9 +2192,8 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase): return False def import_object(self, raiseerror: bool = False) -> bool: - """Check the exisitence of uninitizlied instance attribute when failed to import - the attribute. - """ + """Check the exisitence of runtime instance attribute when failed to import the + attribute.""" try: return super().import_object(raiseerror=True) # type: ignore except ImportError as exc: @@ -2201,8 +2203,8 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase): attrgetter=self.get_attr, # type: ignore warningiserror=self.config.autodoc_warningiserror) parent = ret[3] - if self.is_uninitialized_instance_attribute(parent): - self.object = UNINITIALIZED_ATTR + if self.is_runtime_instance_attribute(parent): + self.object = self.RUNTIME_INSTANCE_ATTRIBUTE self.parent = parent return True except ImportError: @@ -2216,11 +2218,11 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase): return False def should_suppress_value_header(self) -> bool: - return (self.object is UNINITIALIZED_ATTR or + return (self.object is self.RUNTIME_INSTANCE_ATTRIBUTE or super().should_suppress_value_header()) def get_doc(self, encoding: str = None, ignore: int = None) -> List[List[str]]: - if self.object is UNINITIALIZED_ATTR: + if self.object is self.RUNTIME_INSTANCE_ATTRIBUTE: comment = self.get_attribute_comment(self.parent) if comment: return [comment] @@ -2229,14 +2231,14 @@ class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase): def add_content(self, more_content: Optional[StringList], no_docstring: bool = False ) -> None: - if self.object is UNINITIALIZED_ATTR: + if self.object is self.RUNTIME_INSTANCE_ATTRIBUTE: self.analyzer = None super().add_content(more_content, no_docstring=no_docstring) # type: ignore class AttributeDocumenter(GenericAliasMixin, NewTypeMixin, SlotsMixin, # type: ignore - TypeVarMixin, UninitializedInstanceAttributeMixin, + TypeVarMixin, RuntimeInstanceAttributeMixin, NonDataDescriptorMixin, DocstringStripSignatureMixin, ClassLevelDocumenter): """