Karthikeyan Singaravelan <[email protected]> added the comment:
I did some analysis with the given example script. Related issue where Aaron
has some analysis : issue12154 . The patch doesn't break anything since there
are no tests for this that also could be added.
1. When we do inspect.getdoc(c.sum) it looks for obj.__doc__ (c.sum.__doc__)
returning partialmethod.__doc__ ("new function with partial...") instead of
checking if c.sum is a partial method and returning obj.func.__doc__ which
contains the relevant doc ("sum doc"). Thus getdoc needs to check before trying
for obj.__doc__ if the obj is a partialmethod or partial object thus returning
the original function object.
2. When we do inspect.getdoc(Child.sum) it looks for obj.__doc__
(Child.sum.__doc__) and since Child.sum is a partialmethod which has __get__
overridden it calls _make_unbound_method that returns a _method object with no
doc and thus returning None. partialmethod object copies objects from the given
function at
https://github.com/python/cpython/blob/f1b9ad3d38c11676b45edcbf2369239bae436e56/Lib/functools.py#L368
and the actual object is returned at
https://github.com/python/cpython/blob/f1b9ad3d38c11676b45edcbf2369239bae436e56/Lib/functools.py#L401
. Here self.func has the original function in this case Base.sum and
_method._partialmethod has reference to Base.sum which contains the relevant
docs but _method itself has no docs thus pydoc doesn't get any docs. So we can
set _method.__doc__ = self.func.__doc__ and getdoc can pick up the docs.
sample script with
print(pydoc.render_doc(Child))
print(pydoc.render_doc(c))
print(inspect.getdoc(c.sum)) # Need to patch getdoc before it checks for
obj.__doc__ to check if the c.sum is an instance of partialmethod or partial
print(inspect.getdoc(Child.sum)) # Need to patch
functools.partialmethod._make_unbound_method to copy the docs to _method
Output :
```
Python Library Documentation: class Child in module __main__
class Child(builtins.object)
| Methods defined here:
|
| diff(self, arg1, arg2)
| diff doc
|
| sum = _method(self, arg2)
| sum doc
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
Python Library Documentation: Child in module __main__ object
class Child(builtins.object)
| Methods defined here:
|
| diff(self, arg1, arg2)
| diff doc
|
| sum = _method(self, arg2)
| sum doc
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
sum doc
sum doc
```
patch :
diff --git a/Lib/functools.py b/Lib/functools.py
index ab7d71e126..751f67fcd0 100644
--- a/Lib/functools.py
+++ b/Lib/functools.py
@@ -398,6 +398,7 @@ class partialmethod(object):
return self.func(*call_args, **call_keywords)
_method.__isabstractmethod__ = self.__isabstractmethod__
_method._partialmethod = self
+ _method.__doc__ = self.func.__doc__ or self.__doc__
return _method
def __get__(self, obj, cls):
diff --git a/Lib/inspect.py b/Lib/inspect.py
index b8a142232b..2c796546b2 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -600,6 +600,9 @@ def getdoc(object):
All tabs are expanded to spaces. To clean up docstrings that are
indented to line up with blocks of code, any whitespace than can be
uniformly removed from the second line onwards is removed."""
+ if isinstance(object, (functools.partialmethod, functools.partial)):
+ return object.func.__doc__
+
try:
doc = object.__doc__
except AttributeError:
----------
nosy: +xtreak
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue30129>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com