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:
parent
a8f75da8f2
commit
e09bc1e8f5
|
@ -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()
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue