Skip to content

Commit d045227

Browse files
authored
Merge pull request #10539 from AA-Turner/fix-inherited-attrs
Fix inherited attribute docstrings
2 parents 60775ec + 29edce9 commit d045227

File tree

6 files changed

+93
-3
lines changed

6 files changed

+93
-3
lines changed

sphinx/ext/autodoc/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1670,7 +1670,8 @@ def add_directive_header(self, sig: str) -> None:
16701670
self.add_line(' ' + _('Bases: %s') % ', '.join(base_classes), sourcename)
16711671

16721672
def get_object_members(self, want_all: bool) -> Tuple[bool, ObjectMembers]:
1673-
members = get_class_members(self.object, self.objpath, self.get_attr)
1673+
members = get_class_members(self.object, self.objpath, self.get_attr,
1674+
self.config.autodoc_inherit_docstrings)
16741675
if not want_all:
16751676
if not self.options.members:
16761677
return False, [] # type: ignore

sphinx/ext/autodoc/importer.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,8 @@ def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable,
205205
return members
206206

207207

208-
def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
209-
) -> Dict[str, "ObjectMember"]:
208+
def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable,
209+
inherit_docstrings: bool = True) -> Dict[str, "ObjectMember"]:
210210
"""Get members and attributes of target class."""
211211
from sphinx.ext.autodoc import INSTANCEATTR, ObjectMember
212212

@@ -290,6 +290,11 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
290290
elif (ns == qualname and docstring and
291291
isinstance(members[name], ObjectMember) and
292292
not members[name].docstring):
293+
if cls != subject and not inherit_docstrings:
294+
# If we are in the MRO of the class and not the class itself,
295+
# and we do not want to inherit docstrings, then skip setting
296+
# the docstring below
297+
continue
293298
# attribute is already known, because dir(subject) enumerates it.
294299
# But it has no docstring yet
295300
members[name].docstring = '\n'.join(docstring)

tests/roots/test-ext-autodoc/target/inheritance.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
class Base(object):
2+
#: docstring
3+
inheritedattr = None
4+
25
def inheritedmeth(self):
36
"""Inherited function."""
47

