diff --git a/CHANGES b/CHANGES index e0cee6fed..aaa6ed0a7 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,7 @@ Features added Bugs fixed ---------- +* #9866: autodoc: doccoment for the imported class was ignored * #9878: mathjax: MathJax configuration is placed after loading MathJax itself * #9857: Generated RFC links use outdated base url diff --git a/doc/tutorial/describing-code.rst b/doc/tutorial/describing-code.rst index bfeca0455..0b88f5bd9 100644 --- a/doc/tutorial/describing-code.rst +++ b/doc/tutorial/describing-code.rst @@ -14,8 +14,11 @@ section apply for the other domains as well. .. _tutorial-describing-objects: +Python +------ + Documenting Python objects --------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~ Sphinx offers several roles and directives to document Python objects, all grouped together in :ref:`the Python domain `. For example, @@ -68,7 +71,7 @@ Notice several things: ``.. function::`` directly. Cross-referencing Python objects --------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ By default, most of these directives generate entities that can be cross-referenced from any part of the documentation by using @@ -123,7 +126,7 @@ And finally, this is how the result would look: Beautiful, isn't it? Including doctests in your documentation ----------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Since you are now describing code from a Python library, it will become useful to keep both the documentation and the code as synchronized as possible. @@ -229,3 +232,44 @@ And finally, ``make test`` reports success! For big projects though, this manual approach can become a bit tedious. In the next section, you will see :doc:`how to automate the process `. + +Other languages (C, C++, others) +-------------------------------- + +Documenting and cross-referencing objects +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sphinx also supports documenting and cross-referencing objects written in +other programming languages. There are four additional built-in domains: +C, C++, JavaScript, and reStructuredText. Third-party extensions may +define domains for more languages, such as + +- `Fortran `_, +- `Julia `_, or +- `PHP `_. + +For example, to document a C++ type definition, you would use the built-in +:rst:dir:`cpp:type` directive, as follows: + +.. code-block:: rst + + .. cpp:type:: std::vector CustomList + + A typedef-like declaration of a type. + +Which would give the following result: + +.. cpp:type:: std::vector CustomList + + A typedef-like declaration of a type. + +All such directives then generate references that can be +cross-referenced by using the corresponding role. For example, to reference +the previous type definition, you can use the :rst:role:`cpp:type` role +as follows: + +.. code-block:: rst + + Cross reference to :cpp:type:`CustomList`. + +Which would produce a hyperlink to the previous definition: :cpp:type:`CustomList`. diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 2cdf224cb..62f1fb1b3 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1743,14 +1743,22 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type: 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 d18128584..5ba0294fb 100644 --- a/tests/roots/test-ext-autodoc/target/classes.py +++ b/tests/roots/test-ext-autodoc/target/classes.py @@ -37,3 +37,6 @@ Alias = Foo #: docstring OtherAlias = Bar + +#: docstring +IntAlias = int diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py index 8f14392b2..c853fbb03 100644 --- a/tests/test_ext_autodoc.py +++ b/tests/test_ext_autodoc.py @@ -1870,12 +1870,15 @@ 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', ' :module: target.genericalias', '', - ' alias of :py:class:`~typing.List`\\ [:py:class:`int`]', + ' A list of int', + '', ] else: assert list(actual) == [ diff --git a/tests/test_ext_autodoc_autoclass.py b/tests/test_ext_autodoc_autoclass.py index 9c730f425..6f4e21060 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}