Merge pull request #10539 from AA-Turner/fix-inherited-attrs

Fix inherited attribute docstrings
This commit is contained in:
Takeshi KOMIYA
2022-06-14 03:03:40 +09:00
committed by GitHub
6 changed files with 93 additions and 3 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -1,4 +1,7 @@
class Base(object):
#: docstring
inheritedattr = None
def inheritedmeth(self):
"""Inherited function."""

View File

@@ -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)'

View File

@@ -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:',

View File

@@ -277,6 +277,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__"}