Merge pull request #9261 from tk0miya/9250_inherited_docstring

Fix #9250: autodoc: The inherited method not having docstring is wrongly parsed
This commit is contained in:
Takeshi KOMIYA
2021-05-24 01:24:23 +09:00
committed by GitHub
4 changed files with 25 additions and 12 deletions

View File

@@ -54,6 +54,7 @@ Bugs fixed
* #8597: autodoc: a docsting having metadata only should be treated as
undocumented
* #9185: autodoc: typehints for overloaded functions and methods are inaccurate
* #9250: autodoc: The inherited method not having docstring is wrongly parsed
* #9217: manpage: The name of manpage directory that is generated by
:confval:`man_make_section_directory` is not correct
* #9224: ``:param:`` and ``:type:`` fields does not support a type containing

View File

@@ -1704,7 +1704,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
__init__ = self.get_attr(self.object, '__init__', None)
initdocstring = getdoc(__init__, self.get_attr,
self.config.autodoc_inherit_docstrings,
self.parent, self.object_name)
self.object, '__init__')
# for new-style classes, no __init__ means default __init__
if (initdocstring is not None and
(initdocstring == object.__init__.__doc__ or # for pypy
@@ -1715,7 +1715,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
__new__ = self.get_attr(self.object, '__new__', None)
initdocstring = getdoc(__new__, self.get_attr,
self.config.autodoc_inherit_docstrings,
self.parent, self.object_name)
self.object, '__new__')
# for new-style classes, no __new__ means default __new__
if (initdocstring is not None and
(initdocstring == object.__new__.__doc__ or # for pypy

View File

@@ -838,16 +838,25 @@ def getdoc(obj: Any, attrgetter: Callable = safe_getattr,
if ispartial(obj) and doc == obj.__class__.__doc__:
return getdoc(obj.func)
elif doc is None and allow_inherited:
doc = inspect.getdoc(obj)
if doc is None and cls and name:
# inspect.getdoc() does not support some kind of inherited and decorated methods.
# This tries to obtain the docstring from super classes.
for basecls in getattr(cls, '__mro__', []):
if cls and name:
# Check a docstring of the attribute or method from super classes.
for basecls in getmro(cls):
meth = safe_getattr(basecls, name, None)
if meth is not None:
doc = inspect.getdoc(meth)
if doc:
doc = attrgetter(meth, '__doc__', None)
if doc is not None:
break
if doc is None:
# retry using `inspect.getdoc()`
for basecls in getmro(cls):
meth = safe_getattr(basecls, name, None)
if meth is not None:
doc = inspect.getdoc(meth)
if doc is not None:
break
if doc is None:
doc = inspect.getdoc(obj)
return doc

View File

@@ -674,7 +674,10 @@ def test_unpartial():
def test_getdoc_inherited_decorated_method():
class Foo:
def meth(self):
"""docstring."""
"""
docstring
indented text
"""
class Bar(Foo):
@functools.lru_cache()
@@ -683,7 +686,7 @@ def test_getdoc_inherited_decorated_method():
pass
assert inspect.getdoc(Bar.meth, getattr, False, Bar, "meth") is None
assert inspect.getdoc(Bar.meth, getattr, True, Bar, "meth") == "docstring."
assert inspect.getdoc(Bar.meth, getattr, True, Bar, "meth") == Foo.meth.__doc__
def test_is_builtin_class_method():