Skip to content

Commit 639ff80

Browse files
fix: Fix inheritance logic when intermediate class without member is present
Issue-4: #4 PR-5: #5 Co-authored-by: Timothée Mazzucotelli <dev@pawamoy.fr>
1 parent c89f92f commit 639ff80

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

src/griffe_inherited_docstrings/extension.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313

1414
def _docstring_above(obj: Object) -> Docstring | None:
1515
with contextlib.suppress(IndexError, KeyError):
16-
parent = obj.parent.mro()[0] # type: ignore[union-attr]
17-
return parent.members[obj.name].docstring
16+
for parent in obj.parent.mro(): # type: ignore[union-attr]
17+
# Fetch docstring from first parent that has the member.
18+
if obj.name in parent.members:
19+
return parent.members[obj.name].docstring
1820
return None
1921

2022

@@ -35,7 +37,7 @@ def _inherit_docstrings(obj: Object, *, merge: bool = False, seen: set[str] | No
3537

3638
elif obj.is_class:
3739
# Recursively handle top-most parents first.
38-
# It means that we can just check the first parent
40+
# It means that we can just check the first parent with the member
3941
# when actually inheriting (and optionally merging) a docstring,
4042
# since the docstrings of the other parents have already been inherited.
4143
for parent in reversed(obj.mro()): # type: ignore[attr-defined]

tests/test_extension.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,32 @@ def meth(self):
8787
assert package["D.meth"].docstring.value == package["A.meth"].docstring.value + "\n\n" + f"{meth_doc} D."
8888
assert package["E.attr"].docstring.value == package["D.attr"].docstring.value + "\n\n" + f"{attr_doc} E."
8989
assert package["E.meth"].docstring.value == package["D.meth"].docstring.value + "\n\n" + f"{meth_doc} E."
90+
91+
92+
def test_inherit_and_merge_docstrings_intermediate_class() -> None:
93+
"""Inherit and merge docstrings from parent classes with an intermediate class.
94+
95+
It is important that the intermediate class doesn't have the member for which
96+
docstring inheritance should be performed.
97+
"""
98+
with temporary_visited_package(
99+
"package",
100+
modules={
101+
"__init__.py": """
102+
class Parent:
103+
def method(self):
104+
'''Parent.'''
105+
106+
class Intermediate(Parent):
107+
# This shouldn't break the inherting of docstrings.
108+
# See https://github.com/mkdocstrings/griffe-inherited-docstrings/issues/4.
109+
...
110+
111+
class Child(Intermediate):
112+
def method(self):
113+
'''Child.'''
114+
""",
115+
},
116+
extensions=Extensions(InheritDocstringsExtension(merge=True)),
117+
) as package:
118+
assert package["Child.method"].docstring.value == "Parent.\n\nChild."

0 commit comments

Comments
 (0)