summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/inspect.py34
-rwxr-xr-xLib/pydoc.py22
-rw-r--r--Lib/test/test_inspect.py18
-rw-r--r--Lib/types.py14
4 files changed, 83 insertions, 5 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py
index dc2fa08..0cbf521 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -89,6 +89,40 @@ def isdatadescriptor(object):
is not guaranteed."""
return (hasattr(object, "__set__") and hasattr(object, "__get__"))
+if hasattr(types, 'MemberDescriptorType'):
+ # CPython and equivalent
+ def ismemberdescriptor(object):
+ """Return true if the object is a member descriptor.
+
+ Member descriptors are specialized descriptors defined in extension
+ modules."""
+ return isinstance(object, types.MemberDescriptorType)
+else:
+ # Other implementations
+ def ismemberdescriptor(object):
+ """Return true if the object is a member descriptor.
+
+ Member descriptors are specialized descriptors defined in extension
+ modules."""
+ return False
+
+if hasattr(types, 'GetSetDescriptorType'):
+ # CPython and equivalent
+ def isgetsetdescriptor(object):
+ """Return true if the object is a getset descriptor.
+
+ getset descriptors are specialized descriptors defined in extension
+ modules."""
+ return isinstance(object, types.GetSetDescriptorType)
+else:
+ # Other implementations
+ def isgetsetdescriptor(object):
+ """Return true if the object is a getset descriptor.
+
+ getset descriptors are specialized descriptors defined in extension
+ modules."""
+ return False
+
def isfunction(object):
"""Return true if the object is a user-defined function.
diff --git a/Lib/pydoc.py b/Lib/pydoc.py
index ff6e7ca..0fc624e 100755
--- a/Lib/pydoc.py
+++ b/Lib/pydoc.py
@@ -318,6 +318,8 @@ 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)
@@ -333,7 +335,7 @@ class Doc:
name and ' ' + repr(name), type(object).__name__)
raise TypeError, message
- docmodule = docclass = docroutine = docother = fail
+ docmodule = docclass = docroutine = docother = docproperty = docdata = fail
def getdocloc(self, object):
"""Return the location of module docs or None"""
@@ -915,6 +917,10 @@ class HTMLDoc(Doc):
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 = []
@@ -1268,6 +1274,10 @@ class TextDoc(Doc):
"""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)
+
def docother(self, object, name=None, mod=None, parent=None, maxlen=None, doc=None):
"""Produce text documentation for a data object."""
repr = self.repr(object)
@@ -1397,6 +1407,14 @@ def describe(thing):
return 'module ' + thing.__name__
if inspect.isbuiltin(thing):
return 'built-in function ' + thing.__name__
+ if inspect.isgetsetdescriptor(thing):
+ return 'getset descriptor %s.%s.%s' % (
+ thing.__objclass__.__module__, thing.__objclass__.__name__,
+ thing.__name__)
+ if inspect.ismemberdescriptor(thing):
+ return 'member descriptor %s.%s.%s' % (
+ thing.__objclass__.__module__, thing.__objclass__.__name__,
+ thing.__name__)
if inspect.isclass(thing):
return 'class ' + thing.__name__
if inspect.isfunction(thing):
@@ -1453,6 +1471,8 @@ def 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)):
# If the passed object is a piece of data or an instance,
# document its available methods instead of its value.
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index 76f2566..928af07 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -1,6 +1,8 @@
import sys
+import types
import unittest
import inspect
+import datetime
from test.test_support import TESTFN, run_unittest
@@ -40,10 +42,11 @@ class IsTestBase(unittest.TestCase):
self.failIf(other(obj), 'not %s(%s)' % (other.__name__, exp))
class TestPredicates(IsTestBase):
- def test_eleven(self):
- # Doc/lib/libinspect.tex claims there are 11 such functions
+ def test_thirteen(self):
+ # Doc/lib/libinspect.tex claims there are 13 such functions
count = len(filter(lambda x:x.startswith('is'), dir(inspect)))
- self.assertEqual(count, 11, "There are %d (not 11) is* functions" % count)
+ self.assertEqual(count, 13,
+ "There are %d (not 12) is* functions" % count)
def test_excluding_predicates(self):
self.istest(inspect.isbuiltin, 'sys.exit')
@@ -58,6 +61,15 @@ class TestPredicates(IsTestBase):
self.istest(inspect.istraceback, 'tb')
self.istest(inspect.isdatadescriptor, '__builtin__.file.closed')
self.istest(inspect.isdatadescriptor, '__builtin__.file.softspace')
+ if hasattr(types, 'GetSetDescriptorType'):
+ self.istest(inspect.isgetsetdescriptor,
+ 'type(tb.tb_frame).f_locals')
+ else:
+ self.failIf(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
+ if hasattr(types, 'MemberDescriptorType'):
+ self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
+ else:
+ self.failIf(inspect.ismemberdescriptor(datetime.timedelta.days))
def test_isroutine(self):
self.assert_(inspect.isroutine(mod.spam))
diff --git a/Lib/types.py b/Lib/types.py
index 39812ac..6c8c2b2 100644
--- a/Lib/types.py
+++ b/Lib/types.py
@@ -86,4 +86,16 @@ EllipsisType = type(Ellipsis)
DictProxyType = type(TypeType.__dict__)
NotImplementedType = type(NotImplemented)
-del sys, _f, _g, _C, _x # Not for export
+# Extension types defined in a C helper module. XXX There may be no
+# equivalent in implementations other than CPython, so it seems better to
+# leave them undefined then to set them to e.g. None.
+try:
+ import _types
+except ImportError:
+ pass
+else:
+ GetSetDescriptorType = type(_types.Helper.getter)
+ MemberDescriptorType = type(_types.Helper.member)
+ del _types
+
+del sys, _f, _g, _C, _x # Not for export