summaryrefslogtreecommitdiff
path: root/Lib/inspect.py
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2015-04-03 22:38:53 +0300
committerSerhiy Storchaka <storchaka@gmail.com>2015-04-03 22:38:53 +0300
commit7cad953b314473748a500f636213ff13039ae2e9 (patch)
tree5fd3de6de80b93c9e808f1940d59b3c8784ef58d /Lib/inspect.py
parent510894c2381c1299117f83314ff8cdc2ec5c3042 (diff)
downloadcpython-7cad953b314473748a500f636213ff13039ae2e9.tar.gz
Issue #15582: inspect.getdoc() now follows inheritance chains.
Diffstat (limited to 'Lib/inspect.py')
-rw-r--r--Lib/inspect.py73
1 files changed, 73 insertions, 0 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py
index 98d665dd45..81b1ce8709 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -468,6 +468,74 @@ def indentsize(line):
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.
@@ -478,6 +546,11 @@ def getdoc(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)