From 022bbb92a1a3e07b0da447cc6f338b59017e6ec4 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 21 Dec 2020 02:29:46 +0900 Subject: [PATCH] refactor: autodoc: Move get_attribute_comment() to AttributeDocumenter To share the implementation to every attributes-mixins, this moves get_attribute_comment() method to AttributeDocumenter. --- sphinx/ext/autodoc/__init__.py | 66 ++++++++++++++++------------------ 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 934d65725..78ded1463 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -2164,30 +2164,10 @@ class RuntimeInstanceAttributeMixin(DataDocumenterMixinBase): RUNTIME_INSTANCE_ATTRIBUTE = object() - def get_attribute_comment(self, parent: Any) -> Optional[List[str]]: - try: - for cls in inspect.getmro(parent): - try: - module = safe_getattr(cls, '__module__') - qualname = safe_getattr(cls, '__qualname__') - - analyzer = ModuleAnalyzer.for_module(module) - analyzer.analyze() - if qualname and self.objpath: - key = (qualname, self.objpath[-1]) - if key in analyzer.attr_docs: - return list(analyzer.attr_docs[key]) - except (AttributeError, PycodeError): - pass - except (AttributeError, PycodeError): - pass - - return None - 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): + if self.get_attribute_comment(parent, self.objpath[-1]): # type: ignore return True else: return False @@ -2222,21 +2202,6 @@ class RuntimeInstanceAttributeMixin(DataDocumenterMixinBase): 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 self.RUNTIME_INSTANCE_ATTRIBUTE: - comment = self.get_attribute_comment(self.parent) - if comment: - return [comment] - - return super().get_doc(encoding, ignore) # type: ignore - - def add_content(self, more_content: Optional[StringList], no_docstring: bool = False - ) -> None: - 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, RuntimeInstanceAttributeMixin, @@ -2366,7 +2331,32 @@ class AttributeDocumenter(GenericAliasMixin, NewTypeMixin, SlotsMixin, # type: except ValueError: pass + def get_attribute_comment(self, parent: Any, attrname: str) -> Optional[List[str]]: + try: + for cls in inspect.getmro(parent): + try: + module = safe_getattr(cls, '__module__') + qualname = safe_getattr(cls, '__qualname__') + + analyzer = ModuleAnalyzer.for_module(module) + analyzer.analyze() + if qualname and self.objpath: + key = (qualname, attrname) + if key in analyzer.attr_docs: + return list(analyzer.attr_docs[key]) + except (AttributeError, PycodeError): + pass + except (AttributeError, PycodeError): + pass + + return None + def get_doc(self, encoding: str = None, ignore: int = None) -> List[List[str]]: + # Check the attribute has a docstring-comment + comment = self.get_attribute_comment(self.parent, self.objpath[-1]) + if comment: + return [comment] + if self.object is INSTANCEATTR: return [] @@ -2382,6 +2372,10 @@ class AttributeDocumenter(GenericAliasMixin, NewTypeMixin, SlotsMixin, # type: def add_content(self, more_content: Optional[StringList], no_docstring: bool = False ) -> None: + # Disable analyzing attribute comment on Documenter.add_content() to control it on + # AttributeDocumenter.add_content() + self.analyzer = None + if more_content is None: more_content = StringList() self.update_content(more_content)