diff --git a/Doc/lib/libinspect.tex b/Doc/lib/libinspect.tex index a1293f0e96a..cc41f2f18ed 100644 --- a/Doc/lib/libinspect.tex +++ b/Doc/lib/libinspect.tex @@ -161,6 +161,31 @@ Note: Return true if the object is a user-defined or built-in function or method. \end{funcdesc} +\begin{funcdesc}{ismethoddescriptor}{object} + Return true if the object is a method descriptor, but not if ismethod() or + isclass() or isfunction() are true. + + This is new as of Python 2.2, and, for example, is true of int.__add__. + An object passing this test has a __get__ attribute but not a __set__ + attribute, but beyond that the set of attributes varies. __name__ is + usually sensible, and __doc__ often is. + + Methods implemented via descriptors that also pass one of the other + tests return false from the ismethoddescriptor() test, simply because + the other tests promise more -- you can, e.g., count on having the + im_func attribute (etc) when an object passes ismethod(). +\end{funcdesc} + +\begin{funcdesc}{isdatadescriptor}{object} + Return true if the object is a data descriptor. + + Data descriptors have both a __get__ and a __set__ attribute. Examples are + properties (defined in Python) and getsets and members (defined in C). + Typically, data descriptors will also have __name__ and __doc__ attributes + (properties, getsets, and members have both of these attributes), but this + is not guaranteed. +\end{funcdesc} + \subsection{Retrieving source code \label{inspect-source}} diff --git a/Lib/inspect.py b/Lib/inspect.py index 4baebe0c6f4..a2ea7390bdb 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -78,6 +78,16 @@ def ismethoddescriptor(object): and not isfunction(object) and not isclass(object)) +def isdatadescriptor(object): + """Return true if the object is a data descriptor. + + Data descriptors have both a __get__ and a __set__ attribute. Examples are + properties (defined in Python) and getsets and members (defined in C). + Typically, data descriptors will also have __name__ and __doc__ attributes + (properties, getsets, and members have both of these attributes), but this + is not guaranteed.""" + return (hasattr(object, "__set__") and hasattr(object, "__get__")) + def isfunction(object): """Return true if the object is a user-defined function. diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 7f0adddb19a..8e5064a44db 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -686,7 +686,7 @@ class HTMLDoc(Doc): push(msg) for name, kind, homecls, value in ok: base = self.docother(getattr(object, name), name, mod) - if callable(value): + if callable(value) or inspect.isdatadescriptor(value): doc = getattr(value, "__doc__", None) else: doc = None @@ -1087,7 +1087,7 @@ class TextDoc(Doc): hr.maybe() push(msg) for name, kind, homecls, value in ok: - if callable(value): + if callable(value) or inspect.isdatadescriptor(value): doc = getattr(value, "__doc__", None) else: doc = None diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index d253f26a5fd..33e0b0d7e17 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -61,6 +61,7 @@ class FesteringGob(MalodorousPervert, ParrotDroppings): # isbuiltin, isroutine, getmembers, getdoc, getfile, getmodule, # getsourcefile, getcomments, getsource, getclasstree, getargspec, # getargvalues, formatargspec, formatargvalues, currentframe, stack, trace +# isdatadescriptor from test.test_support import TestFailed, TESTFN import sys, imp, os, string @@ -104,6 +105,8 @@ istest(inspect.ismethod, 'mod.StupidGit.abuse') istest(inspect.ismethod, 'git.argue') istest(inspect.ismodule, 'mod') istest(inspect.istraceback, 'tb') +istest(inspect.isdatadescriptor, '__builtins__.file.closed') +istest(inspect.isdatadescriptor, '__builtins__.file.softspace') test(inspect.isroutine(mod.spam), 'isroutine(mod.spam)') test(inspect.isroutine([].count), 'isroutine([].count)') diff --git a/Misc/NEWS b/Misc/NEWS index a9063e21eb5..05c9ce26ddf 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,9 @@ Extension modules Library ------- +- inspect.is{method|data}descriptor was added, to allow pydoc display + __doc__ of data descriptors. + - Fixed socket speed loss caused by use of the _socketobject wrapper class in socket.py.