summaryrefslogtreecommitdiffstats
path: root/Lib/pydoc.py
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2020-05-18 17:25:07 (GMT)
committerGitHub <noreply@github.com>2020-05-18 17:25:07 (GMT)
commit08b47c367a08f571a986366aa33828d3951fa88d (patch)
treebe06ca168536a48a19f2a093192ad7137ff8aa3c /Lib/pydoc.py
parent98e42d1f882b9b59f587d538c562dbc7d11c64c3 (diff)
downloadcpython-08b47c367a08f571a986366aa33828d3951fa88d.zip
cpython-08b47c367a08f571a986366aa33828d3951fa88d.tar.gz
cpython-08b47c367a08f571a986366aa33828d3951fa88d.tar.bz2
bpo-40257: Revert changes to inspect.getdoc() (GH-20073)
Diffstat (limited to 'Lib/pydoc.py')
-rwxr-xr-xLib/pydoc.py96
1 files changed, 94 insertions, 2 deletions
diff --git a/Lib/pydoc.py b/Lib/pydoc.py
index 898cc44..628f9fc 100755
--- a/Lib/pydoc.py
+++ b/Lib/pydoc.py
@@ -90,9 +90,101 @@ def pathdirs():
normdirs.append(normdir)
return dirs
+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 inspect.isclass(cls):
+ return None
+ return cls
+
+def _finddoc(obj):
+ if inspect.ismethod(obj):
+ name = obj.__func__.__name__
+ self = obj.__self__
+ if (inspect.isclass(self) and
+ getattr(getattr(self, name, None), '__func__') is obj.__func__):
+ # classmethod
+ cls = self
+ else:
+ cls = self.__class__
+ elif inspect.isfunction(obj):
+ name = obj.__name__
+ cls = _findclass(obj)
+ if cls is None or getattr(cls, name) is not obj:
+ return None
+ elif inspect.isbuiltin(obj):
+ name = obj.__name__
+ self = obj.__self__
+ if (inspect.isclass(self) and
+ self.__qualname__ + '.' + name == obj.__qualname__):
+ # classmethod
+ cls = self
+ else:
+ cls = self.__class__
+ # Should be tested before isdatadescriptor().
+ elif isinstance(obj, property):
+ func = obj.fget
+ name = func.__name__
+ cls = _findclass(func)
+ if cls is None or getattr(cls, name) is not obj:
+ return None
+ elif inspect.ismethoddescriptor(obj) or inspect.isdatadescriptor(obj):
+ name = obj.__name__
+ cls = obj.__objclass__
+ if getattr(cls, name) is not obj:
+ return None
+ if inspect.ismemberdescriptor(obj):
+ slots = getattr(cls, '__slots__', None)
+ if isinstance(slots, dict) and name in slots:
+ return slots[name]
+ else:
+ return None
+ for base in cls.__mro__:
+ try:
+ doc = _getowndoc(getattr(base, name))
+ except AttributeError:
+ continue
+ if doc is not None:
+ return doc
+ return None
+
+def _getowndoc(obj):
+ """Get the documentation string for an object if it is not
+ inherited from its class."""
+ try:
+ doc = object.__getattribute__(obj, '__doc__')
+ if doc is None:
+ return None
+ if obj is not type:
+ typedoc = type(obj).__doc__
+ if isinstance(typedoc, str) and typedoc == doc:
+ return None
+ return doc
+ except AttributeError:
+ return None
+
+def _getdoc(object):
+ """Get the documentation string for an object.
+
+ All tabs are expanded to spaces. To clean up docstrings that are
+ indented to line up with blocks of code, any whitespace than can be
+ uniformly removed from the second line onwards is removed."""
+ doc = _getowndoc(object)
+ if doc is None:
+ try:
+ doc = _finddoc(object)
+ except (AttributeError, TypeError):
+ return None
+ if not isinstance(doc, str):
+ return None
+ return inspect.cleandoc(doc)
+
def getdoc(object):
"""Get the doc string or comments for an object."""
- result = inspect.getdoc(object) or inspect.getcomments(object)
+ result = _getdoc(object) or inspect.getcomments(object)
return result and re.sub('^ *\n', '', result.rstrip()) or ''
def splitdoc(doc):
@@ -1669,7 +1761,7 @@ def render_doc(thing, title='Python Library Documentation: %s', forceload=0,
inspect.isclass(object) or
inspect.isroutine(object) or
inspect.isdatadescriptor(object) or
- inspect.getdoc(object)):
+ _getdoc(object)):
# If the passed object is a piece of data or an instance,
# document its available methods instead of its value.
if hasattr(object, '__origin__'):