diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2015-04-03 22:38:53 +0300 |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2015-04-03 22:38:53 +0300 |
commit | 7cad953b314473748a500f636213ff13039ae2e9 (patch) | |
tree | 5fd3de6de80b93c9e808f1940d59b3c8784ef58d /Lib/inspect.py | |
parent | 510894c2381c1299117f83314ff8cdc2ec5c3042 (diff) | |
download | cpython-7cad953b314473748a500f636213ff13039ae2e9.tar.gz |
Issue #15582: inspect.getdoc() now follows inheritance chains.
Diffstat (limited to 'Lib/inspect.py')
-rw-r--r-- | Lib/inspect.py | 73 |
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) |