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 "")
Open the generated HTML for module foo and scroll to GenericSubclass2.
Observed Behavior
For GenericSubclass2(GenericABC1[T], ABC1):
method_generic1 is shown normally with its docstring.
method1 is not shown as a concrete method on GenericSubclass2.
- Instead,
method1 appears under Inherited Members as ABC1.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
method1 as belonging to GenericSubclass2 (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
Problem Description
When a subclass uses multiple inheritance and one of its base classes is a generic ABC (
abc.ABC+typing.Generic[...]),pdocincorrectly 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:
So the misclassification appears specific to mixing a
Generic[...]base with a non-generic ABC base.Steps to reproduce the behavior:
Open the generated HTML for module
fooand scroll toGenericSubclass2.Observed Behavior
For
GenericSubclass2(GenericABC1[T], ABC1):method_generic1is shown normally with its docstring.method1is not shown as a concrete method on GenericSubclass2.method1appears under Inherited Members asABC1.method1()."method1 implementation docstring"is not displayed as the subclass implementation.Expected Behavior
Because
GenericSubclass2explicitly definesdef method1(self): ...,pdocshould:method1as belonging toGenericSubclass2(not inherited), andThis is the same behavior
pdocalready has forNonGenericSubclass(ABC1, ABC2)andGenericSubclass1(GenericABC1[T], GenericABC2[U]).System Information