From ccb9a3e63563dade561a8e79867f4a6ff27be699 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 20 Dec 2020 19:19:44 +0900 Subject: [PATCH 1/4] refactor: Rename UninitializedInstanceAttributeMixin The instance variables defined at __init__() method are basically initialized. So it's not appropriate to call them as "uninitialized". So this renames the documenter for them to RuntimeInstanceAttributeMixin. --- sphinx/ext/autodoc/__init__.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index a23547a61..baa0f3c77 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -2148,9 +2148,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 +2160,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 +2182,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 +2191,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: @@ -2200,8 +2201,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: @@ -2215,11 +2216,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] @@ -2228,14 +2229,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): """ From d7c490fefcb8821ff288f82ab5f79c525645016e Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 21 Dec 2020 01:20:58 +0900 Subject: [PATCH 2/4] refactor: autodoc: Do not fill parent field when not global variable --- sphinx/ext/autodoc/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index a23547a61..94c32ae7c 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1809,11 +1809,11 @@ 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) + parent = importlib.import_module(self.modname) + 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 From edc7f23620cfa2d9af54c94a4e701762ce3afc64 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 21 Dec 2020 01:32:50 +0900 Subject: [PATCH 3/4] autodoc: Fix enable mocks on importing module --- sphinx/ext/autodoc/__init__.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 94c32ae7c..5d689557d 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1809,12 +1809,14 @@ class UninitializedGlobalVariableMixin(DataDocumenterMixinBase): except ImportError as exc: # annotation only instance variable (PEP-526) try: - parent = importlib.import_module(self.modname) - 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 + with mock(self.config.autodoc_mock_imports): + parent = importlib.import_module(self.modname) + 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 From 0f0560f07baa9e6287b5e3c1713a314b6224e113 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 21 Dec 2020 01:52:20 +0900 Subject: [PATCH 4/4] refactor: autodoc: Use importer.import_module() --- sphinx/ext/autodoc/__init__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 5d689557d..b254cc8c0 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 @@ -1810,7 +1809,7 @@ class UninitializedGlobalVariableMixin(DataDocumenterMixinBase): # annotation only instance variable (PEP-526) try: with mock(self.config.autodoc_mock_imports): - parent = importlib.import_module(self.modname) + 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: