Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 24a882b

Browse files
committed
Issue #20710: The pydoc summary line no longer displays the "self" parameter
for bound methods. Previous to this change, it displayed "self" for methods implemented in Python but not methods implemented in C; it is now both internally consistent and consistent with inspect.Signature.
1 parent 8c185ee commit 24a882b

3 files changed

Lines changed: 54 additions & 10 deletions

File tree

Lib/pydoc.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,19 @@ def _is_some_method(obj):
137137
inspect.isbuiltin(obj) or
138138
inspect.ismethoddescriptor(obj))
139139

140+
def _is_bound_method(fn):
141+
"""
142+
Returns True if fn is a bound method, regardless of whether
143+
fn was implemented in Python or in C.
144+
"""
145+
if inspect.ismethod(fn):
146+
return True
147+
if inspect.isbuiltin(fn):
148+
self = getattr(fn, '__self__', None)
149+
return not (inspect.ismodule(self) or (self is None))
150+
return False
151+
152+
140153
def allmethods(cl):
141154
methods = {}
142155
for key, value in inspect.getmembers(cl, _is_some_method):
@@ -898,7 +911,7 @@ def docroutine(self, object, name=None, mod=None,
898911
anchor = (cl and cl.__name__ or '') + '-' + name
899912
note = ''
900913
skipdocs = 0
901-
if inspect.ismethod(object):
914+
if _is_bound_method(object):
902915
imclass = object.__self__.__class__
903916
if cl:
904917
if imclass is not cl:
@@ -909,7 +922,6 @@ def docroutine(self, object, name=None, mod=None,
909922
object.__self__.__class__, mod)
910923
else:
911924
note = ' unbound %s method' % self.classlink(imclass,mod)
912-
object = object.__func__
913925

914926
if name == realname:
915927
title = '<a name="%s"><strong>%s</strong></a>' % (anchor, realname)
@@ -924,7 +936,7 @@ def docroutine(self, object, name=None, mod=None,
924936
title = '<a name="%s"><strong>%s</strong></a> = %s' % (
925937
anchor, name, reallink)
926938
argspec = None
927-
if inspect.isfunction(object) or inspect.isbuiltin(object):
939+
if inspect.isroutine(object):
928940
try:
929941
signature = inspect.signature(object)
930942
except (ValueError, TypeError):
@@ -1304,7 +1316,7 @@ def docroutine(self, object, name=None, mod=None, cl=None):
13041316
name = name or realname
13051317
note = ''
13061318
skipdocs = 0
1307-
if inspect.ismethod(object):
1319+
if _is_bound_method(object):
13081320
imclass = object.__self__.__class__
13091321
if cl:
13101322
if imclass is not cl:
@@ -1315,7 +1327,6 @@ def docroutine(self, object, name=None, mod=None, cl=None):
13151327
object.__self__.__class__, mod)
13161328
else:
13171329
note = ' unbound %s method' % classname(imclass,mod)
1318-
object = object.__func__
13191330

13201331
if name == realname:
13211332
title = self.bold(realname)

Lib/test/test_pydoc.py

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import inspect
77
import pydoc
88
import keyword
9+
import _pickle
910
import pkgutil
1011
import re
1112
import string
@@ -699,12 +700,41 @@ def test_builtin(self):
699700
self.assertIsNone(pydoc.locate(name))
700701
self.assertRaises(ImportError, pydoc.render_doc, name)
701702

703+
@staticmethod
704+
def _get_summary_line(o):
705+
text = pydoc.plain(pydoc.render_doc(o))
706+
lines = text.split('\n')
707+
assert len(lines) >= 2
708+
return lines[2]
709+
710+
# these should include "self"
711+
def test_unbound_python_method(self):
712+
self.assertEqual(self._get_summary_line(textwrap.TextWrapper.wrap),
713+
"wrap(self, text)")
714+
715+
@requires_docstrings
716+
def test_unbound_builtin_method(self):
717+
self.assertEqual(self._get_summary_line(_pickle.Pickler.dump),
718+
"dump(self, obj, /)")
719+
720+
# these no longer include "self"
721+
def test_bound_python_method(self):
722+
t = textwrap.TextWrapper()
723+
self.assertEqual(self._get_summary_line(t.wrap),
724+
"wrap(text) method of textwrap.TextWrapper instance")
725+
726+
@requires_docstrings
727+
def test_bound_builtin_method(self):
728+
s = StringIO()
729+
p = _pickle.Pickler(s)
730+
self.assertEqual(self._get_summary_line(p.dump),
731+
"dump(obj, /) method of _pickle.Pickler instance")
732+
733+
# this should *never* include self!
702734
@requires_docstrings
703-
def test_builtin_signatures(self):
704-
# test producing signatures from builtins
705-
stat_sig = pydoc.render_doc(os.stat)
706-
self.assertEqual(pydoc.plain(stat_sig).splitlines()[2],
707-
'stat(path, *, dir_fd=None, follow_symlinks=True)')
735+
def test_module_level_callable(self):
736+
self.assertEqual(self._get_summary_line(os.stat),
737+
"stat(path, *, dir_fd=None, follow_symlinks=True)")
708738

709739

710740
@unittest.skipUnless(threading, 'Threading required for this test.')

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ Core and Builtins
2828
Library
2929
-------
3030

31+
- Issue #20710: The pydoc summary line no longer displays the "self" parameter
32+
for bound methods.
33+
3134
- Issue #20654: Fixed pydoc for enums with zero value. Patch by Vajrasky Kok.
3235

3336
- Issue #20635: Fixed grid_columnconfigure() and grid_rowconfigure() methods of

0 commit comments

Comments
 (0)