From eea38ba61ba7418936f5fb20eb811a94888cbaf9 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 21 Nov 2021 11:25:48 +0900 Subject: [PATCH] Fix #9866: autodoc: doccoment for the imported class was ignored Autodoc tried to scan doccomment on the module where the class defined. But it failed to get it if the class is imported from other module. This analyzes the target module to obtain the doccomment. --- CHANGES | 1 + sphinx/ext/autodoc/__init__.py | 12 ++++++++++-- tests/roots/test-ext-autodoc/target/classes.py | 3 +++ tests/test_ext_autodoc.py | 2 ++ tests/test_ext_autodoc_autoclass.py | 12 ++++++++++++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 497aa719cc9..762fab5b813 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,7 @@ Features added Bugs fixed ---------- +* #9866: autodoc: doccoment for the imported class was ignored * #9857: Generated RFC links use outdated base url Testing diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 2cdf224cb25..62f1fb1b313 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1743,14 +1743,22 @@ def get_doc(self, ignore: int = None) -> Optional[List[List[str]]]: def get_variable_comment(self) -> Optional[List[str]]: try: key = ('', '.'.join(self.objpath)) - analyzer = ModuleAnalyzer.for_module(self.get_real_modname()) + if self.doc_as_attr: + analyzer = ModuleAnalyzer.for_module(self.modname) + else: + analyzer = ModuleAnalyzer.for_module(self.get_real_modname()) analyzer.analyze() - return list(self.analyzer.attr_docs.get(key, [])) + return list(analyzer.attr_docs.get(key, [])) except PycodeError: return None def add_content(self, more_content: Optional[StringList], no_docstring: bool = False ) -> None: + if self.doc_as_attr and self.modname != self.get_real_modname(): + # override analyzer to obtain doccomment around its definition. + self.analyzer = ModuleAnalyzer.for_module(self.modname) + self.analyzer.analyze() + if self.doc_as_attr and not self.get_variable_comment(): try: more_content = StringList([_('alias of %s') % restify(self.object)], source='') diff --git a/tests/roots/test-ext-autodoc/target/classes.py b/tests/roots/test-ext-autodoc/target/classes.py index d18128584af..5ba0294fbd6 100644 --- a/tests/roots/test-ext-autodoc/target/classes.py +++ b/tests/roots/test-ext-autodoc/target/classes.py @@ -37,3 +37,6 @@ class Corge(Quux): #: docstring OtherAlias = Bar + +#: docstring +IntAlias = int diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py index 8f14392b218..03efb5bcbbc 100644 --- a/tests/test_ext_autodoc.py +++ b/tests/test_ext_autodoc.py @@ -1870,6 +1870,8 @@ def test_autodoc_GenericAlias(app): ' .. py:attribute:: Class.T', ' :module: target.genericalias', '', + ' A list of int', + '', ' alias of :py:class:`~typing.List`\\ [:py:class:`int`]', '', '.. py:attribute:: T', diff --git a/tests/test_ext_autodoc_autoclass.py b/tests/test_ext_autodoc_autoclass.py index 9c730f425c8..6f4e2106046 100644 --- a/tests/test_ext_autodoc_autoclass.py +++ b/tests/test_ext_autodoc_autoclass.py @@ -407,6 +407,18 @@ def test_class_alias_having_doccomment(app): ] +def test_class_alias_for_imported_object_having_doccomment(app): + actual = do_autodoc(app, 'class', 'target.classes.IntAlias') + assert list(actual) == [ + '', + '.. py:attribute:: IntAlias', + ' :module: target.classes', + '', + ' docstring', + '', + ] + + @pytest.mark.sphinx('html', testroot='ext-autodoc') def test_coroutine(app): options = {"members": None}