diff options
21 files changed, 203 insertions, 28 deletions
@@ -19,7 +19,7 @@ Bugs fixed Testing -------- -Release 5.0.2 (in development) +Release 5.0.3 (in development) ============================== Dependencies @@ -37,11 +37,29 @@ Features added Bugs fixed ---------- -* #10509: autosummary: autosummary fails with a shared library - Testing -------- +Release 5.0.2 (released Jun 17, 2022) +===================================== + +Features added +-------------- + +* #10523: HTML Theme: Expose the Docutils's version info tuple as a template + variable, ``docutils_version_info``. Patch by Adam Turner. + +Bugs fixed +---------- + +* #10538: autodoc: Inherited class attribute having docstring is documented even + if :confval:`autodoc_inherit_docstring` is disabled +* #10509: autosummary: autosummary fails with a shared library +* #10497: py domain: Failed to resolve strings in Literal. Patch by Adam Turner. +* #10523: HTML Theme: Fix double brackets on citation references in Docutils 0.18+. + Patch by Adam Turner. +* #10534: Missing CSS for nav.contents in Docutils 0.18+. Patch by Adam Turner. + Release 5.0.1 (released Jun 03, 2022) ===================================== @@ -49,10 +67,11 @@ Bugs fixed ---------- * #10498: gettext: TypeError is raised when sorting warning messages if a node - has no line number -* #10493: html theme: :rst:dir:`topic` directive is rendered incorrectly with - docutils-0.18 -* #10495: IndexError is raised for a :rst:role:`kbd` role having a separator + has no line number. Patch by Adam Turner. +* #10493: HTML Theme: :rst:dir:`topic` directive is rendered incorrectly with + Docutils 0.18. Patch by Adam Turner. +* #10495: IndexError is raised for a :rst:role:`kbd` role having a separator. + Patch by Adam Turner. Release 5.0.0 (released May 30, 2022) ===================================== @@ -93,6 +112,7 @@ Incompatible changes * #10474: :confval:`language` does not accept ``None`` as it value. The default value of ``language`` becomes to ``'en'`` now. + Patch by Adam Turner and Takeshi KOMIYA. Deprecated ---------- @@ -148,11 +168,12 @@ Features added non-imported * #10028: Removed internal usages of JavaScript frameworks (jQuery and underscore.js) and modernised ``doctools.js`` and ``searchtools.js`` to - EMCAScript 2018. + EMCAScript 2018. Patch by Adam Turner. * #10302: C++, add support for conditional expressions (``?:``). * #5157, #10251: Inline code is able to be highlighted via :rst:dir:`role` directive -* #10337: Make sphinx-build faster by caching Publisher object during build +* #10337: Make sphinx-build faster by caching Publisher object during build. + Patch by Adam Turner. Bugs fixed ---------- @@ -160,7 +181,7 @@ Bugs fixed 5.0.0 b1 * #10200: apidoc: Duplicated submodules are shown for modules having both .pyx - and .so files + and .so files. Patch by Adam Turner and Takeshi KOMIYA. * #10279: autodoc: Default values for keyword only arguments in overloaded functions are rendered as a string literal * #10280: autodoc: :confval:`autodoc_docstring_signature` unexpectedly generates diff --git a/doc/_themes/sphinx13/static/sphinx13.css b/doc/_themes/sphinx13/static/sphinx13.css index c8fb2e5c9..5d64eda51 100644 --- a/doc/_themes/sphinx13/static/sphinx13.css +++ b/doc/_themes/sphinx13/static/sphinx13.css @@ -372,7 +372,9 @@ div.quotebar { margin-left: 1em; } -div.topic { +nav.contents, +div.topic, +aside.topic { background-color: #f8f8f8; } diff --git a/doc/templating.rst b/doc/templating.rst index 3d80edd60..d9755a836 100644 --- a/doc/templating.rst +++ b/doc/templating.rst @@ -383,6 +383,15 @@ in the future. .. versionadded:: 4.2 +.. data:: docutils_version_info + + The version of Docutils used to build represented as a tuple of five elements. + For Docutils version 0.16.1 beta 2 this would be `(0, 16, 1, 'beta', 2)``. + The fourth element can be one of: ``alpha``, ``beta``, ``candidate``, ``final``. + ``final`` always has 0 as the last element. + + .. versionadded:: 5.0.2 + .. data:: style The name of the main stylesheet, as given by the theme or diff --git a/sphinx/builders/html/__init__.py b/sphinx/builders/html/__init__.py index 6ba92eb3e..9404ae458 100644 --- a/sphinx/builders/html/__init__.py +++ b/sphinx/builders/html/__init__.py @@ -536,6 +536,7 @@ class StandaloneHTMLBuilder(Builder): 'css_files': self.css_files, 'sphinx_version': __display_version__, 'sphinx_version_tuple': sphinx_version, + 'docutils_version_info': docutils.__version_info__[:5], 'style': self._get_style_filename(), 'rellinks': rellinks, 'builder': self.name, diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index a634a51d2..fd43b15b2 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -396,7 +396,7 @@ class PyXrefMixin: results.append(self.make_xref(rolename, domain, sub_target, innernode, contnode, env, inliner, location)) - if sub_target in ('Literal', 'typing.Literal'): + if sub_target in ('Literal', 'typing.Literal', '~typing.Literal'): in_literal = True return results diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index e16ab8ce5..642e0cfd8 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1670,7 +1670,8 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type: self.add_line(' ' + _('Bases: %s') % ', '.join(base_classes), sourcename) def get_object_members(self, want_all: bool) -> Tuple[bool, ObjectMembers]: - members = get_class_members(self.object, self.objpath, self.get_attr) + members = get_class_members(self.object, self.objpath, self.get_attr, + self.config.autodoc_inherit_docstrings) if not want_all: if not self.options.members: return False, [] # type: ignore diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index 85c1e81be..d392ae75d 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -205,8 +205,8 @@ def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable, return members -def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable - ) -> Dict[str, "ObjectMember"]: +def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable, + inherit_docstrings: bool = True) -> Dict[str, "ObjectMember"]: """Get members and attributes of target class.""" from sphinx.ext.autodoc import INSTANCEATTR, ObjectMember @@ -290,6 +290,11 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable elif (ns == qualname and docstring and isinstance(members[name], ObjectMember) and not members[name].docstring): + if cls != subject and not inherit_docstrings: + # If we are in the MRO of the class and not the class itself, + # and we do not want to inherit docstrings, then skip setting + # the docstring below + continue # attribute is already known, because dir(subject) enumerates it. # But it has no docstring yet members[name].docstring = '\n'.join(docstring) diff --git a/sphinx/themes/basic/static/basic.css_t b/sphinx/themes/basic/static/basic.css_t index 9e5047afe..d8f3fe746 100644 --- a/sphinx/themes/basic/static/basic.css_t +++ b/sphinx/themes/basic/static/basic.css_t @@ -237,6 +237,7 @@ a.headerlink { visibility: hidden; } +{%- if docutils_version_info[:2] < (0, 18) %} a.brackets:before, span.brackets > a:before{ content: "["; @@ -246,6 +247,7 @@ a.brackets:after, span.brackets > a:after { content: "]"; } +{% endif %} h1:hover > a.headerlink, h2:hover > a.headerlink, @@ -335,13 +337,21 @@ p.sidebar-title { font-weight: bold; } -div.admonition, div.topic, aside.topic, blockquote { +{%- if docutils_version_info[:2] >= (0, 18) %} +nav.contents, +aside.topic, +{% endif %} +div.admonition, div.topic, blockquote { clear: left; } /* -- topics ---------------------------------------------------------------- */ -div.topic, aside.topic { +{%- if docutils_version_info[:2] >= (0, 18) %} +nav.contents, +aside.topic, +{% endif %} +div.topic { border: 1px solid #ccc; padding: 7px; margin: 10px 0 10px 0; @@ -379,16 +389,22 @@ div.body p.centered { div.sidebar > :last-child, aside.sidebar > :last-child, -div.topic > :last-child, +{%- if docutils_version_info[:2] >= (0, 18) %} +nav.contents > :last-child, aside.topic > :last-child, +{% endif %} +div.topic > :last-child, div.admonition > :last-child { margin-bottom: 0; } div.sidebar::after, aside.sidebar::after, -div.topic::after, +{%- if docutils_version_info[:2] >= (0, 18) %} +nav.contents::after, aside.topic::after, +{% endif %} +div.topic::after, div.admonition::after, blockquote::after { display: block; diff --git a/sphinx/themes/bizstyle/static/bizstyle.css_t b/sphinx/themes/bizstyle/static/bizstyle.css_t index b5c84e0bb..a524345f9 100644 --- a/sphinx/themes/bizstyle/static/bizstyle.css_t +++ b/sphinx/themes/bizstyle/static/bizstyle.css_t @@ -306,7 +306,11 @@ div.quotebar { border: 1px solid #ccc; } -div.topic, aside.topic { +{%- if docutils_version_info[:2] >= (0, 18) %} +nav.contents, +aside.topic, +{% endif %} +div.topic { background-color: #f8f8f8; } diff --git a/sphinx/themes/classic/static/classic.css_t b/sphinx/themes/classic/static/classic.css_t index 58b55c8bf..789bec811 100644 --- a/sphinx/themes/classic/static/classic.css_t +++ b/sphinx/themes/classic/static/classic.css_t @@ -290,7 +290,11 @@ div.seealso { border: 1px solid #ff6; } -div.topic, aside.topic { +{%- if docutils_version_info[:2] >= (0, 18) %} +nav.contents, +aside.topic, +{% endif %} +div.topic { background-color: #eee; } diff --git a/sphinx/themes/epub/static/epub.css_t b/sphinx/themes/epub/static/epub.css_t index bd64a1bc8..a30344431 100644 --- a/sphinx/themes/epub/static/epub.css_t +++ b/sphinx/themes/epub/static/epub.css_t @@ -245,7 +245,11 @@ p.sidebar-title { /* -- topics ---------------------------------------------------------------- */ -div.topic, aside.topic { +{%- if docutils_version_info[:2] >= (0, 18) %} +nav.contents, +aside.topic, +{% endif %} +div.topic { border: 1px solid #ccc; padding: 7px 7px 0 7px; margin: 10px 0 10px 0; diff --git a/sphinx/themes/nature/static/nature.css_t b/sphinx/themes/nature/static/nature.css_t index f3c0d0224..93f9a5944 100644 --- a/sphinx/themes/nature/static/nature.css_t +++ b/sphinx/themes/nature/static/nature.css_t @@ -194,7 +194,11 @@ div.seealso { border: 1px solid #ff6; } -div.topic, aside.topic { +{%- if docutils_version_info[:2] >= (0, 18) %} +nav.contents, +aside.topic, +{% endif %} +div.topic { background-color: #eee; } diff --git a/sphinx/themes/nonav/static/nonav.css b/sphinx/themes/nonav/static/nonav.css_t index 90c3300cf..933365e07 100644 --- a/sphinx/themes/nonav/static/nonav.css +++ b/sphinx/themes/nonav/static/nonav.css_t @@ -234,7 +234,11 @@ p.sidebar-title { /* -- topics ---------------------------------------------------------------- */ -div.topic, aside.topic { +{%- if docutils_version_info[:2] >= (0, 18) %} +nav.contents, +aside.topic, +{% endif %} +div.topic { border: 1px solid #ccc; padding: 7px 7px 0 7px; margin: 10px 0 10px 0; diff --git a/sphinx/themes/pyramid/static/epub.css b/sphinx/themes/pyramid/static/epub.css_t index 8606c8c8d..98741d0b8 100644 --- a/sphinx/themes/pyramid/static/epub.css +++ b/sphinx/themes/pyramid/static/epub.css_t @@ -254,7 +254,11 @@ div.seealso { border: 1px solid #ff6; } -div.topic, aside.topic { +{%- if docutils_version_info[:2] >= (0, 18) %} +nav.contents, +aside.topic, +{% endif %} +div.topic { background-color: #eee; } diff --git a/sphinx/themes/pyramid/static/pyramid.css_t b/sphinx/themes/pyramid/static/pyramid.css_t index f093ba164..0ced6b29f 100644 --- a/sphinx/themes/pyramid/static/pyramid.css_t +++ b/sphinx/themes/pyramid/static/pyramid.css_t @@ -245,7 +245,11 @@ div.seealso { padding: 10px 20px 10px 60px; } -div.topic, aside.topic { +{%- if docutils_version_info[:2] >= (0, 18) %} +nav.contents, +aside.topic, +{% endif %} +div.topic { background: #eeeeee; border: 2px solid #C6C9CB; padding: 10px 20px; diff --git a/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t b/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t index b6de4ae6f..1817c48bc 100644 --- a/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t +++ b/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t @@ -266,7 +266,11 @@ div.quotebar { border: 1px solid #ccc; } -div.topic, aside.topic { +{%- if docutils_version_info[:2] >= (0, 18) %} +nav.contents, +aside.topic, +{% endif %} +div.topic { background-color: #f8f8f8; } diff --git a/sphinx/themes/traditional/static/traditional.css_t b/sphinx/themes/traditional/static/traditional.css_t index b5b05dc21..8a2f0712f 100644 --- a/sphinx/themes/traditional/static/traditional.css_t +++ b/sphinx/themes/traditional/static/traditional.css_t @@ -506,7 +506,11 @@ p.rubric { /* "Topics" */ -div.topic, aside.topic { +{%- if docutils_version_info[:2] >= (0, 18) %} +nav.contents, +aside.topic, +{% endif %} +div.topic { background-color: #eee; border: 1px solid #ccc; padding: 0 7px 0 7px; diff --git a/tests/roots/test-ext-autodoc/target/inheritance.py b/tests/roots/test-ext-autodoc/target/inheritance.py index 485a943c8..85d95cd74 100644 --- a/tests/roots/test-ext-autodoc/target/inheritance.py +++ b/tests/roots/test-ext-autodoc/target/inheritance.py @@ -1,4 +1,7 @@ class Base(object): + #: docstring + inheritedattr = None + def inheritedmeth(self): """Inherited function.""" diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py index ecd2bbce6..a35c6f640 100644 --- a/tests/test_ext_autodoc.py +++ b/tests/test_ext_autodoc.py @@ -549,6 +549,7 @@ def test_autodoc_members(app): actual = do_autodoc(app, 'class', 'target.inheritance.Base', options) assert list(filter(lambda l: '::' in l, actual)) == [ '.. py:class:: Base()', + ' .. py:attribute:: Base.inheritedattr', ' .. py:method:: Base.inheritedclassmeth()', ' .. py:method:: Base.inheritedmeth()', ' .. py:method:: Base.inheritedstaticmeth(cls)' @@ -569,6 +570,7 @@ def test_autodoc_members(app): actual = do_autodoc(app, 'class', 'target.inheritance.Base', options) assert list(filter(lambda l: '::' in l, actual)) == [ '.. py:class:: Base()', + ' .. py:attribute:: Base.inheritedattr', ' .. py:method:: Base.inheritedclassmeth()', ' .. py:method:: Base.inheritedmeth()', ' .. py:method:: Base.inheritedstaticmeth(cls)' @@ -601,6 +603,7 @@ def test_autodoc_exclude_members(app): actual = do_autodoc(app, 'class', 'target.inheritance.Base', options) assert list(filter(lambda l: '::' in l, actual)) == [ '.. py:class:: Base()', + ' .. py:attribute:: Base.inheritedattr', ' .. py:method:: Base.inheritedclassmeth()' ] @@ -618,6 +621,7 @@ def test_autodoc_exclude_members(app): actual = do_autodoc(app, 'class', 'target.inheritance.Base', options) assert list(filter(lambda l: '::' in l, actual)) == [ '.. py:class:: Base()', + ' .. py:attribute:: Base.inheritedattr', ' .. py:method:: Base.inheritedclassmeth()' ] @@ -628,6 +632,7 @@ def test_autodoc_exclude_members(app): actual = do_autodoc(app, 'class', 'target.inheritance.Base', options) assert list(filter(lambda l: '::' in l, actual)) == [ '.. py:class:: Base()', + ' .. py:attribute:: Base.inheritedattr', ' .. py:method:: Base.inheritedclassmeth()', ' .. py:method:: Base.inheritedstaticmeth(cls)' ] @@ -639,6 +644,7 @@ def test_autodoc_exclude_members(app): actual = do_autodoc(app, 'class', 'target.inheritance.Base', options) assert list(filter(lambda l: '::' in l, actual)) == [ '.. py:class:: Base()', + ' .. py:attribute:: Base.inheritedattr', ' .. py:method:: Base.inheritedclassmeth()', ] @@ -648,6 +654,7 @@ def test_autodoc_exclude_members(app): actual = do_autodoc(app, 'class', 'target.inheritance.Base', options) assert list(filter(lambda l: '::' in l, actual)) == [ '.. py:class:: Base()', + ' .. py:attribute:: Base.inheritedattr', ' .. py:method:: Base.inheritedclassmeth()', ] @@ -658,6 +665,7 @@ def test_autodoc_exclude_members(app): actual = do_autodoc(app, 'class', 'target.inheritance.Base', options) assert list(filter(lambda l: '::' in l, actual)) == [ '.. py:class:: Base()', + ' .. py:attribute:: Base.inheritedattr', ' .. py:method:: Base.inheritedclassmeth()', ' .. py:method:: Base.inheritedmeth()', ' .. py:method:: Base.inheritedstaticmeth(cls)' diff --git a/tests/test_ext_autodoc_automodule.py b/tests/test_ext_autodoc_automodule.py index 8208d86f6..71b23679d 100644 --- a/tests/test_ext_autodoc_automodule.py +++ b/tests/test_ext_autodoc_automodule.py @@ -133,6 +133,13 @@ def test_automodule_inherited_members(app): ' :module: target.inheritance', '', '', + ' .. py:attribute:: Base.inheritedattr', + ' :module: target.inheritance', + ' :value: None', + '', + ' docstring', + '', + '', ' .. py:method:: Base.inheritedclassmeth()', ' :module: target.inheritance', ' :classmethod:', diff --git a/tests/test_ext_autodoc_configs.py b/tests/test_ext_autodoc_configs.py index 0011f450b..f40f3354e 100644 --- a/tests/test_ext_autodoc_configs.py +++ b/tests/test_ext_autodoc_configs.py @@ -278,6 +278,72 @@ def test_autodoc_inherit_docstrings(app): @pytest.mark.sphinx('html', testroot='ext-autodoc') +def test_autodoc_inherit_docstrings_for_inherited_members(app): + options = {"members": None, + "inherited-members": None} + + assert app.config.autodoc_inherit_docstrings is True # default + actual = do_autodoc(app, 'class', 'target.inheritance.Derived', options) + assert list(actual) == [ + '', + '.. py:class:: Derived()', + ' :module: target.inheritance', + '', + '', + ' .. py:attribute:: Derived.inheritedattr', + ' :module: target.inheritance', + ' :value: None', + '', + ' docstring', + '', + '', + ' .. py:method:: Derived.inheritedclassmeth()', + ' :module: target.inheritance', + ' :classmethod:', + '', + ' Inherited class method.', + '', + '', + ' .. py:method:: Derived.inheritedmeth()', + ' :module: target.inheritance', + '', + ' Inherited function.', + '', + '', + ' .. py:method:: Derived.inheritedstaticmeth(cls)', + ' :module: target.inheritance', + ' :staticmethod:', + '', + ' Inherited static method.', + '', + ] + + # disable autodoc_inherit_docstrings + app.config.autodoc_inherit_docstrings = False + actual = do_autodoc(app, 'class', 'target.inheritance.Derived', options) + assert list(actual) == [ + '', + '.. py:class:: Derived()', + ' :module: target.inheritance', + '', + '', + ' .. py:method:: Derived.inheritedclassmeth()', + ' :module: target.inheritance', + ' :classmethod:', + '', + ' Inherited class method.', + '', + '', + ' .. py:method:: Derived.inheritedstaticmeth(cls)', + ' :module: target.inheritance', + ' :staticmethod:', + '', + ' Inherited static method.', + '', + ] + + +@pytest.mark.sphinx('html', testroot='ext-autodoc') def test_autodoc_docstring_signature(app): options = {"members": None, "special-members": "__init__, __new__"} actual = do_autodoc(app, 'class', 'target.DocstringSig', options) |