diff -r ad92e63de42c Lib/pydoc.py --- a/Lib/pydoc.py Thu Feb 20 23:26:12 2014 +0100 +++ b/Lib/pydoc.py Thu Feb 20 22:47:18 2014 -0800 @@ -137,6 +137,19 @@ inspect.isbuiltin(obj) or inspect.ismethoddescriptor(obj)) +def _is_bound_method(fn): + """ + Returns True if fn is a bound method, regardless of whether + fn was implemented in Python or in C. + """ + if inspect.ismethod(fn): + return True + if inspect.isbuiltin(fn): + self = getattr(fn, '__self__', None) + return not (inspect.ismodule(self) or (self is None)) + return False + + def allmethods(cl): methods = {} for key, value in inspect.getmembers(cl, _is_some_method): @@ -898,7 +911,7 @@ anchor = (cl and cl.__name__ or '') + '-' + name note = '' skipdocs = 0 - if inspect.ismethod(object): + if _is_bound_method(object): imclass = object.__self__.__class__ if cl: if imclass is not cl: @@ -909,7 +922,6 @@ object.__self__.__class__, mod) else: note = ' unbound %s method' % self.classlink(imclass,mod) - object = object.__func__ if name == realname: title = '%s' % (anchor, realname) @@ -924,7 +936,7 @@ title = '%s = %s' % ( anchor, name, reallink) argspec = None - if inspect.isfunction(object) or inspect.isbuiltin(object): + if inspect.isroutine(object): try: signature = inspect.signature(object) except (ValueError, TypeError): @@ -1304,7 +1316,7 @@ name = name or realname note = '' skipdocs = 0 - if inspect.ismethod(object): + if _is_bound_method(object): imclass = object.__self__.__class__ if cl: if imclass is not cl: @@ -1315,7 +1327,6 @@ object.__self__.__class__, mod) else: note = ' unbound %s method' % classname(imclass,mod) - object = object.__func__ if name == realname: title = self.bold(realname) diff -r ad92e63de42c Lib/test/test_pydoc.py --- a/Lib/test/test_pydoc.py Thu Feb 20 23:26:12 2014 +0100 +++ b/Lib/test/test_pydoc.py Thu Feb 20 22:47:18 2014 -0800 @@ -6,6 +6,7 @@ import inspect import pydoc import keyword +import _pickle import pkgutil import re import string @@ -553,6 +554,25 @@ methods = pydoc.allmethods(TestClass) self.assertDictEqual(methods, expected) + @staticmethod + def _get_summary_line(o): + text = pydoc.plain(pydoc.render_doc(o)) + lines = text.split('\n') + assert len(lines) >= 2 + return lines[2] + + # these no longer include "self" + def test_bound_python_method(self): + t = textwrap.TextWrapper() + self.assertEqual(self._get_summary_line(t.wrap), + "wrap(text) method of textwrap.TextWrapper instance") + + @requires_docstrings + def test_bound_builtin_method(self): + s = StringIO() + p = _pickle.Pickler(s) + self.assertEqual(self._get_summary_line(p.dump), + "dump(obj, /) method of _pickle.Pickler instance") class PydocImportTest(PydocBaseTest):