.. function:: getdoc(object)
Get the documentation string for an object, cleaned up with :func:`cleandoc`.
+ If the documentation string for an object is not provided and the object is
+ a class, a method, a property or a descriptor, retrieve the documentation
+ string from the inheritance hierarchy.
.. function:: getcomments(object)
expline = line.expandtabs()
return len(expline) - len(expline.lstrip())
+def _findclass(func):
+ cls = sys.modules.get(func.__module__)
+ if cls is None:
+ return None
+ for name in func.__qualname__.split('.')[:-1]:
+ cls = getattr(cls, name)
+ if not isclass(cls):
+ return None
+ return cls
+
+def _finddoc(obj):
+ if isclass(obj):
+ for base in obj.__mro__:
+ if base is not object:
+ try:
+ doc = base.__doc__
+ except AttributeError:
+ continue
+ if doc is not None:
+ return doc
+ return None
+
+ if ismethod(obj):
+ name = obj.__func__.__name__
+ self = obj.__self__
+ if (isclass(self) and
+ getattr(getattr(self, name, None), '__func__') is obj.__func__):
+ # classmethod
+ cls = self
+ else:
+ cls = self.__class__
+ elif isfunction(obj):
+ name = obj.__name__
+ cls = _findclass(obj)
+ if cls is None or getattr(cls, name) is not obj:
+ return None
+ elif isbuiltin(obj):
+ name = obj.__name__
+ self = obj.__self__
+ if (isclass(self) and
+ self.__qualname__ + '.' + name == obj.__qualname__):
+ # classmethod
+ cls = self
+ else:
+ cls = self.__class__
+ elif ismethoddescriptor(obj) or isdatadescriptor(obj):
+ name = obj.__name__
+ cls = obj.__objclass__
+ if getattr(cls, name) is not obj:
+ return None
+ elif isinstance(obj, property):
+ func = f.fget
+ name = func.__name__
+ cls = _findclass(func)
+ if cls is None or getattr(cls, name) is not obj:
+ return None
+ else:
+ return None
+
+ for base in cls.__mro__:
+ try:
+ doc = getattr(base, name).__doc__
+ except AttributeError:
+ continue
+ if doc is not None:
+ return doc
+ return None
+
def getdoc(object):
"""Get the documentation string for an object.
doc = object.__doc__
except AttributeError:
return None
+ if doc is None:
+ try:
+ doc = _finddoc(object)
+ except (AttributeError, TypeError):
+ return None
if not isinstance(doc, str):
return None
return cleandoc(doc)
self.ex = sys.exc_info()
self.tr = inspect.trace()
+ def contradiction(self):
+ 'The automatic gainsaying.'
+ pass
+
# line 48
class MalodorousPervert(StupidGit):
- pass
+ def abuse(self, a, b, c):
+ pass
+ def contradiction(self):
+ pass
Tit = MalodorousPervert
pass
class FesteringGob(MalodorousPervert, ParrotDroppings):
- pass
+ def abuse(self, a, b, c):
+ pass
+ def contradiction(self):
+ pass
self.assertEqual(inspect.getdoc(git.abuse),
'Another\n\ndocstring\n\ncontaining\n\ntabs')
+ @unittest.skipIf(sys.flags.optimize >= 2,
+ "Docstrings are omitted with -O2 and above")
+ def test_getdoc_inherited(self):
+ self.assertEqual(inspect.getdoc(mod.FesteringGob),
+ 'A longer,\n\nindented\n\ndocstring.')
+ self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
+ 'Another\n\ndocstring\n\ncontaining\n\ntabs')
+ self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
+ 'Another\n\ndocstring\n\ncontaining\n\ntabs')
+ self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
+ 'The automatic gainsaying.')
+
+ @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
+ def test_finddoc(self):
+ finddoc = inspect._finddoc
+ self.assertEqual(finddoc(int), int.__doc__)
+ self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
+ self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
+ self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
+ self.assertEqual(finddoc(int.real), int.real.__doc__)
+
def test_cleandoc(self):
self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
'An\nindented\ndocstring.')
def test_getsource(self):
self.assertSourceEqual(git.abuse, 29, 39)
- self.assertSourceEqual(mod.StupidGit, 21, 46)
+ self.assertSourceEqual(mod.StupidGit, 21, 50)
def test_getsourcefile(self):
self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
Library
-------
+- Issue #15582: inspect.getdoc() now follows inheritance chains.
+
- Issue #2175: SAX parsers now support a character stream of InputSource object.
- Issue #16840: Tkinter now supports 64-bit integers added in Tcl 8.4 and