-
-
Notifications
You must be signed in to change notification settings - Fork 212
Open
Labels
Description
Problem Description
When a subclass uses multiple inheritance and one of its base classes is a generic ABC (abc.ABC + typing.Generic[...]), pdoc incorrectly marks an overridden method from a non-generic base class as inherited, and does not show the overriding method’s docstring.
This does not happen for:
- multiple inheritance from two non-generic ABCs, or
- multiple inheritance from two generic ABCs.
So the misclassification appears specific to mixing a Generic[...] base with a non-generic ABC base.
Steps to reproduce the behavior:
# foo.py
from abc import ABC
from typing import Generic, TypeVar
T = TypeVar("T")
U = TypeVar("U")
class GenericABC1(ABC, Generic[T]):
""""""
def method_generic1(self):
pass
class GenericABC2(ABC, Generic[U]):
""""""
def method_generic2(self):
pass
class ABC1(ABC):
""""""
def method1(self):
pass
class ABC2(ABC):
""""""
def method2(self):
pass
class NonGenericSubclass(ABC1, ABC2):
"""
Both methods' docstring are displayed, and are not considered inherited.
"""
def method1(self):
"""method1 implementation docstring"""
pass
def method2(self):
"""method2 implementation docstring"""
pass
class GenericSubclass1(GenericABC1[T], GenericABC2[U]):
"""
Both methods' docstring are displayed, and are not considered inherited.
"""
def method_generic1(self):
"""method_generic1 implementation docstring"""
pass
def method_generic2(self):
"""method_generic2 implementation docstring"""
pass
class GenericSubclass2(GenericABC1[T], ABC1):
"""
method1's docstring should be displayed, but it is considered inherited. Behavior is different than inheriting either from both non-generic ABC, or from both generic ABC, as above.
"""
def method_generic1(self):
"""method_generic1 implementation docstring"""
pass
def method1(self):
"""method1 implementation docstring"""
pass
if __name__ == "__main__":
assert GenericSubclass2.method1 is not ABC1.method1
assert "method1 implementation" in (GenericSubclass2.method1.__doc__ or "")pdoc ./fooOpen the generated HTML for module foo and scroll to GenericSubclass2.
Observed Behavior
For GenericSubclass2(GenericABC1[T], ABC1):
method_generic1is shown normally with its docstring.method1is not shown as a concrete method on GenericSubclass2.- Instead,
method1appears under Inherited Members asABC1.method1(). - The docstring
"method1 implementation docstring"is not displayed as the subclass implementation.
Expected Behavior
Because GenericSubclass2 explicitly defines def method1(self): ..., pdoc should:
- treat
method1as belonging toGenericSubclass2(not inherited), and - display the overriding method’s docstring.
This is the same behavior pdoc already has for NonGenericSubclass(ABC1, ABC2) and GenericSubclass1(GenericABC1[T], GenericABC2[U]).
System Information
pdoc --version
pdoc: 16.0.0
Python: 3.12.11
Platform: macOS-15.6.1-arm64-arm-64bit