tests/test_ext_autodoc.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ def test_autodoc_members(app):
549549
actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
550550
assert list(filter(lambda l: '::' in l, actual)) == [
551551
'.. py:class:: Base()',
552+
' .. py:attribute:: Base.inheritedattr',
552553
' .. py:method:: Base.inheritedclassmeth()',
553554
' .. py:method:: Base.inheritedmeth()',
554555
' .. py:method:: Base.inheritedstaticmeth(cls)'
@@ -569,6 +570,7 @@ def test_autodoc_members(app):
569570
actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
570571
assert list(filter(lambda l: '::' in l, actual)) == [
571572
'.. py:class:: Base()',
573+
' .. py:attribute:: Base.inheritedattr',
572574
' .. py:method:: Base.inheritedclassmeth()',
573575
' .. py:method:: Base.inheritedmeth()',
574576
' .. py:method:: Base.inheritedstaticmeth(cls)'
@@ -601,6 +603,7 @@ def test_autodoc_exclude_members(app):
601603
actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
602604
assert list(filter(lambda l: '::' in l, actual)) == [
603605
'.. py:class:: Base()',
606+
' .. py:attribute:: Base.inheritedattr',
604607
' .. py:method:: Base.inheritedclassmeth()'
605608
]
606609

@@ -618,6 +621,7 @@ def test_autodoc_exclude_members(app):
618621
actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
619622
assert list(filter(lambda l: '::' in l, actual)) == [
620623
'.. py:class:: Base()',
624+
' .. py:attribute:: Base.inheritedattr',
621625
' .. py:method:: Base.inheritedclassmeth()'
622626
]
623627

@@ -628,6 +632,7 @@ def test_autodoc_exclude_members(app):
628632
actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
629633
assert list(filter(lambda l: '::' in l, actual)) == [
630634
'.. py:class:: Base()',
635+
' .. py:attribute:: Base.inheritedattr',
631636
' .. py:method:: Base.inheritedclassmeth()',
632637
' .. py:method:: Base.inheritedstaticmeth(cls)'
633638
]
@@ -639,6 +644,7 @@ def test_autodoc_exclude_members(app):
639644
actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
640645
assert list(filter(lambda l: '::' in l, actual)) == [
641646
'.. py:class:: Base()',
647+
' .. py:attribute:: Base.inheritedattr',
642648
' .. py:method:: Base.inheritedclassmeth()',
643649
]
644650

@@ -648,6 +654,7 @@ def test_autodoc_exclude_members(app):
648654
actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
649655
assert list(filter(lambda l: '::' in l, actual)) == [
650656
'.. py:class:: Base()',
657+
' .. py:attribute:: Base.inheritedattr',
651658
' .. py:method:: Base.inheritedclassmeth()',
652659
]
653660

@@ -658,6 +665,7 @@ def test_autodoc_exclude_members(app):
658665
actual = do_autodoc(app, 'class', 'target.inheritance.Base', options)
659666
assert list(filter(lambda l: '::' in l, actual)) == [
660667
'.. py:class:: Base()',
668+
' .. py:attribute:: Base.inheritedattr',
661669
' .. py:method:: Base.inheritedclassmeth()',
662670
' .. py:method:: Base.inheritedmeth()',
663671
' .. py:method:: Base.inheritedstaticmeth(cls)'

tests/test_ext_autodoc_automodule.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,13 @@ def test_automodule_inherited_members(app):
133133
' :module: target.inheritance',
134134
'',
135135
'',
136+
' .. py:attribute:: Base.inheritedattr',
137+
' :module: target.inheritance',
138+
' :value: None',
139+
'',
140+
' docstring',
141+
'',
142+
'',
136143
' .. py:method:: Base.inheritedclassmeth()',
137144
' :module: target.inheritance',
138145
' :classmethod:',

tests/test_ext_autodoc_configs.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,72 @@ def test_autodoc_inherit_docstrings(app):
277277
]
278278

279279

280+
@pytest.mark.sphinx('html', testroot='ext-autodoc')
281+
def test_autodoc_inherit_docstrings_for_inherited_members(app):
282+
options = {"members": None,
283+
"inherited-members": None}
284+
285+
assert app.config.autodoc_inherit_docstrings is True # default
286+
actual = do_autodoc(app, 'class', 'target.inheritance.Derived', options)
287+
assert list(actual) == [
288+
'',
289+
'.. py:class:: Derived()',
290+
' :module: target.inheritance',
291+
'',
292+
'',
293+
' .. py:attribute:: Derived.inheritedattr',
294+
' :module: target.inheritance',
295+
' :value: None',
296+
'',
297+
' docstring',
298+
'',
299+
'',
300+
' .. py:method:: Derived.inheritedclassmeth()',
301+
' :module: target.inheritance',
302+
' :classmethod:',
303+
'',
304+
' Inherited class method.',
305+
'',
306+
'',
307+
' .. py:method:: Derived.inheritedmeth()',
308+
' :module: target.inheritance',
309+
'',
310+
' Inherited function.',
311+
'',
312+
'',
313+
' .. py:method:: Derived.inheritedstaticmeth(cls)',
314+
' :module: target.inheritance',
315+
' :staticmethod:',
316+
'',
317+
' Inherited static method.',
318+
'',
319+
]
320+
321+
# disable autodoc_inherit_docstrings
322+
app.config.autodoc_inherit_docstrings = False
323+
actual = do_autodoc(app, 'class', 'target.inheritance.Derived', options)
324+
assert list(actual) == [
325+
'',
326+
'.. py:class:: Derived()',
327+
' :module: target.inheritance',
328+
'',
329+
'',
330+
' .. py:method:: Derived.inheritedclassmeth()',
331+
' :module: target.inheritance',
332+
' :classmethod:',
333+
'',
334+
' Inherited class method.',
335+
'',
336+
'',
337+
' .. py:method:: Derived.inheritedstaticmeth(cls)',
338+
' :module: target.inheritance',
339+
' :staticmethod:',
340+
'',
341+
' Inherited static method.',
342+
'',
343+
]
344+
345+
280346
@pytest.mark.sphinx('html', testroot='ext-autodoc')
281347
def test_autodoc_docstring_signature(app):
282348
options = {"members": None, "special-members": "__init__, __new__"}

0 commit comments

Comments
 (0)