mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
gh-131116: Fix inspect.getdoc() to work with cached_property objects (GH-131165)
This commit is contained in:
parent
23d85a2a3f
commit
70748bdbea
5 changed files with 70 additions and 0 deletions
|
|
@ -639,6 +639,9 @@ Retrieving source code
|
||||||
.. versionchanged:: next
|
.. versionchanged:: next
|
||||||
Added parameters *inherit_class_doc* and *fallback_to_class_doc*.
|
Added parameters *inherit_class_doc* and *fallback_to_class_doc*.
|
||||||
|
|
||||||
|
Documentation strings on :class:`~functools.cached_property`
|
||||||
|
objects are now inherited if not overriden.
|
||||||
|
|
||||||
|
|
||||||
.. function:: getcomments(object)
|
.. function:: getcomments(object)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -747,6 +747,12 @@ def _finddoc(obj, *, search_in_class=True):
|
||||||
cls = _findclass(obj.fget)
|
cls = _findclass(obj.fget)
|
||||||
if cls is None or getattr(cls, name) is not obj:
|
if cls is None or getattr(cls, name) is not obj:
|
||||||
return None
|
return None
|
||||||
|
# Should be tested before ismethoddescriptor()
|
||||||
|
elif isinstance(obj, functools.cached_property):
|
||||||
|
name = obj.attrname
|
||||||
|
cls = _findclass(obj.func)
|
||||||
|
if cls is None or getattr(cls, name) is not obj:
|
||||||
|
return None
|
||||||
elif ismethoddescriptor(obj) or isdatadescriptor(obj):
|
elif ismethoddescriptor(obj) or isdatadescriptor(obj):
|
||||||
name = obj.__name__
|
name = obj.__name__
|
||||||
cls = obj.__objclass__
|
cls = obj.__objclass__
|
||||||
|
|
|
||||||
39
Lib/test/test_inspect/inspect_fodder3.py
Normal file
39
Lib/test/test_inspect/inspect_fodder3.py
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
from functools import cached_property
|
||||||
|
|
||||||
|
# docstring in parent, inherited in child
|
||||||
|
class ParentInheritDoc:
|
||||||
|
@cached_property
|
||||||
|
def foo(self):
|
||||||
|
"""docstring for foo defined in parent"""
|
||||||
|
|
||||||
|
class ChildInheritDoc(ParentInheritDoc):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ChildInheritDefineDoc(ParentInheritDoc):
|
||||||
|
@cached_property
|
||||||
|
def foo(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Redefine foo as something other than cached_property
|
||||||
|
class ChildPropertyFoo(ParentInheritDoc):
|
||||||
|
@property
|
||||||
|
def foo(self):
|
||||||
|
"""docstring for the property foo"""
|
||||||
|
|
||||||
|
class ChildMethodFoo(ParentInheritDoc):
|
||||||
|
def foo(self):
|
||||||
|
"""docstring for the method foo"""
|
||||||
|
|
||||||
|
# docstring in child but not parent
|
||||||
|
class ParentNoDoc:
|
||||||
|
@cached_property
|
||||||
|
def foo(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ChildNoDoc(ParentNoDoc):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ChildDefineDoc(ParentNoDoc):
|
||||||
|
@cached_property
|
||||||
|
def foo(self):
|
||||||
|
"""docstring for foo defined in child"""
|
||||||
|
|
@ -46,6 +46,7 @@
|
||||||
|
|
||||||
from test.test_inspect import inspect_fodder as mod
|
from test.test_inspect import inspect_fodder as mod
|
||||||
from test.test_inspect import inspect_fodder2 as mod2
|
from test.test_inspect import inspect_fodder2 as mod2
|
||||||
|
from test.test_inspect import inspect_fodder3 as mod3
|
||||||
from test.test_inspect import inspect_stringized_annotations
|
from test.test_inspect import inspect_stringized_annotations
|
||||||
from test.test_inspect import inspect_deferred_annotations
|
from test.test_inspect import inspect_deferred_annotations
|
||||||
|
|
||||||
|
|
@ -714,6 +715,25 @@ class B(A):
|
||||||
b.__doc__ = 'Instance'
|
b.__doc__ = 'Instance'
|
||||||
self.assertEqual(inspect.getdoc(b, fallback_to_class_doc=False), 'Instance')
|
self.assertEqual(inspect.getdoc(b, fallback_to_class_doc=False), 'Instance')
|
||||||
|
|
||||||
|
def test_getdoc_inherited_cached_property(self):
|
||||||
|
doc = inspect.getdoc(mod3.ParentInheritDoc.foo)
|
||||||
|
self.assertEqual(doc, 'docstring for foo defined in parent')
|
||||||
|
self.assertEqual(inspect.getdoc(mod3.ChildInheritDoc.foo), doc)
|
||||||
|
self.assertEqual(inspect.getdoc(mod3.ChildInheritDefineDoc.foo), doc)
|
||||||
|
|
||||||
|
def test_getdoc_redefine_cached_property_as_other(self):
|
||||||
|
self.assertEqual(inspect.getdoc(mod3.ChildPropertyFoo.foo),
|
||||||
|
'docstring for the property foo')
|
||||||
|
self.assertEqual(inspect.getdoc(mod3.ChildMethodFoo.foo),
|
||||||
|
'docstring for the method foo')
|
||||||
|
|
||||||
|
def test_getdoc_define_cached_property(self):
|
||||||
|
self.assertEqual(inspect.getdoc(mod3.ChildDefineDoc.foo),
|
||||||
|
'docstring for foo defined in child')
|
||||||
|
|
||||||
|
def test_getdoc_nodoc_inherited(self):
|
||||||
|
self.assertIsNone(inspect.getdoc(mod3.ChildNoDoc.foo))
|
||||||
|
|
||||||
@unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
|
@unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
|
||||||
def test_finddoc(self):
|
def test_finddoc(self):
|
||||||
finddoc = inspect._finddoc
|
finddoc = inspect._finddoc
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
:func:`inspect.getdoc` now correctly returns an inherited docstring on
|
||||||
|
:class:`~functools.cached_property` objects if none is given in a subclass.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue