diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2019-01-15 08:53:18 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-15 08:53:18 (GMT) |
commit | efcf82f94572abcdbd70336e0b2c3d0f4df280bc (patch) | |
tree | 3af379fca24788ac7196139940ba250148c84114 /Lib/pydoc.py | |
parent | 6fe9c446f8302553952f63fc6d96be4dfa48ceba (diff) | |
download | cpython-efcf82f94572abcdbd70336e0b2c3d0f4df280bc.zip cpython-efcf82f94572abcdbd70336e0b2c3d0f4df280bc.tar.gz cpython-efcf82f94572abcdbd70336e0b2c3d0f4df280bc.tar.bz2 |
bpo-35619: Improve support of custom data descriptors in help() and pydoc. (GH-11366)
Diffstat (limited to 'Lib/pydoc.py')
-rw-r--r-- | Lib/pydoc.py | 52 |
1 files changed, 16 insertions, 36 deletions
diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 59f6e39..daa7205 100644 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -137,12 +137,6 @@ def stripid(text): # The behaviour of %p is implementation-dependent in terms of case. return _re_stripid.sub(r'\1', text) -def _is_some_method(obj): - return (inspect.isfunction(obj) or - inspect.ismethod(obj) or - inspect.isbuiltin(obj) or - inspect.ismethoddescriptor(obj)) - def _is_bound_method(fn): """ Returns True if fn is a bound method, regardless of whether @@ -158,7 +152,7 @@ def _is_bound_method(fn): def allmethods(cl): methods = {} - for key, value in inspect.getmembers(cl, _is_some_method): + for key, value in inspect.getmembers(cl, inspect.isroutine): methods[key] = 1 for base in cl.__bases__: methods.update(allmethods(base)) # all your base are belong to us @@ -379,15 +373,13 @@ class Doc: # identifies something in a way that pydoc itself has issues handling; # think 'super' and how it is a descriptor (which raises the exception # by lacking a __name__ attribute) and an instance. - if inspect.isgetsetdescriptor(object): return self.docdata(*args) - if inspect.ismemberdescriptor(object): return self.docdata(*args) try: if inspect.ismodule(object): return self.docmodule(*args) if inspect.isclass(object): return self.docclass(*args) if inspect.isroutine(object): return self.docroutine(*args) except AttributeError: pass - if isinstance(object, property): return self.docproperty(*args) + if inspect.isdatadescriptor(object): return self.docdata(*args) return self.docother(*args) def fail(self, object, name=None, *args): @@ -809,7 +801,7 @@ class HTMLDoc(Doc): except Exception: # Some descriptors may meet a failure in their __get__. # (bug #1785) - push(self._docdescriptor(name, value, mod)) + push(self.docdata(value, name, mod)) else: push(self.document(value, name, mod, funcs, classes, mdict, object)) @@ -822,7 +814,7 @@ class HTMLDoc(Doc): hr.maybe() push(msg) for name, kind, homecls, value in ok: - push(self._docdescriptor(name, value, mod)) + push(self.docdata(value, name, mod)) return attrs def spilldata(msg, attrs, predicate): @@ -994,32 +986,27 @@ class HTMLDoc(Doc): doc = doc and '<dd><tt>%s</tt></dd>' % doc return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc) - def _docdescriptor(self, name, value, mod): + def docdata(self, object, name=None, mod=None, cl=None): + """Produce html documentation for a data descriptor.""" results = [] push = results.append if name: push('<dl><dt><strong>%s</strong></dt>\n' % name) - if value.__doc__ is not None: - doc = self.markup(getdoc(value), self.preformat) + if object.__doc__ is not None: + doc = self.markup(getdoc(object), self.preformat) push('<dd><tt>%s</tt></dd>\n' % doc) push('</dl>\n') return ''.join(results) - def docproperty(self, object, name=None, mod=None, cl=None): - """Produce html documentation for a property.""" - return self._docdescriptor(name, object, mod) + docproperty = docdata def docother(self, object, name=None, mod=None, *ignored): """Produce HTML documentation for a data object.""" lhs = name and '<strong>%s</strong> = ' % name or '' return lhs + self.repr(object) - def docdata(self, object, name=None, mod=None, cl=None): - """Produce html documentation for a data descriptor.""" - return self._docdescriptor(name, object, mod) - def index(self, dir, shadowed=None): """Generate an HTML index for a directory of modules.""" modpkgs = [] @@ -1292,7 +1279,7 @@ location listed above. except Exception: # Some descriptors may meet a failure in their __get__. # (bug #1785) - push(self._docdescriptor(name, value, mod)) + push(self.docdata(value, name, mod)) else: push(self.document(value, name, mod, object)) @@ -1304,7 +1291,7 @@ location listed above. hr.maybe() push(msg) for name, kind, homecls, value in ok: - push(self._docdescriptor(name, value, mod)) + push(self.docdata(value, name, mod)) return attrs def spilldata(msg, attrs, predicate): @@ -1420,26 +1407,21 @@ location listed above. doc = getdoc(object) or '' return decl + '\n' + (doc and self.indent(doc).rstrip() + '\n') - def _docdescriptor(self, name, value, mod): + def docdata(self, object, name=None, mod=None, cl=None): + """Produce text documentation for a data descriptor.""" results = [] push = results.append if name: push(self.bold(name)) push('\n') - doc = getdoc(value) or '' + doc = getdoc(object) or '' if doc: push(self.indent(doc)) push('\n') return ''.join(results) - def docproperty(self, object, name=None, mod=None, cl=None): - """Produce text documentation for a property.""" - return self._docdescriptor(name, object, mod) - - def docdata(self, object, name=None, mod=None, cl=None): - """Produce text documentation for a data descriptor.""" - return self._docdescriptor(name, object, mod) + docproperty = docdata def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None): """Produce text documentation for a data object.""" @@ -1673,9 +1655,7 @@ def render_doc(thing, title='Python Library Documentation: %s', forceload=0, if not (inspect.ismodule(object) or inspect.isclass(object) or inspect.isroutine(object) or - inspect.isgetsetdescriptor(object) or - inspect.ismemberdescriptor(object) or - isinstance(object, property)): + inspect.isdatadescriptor(object)): # If the passed object is a piece of data or an instance, # document its available methods instead of its value. object = type(object) |