Revert part of 13f56cd8dec1 (issue #1785) to avoid breaking getmembers() with unbound methods.

Python 3 isn't affected (unbound methods don't exist).
Thanks to Vincent Pelletier for noticing.
This commit is contained in:
Antoine Pitrou 2012-01-18 17:39:01 +01:00
parent a8f75da8f2
commit e09bc1e8f5
2 changed files with 22 additions and 59 deletions

View File

@ -247,23 +247,12 @@ def isabstract(object):
def getmembers(object, predicate=None):
"""Return all members of an object as (name, value) pairs sorted by name.
Optionally, only return members that satisfy a given predicate."""
if isclass(object):
mro = (object,) + getmro(object)
else:
mro = ()
results = []
for key in dir(object):
# First try to get the value via __dict__. Some descriptors don't
# like calling their __get__ (see bug #1785).
for base in mro:
if key in base.__dict__:
value = base.__dict__[key]
break
else:
try:
value = getattr(object, key)
except AttributeError:
continue
try:
value = getattr(object, key)
except AttributeError:
continue
if not predicate or predicate(value):
results.append((key, value))
results.sort()

View File

@ -600,56 +600,30 @@ class TestClassesAndFunctions(unittest.TestCase):
if isinstance(builtin, type):
inspect.classify_class_attrs(builtin)
def test_getmembers_descriptors(self):
def test_getmembers_method(self):
# Old-style classes
class A:
dd = _BrokenDataDescriptor()
md = _BrokenMethodDescriptor()
class B:
def f(self):
pass
self.assertEqual(inspect.getmembers(A, inspect.ismethoddescriptor),
[('md', A.__dict__['md'])])
self.assertEqual(inspect.getmembers(A, inspect.isdatadescriptor),
[('dd', A.__dict__['dd'])])
class B(A):
pass
self.assertEqual(inspect.getmembers(B, inspect.ismethoddescriptor),
[('md', A.__dict__['md'])])
self.assertEqual(inspect.getmembers(B, inspect.isdatadescriptor),
[('dd', A.__dict__['dd'])])
self.assertIn(('f', B.f), inspect.getmembers(B))
# contrary to spec, ismethod() is also True for unbound methods
# (see #1785)
self.assertIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
b = B()
self.assertIn(('f', b.f), inspect.getmembers(b))
self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
# New-style classes
class A(object):
dd = _BrokenDataDescriptor()
md = _BrokenMethodDescriptor()
def pred_wrapper(pred):
# A quick'n'dirty way to discard standard attributes of new-style
# classes.
class Empty(object):
class B(object):
def f(self):
pass
def wrapped(x):
if hasattr(x, '__name__') and hasattr(Empty, x.__name__):
return False
return pred(x)
return wrapped
ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
[('md', A.__dict__['md'])])
self.assertEqual(inspect.getmembers(A, isdatadescriptor),
[('dd', A.__dict__['dd'])])
class B(A):
pass
self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
[('md', A.__dict__['md'])])
self.assertEqual(inspect.getmembers(B, isdatadescriptor),
[('dd', A.__dict__['dd'])])
self.assertIn(('f', B.f), inspect.getmembers(B))
self.assertIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
b = B()
self.assertIn(('f', b.f), inspect.getmembers(b))
self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
class TestGetcallargsFunctions(unittest.TestCase):