diff --git a/Lib/inspect.py b/Lib/inspect.py index 5bb6a83f194..c4c15f51dd3 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -57,6 +57,23 @@ def ismethod(object): im_self instance to which this method is bound, or None""" return isinstance(object, types.MethodType) +def ismethoddescriptor(object): + """Return true if the object is a method descriptor, and ismethod false. + + This is new in 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 the ismethod() test + return false from the ismethoddescriptor() test, simply because + ismethod() is more informative -- you can, e.g., count on having the + im_func attribute (etc) when an object passes the latter.""" + return (hasattr(object, "__get__") + and not hasattr(object, "__set__") # else it's a data descriptor + and not ismethod(object) # mutual exclusion + and not isclass(object)) + def isfunction(object): """Return true if the object is a user-defined function. @@ -127,7 +144,10 @@ def isbuiltin(object): def isroutine(object): """Return true if the object is any kind of function or method.""" - return isbuiltin(object) or isfunction(object) or ismethod(object) + return (isbuiltin(object) + or isfunction(object) + or ismethod(object) + or ismethoddescriptor(object)) def getmembers(object, predicate=None): """Return all members of an object as (name, value) pairs sorted by name. diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 4c7471afbc0..b8050318b04 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -115,9 +115,12 @@ def stripid(text): return re.sub(pattern, '>', text) return text +def _is_some_method(object): + return inspect.ismethod(object) or inspect.ismethoddescriptor(object) + def allmethods(cl): methods = {} - for key, value in inspect.getmembers(cl, inspect.ismethod): + for key, value in inspect.getmembers(cl, _is_some_method): methods[key] = 1 for base in cl.__bases__: methods.update(allmethods(base)) # all your base are belong to us @@ -656,7 +659,7 @@ TT { font-family: lucidatypewriter, lucida console, courier } reallink = realname title = '%s = %s' % ( anchor, name, reallink) - if inspect.isbuiltin(object): + if inspect.isbuiltin(object) or inspect.ismethoddescriptor(object): argspec = '(...)' else: args, varargs, varkw, defaults = inspect.getargspec(object) @@ -913,7 +916,7 @@ class TextDoc(Doc): cl.__dict__[realname] is object): skipdocs = 1 title = self.bold(name) + ' = ' + realname - if inspect.isbuiltin(object): + if inspect.isbuiltin(object) or inspect.ismethoddescriptor(object): argspec = '(...)' else: args, varargs, varkw, defaults = inspect.getargspec(object)