Kaydet (Commit) e09bc1e8 authored tarafından Antoine Pitrou's avatar Antoine Pitrou

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.
üst a8f75da8
...@@ -247,23 +247,12 @@ def isabstract(object): ...@@ -247,23 +247,12 @@ def isabstract(object):
def getmembers(object, predicate=None): def getmembers(object, predicate=None):
"""Return all members of an object as (name, value) pairs sorted by name. """Return all members of an object as (name, value) pairs sorted by name.
Optionally, only return members that satisfy a given predicate.""" Optionally, only return members that satisfy a given predicate."""
if isclass(object):
mro = (object,) + getmro(object)
else:
mro = ()
results = [] results = []
for key in dir(object): for key in dir(object):
# First try to get the value via __dict__. Some descriptors don't try:
# like calling their __get__ (see bug #1785). value = getattr(object, key)
for base in mro: except AttributeError:
if key in base.__dict__: continue
value = base.__dict__[key]
break
else:
try:
value = getattr(object, key)
except AttributeError:
continue
if not predicate or predicate(value): if not predicate or predicate(value):
results.append((key, value)) results.append((key, value))
results.sort() results.sort()
......
...@@ -600,56 +600,30 @@ class TestClassesAndFunctions(unittest.TestCase): ...@@ -600,56 +600,30 @@ class TestClassesAndFunctions(unittest.TestCase):
if isinstance(builtin, type): if isinstance(builtin, type):
inspect.classify_class_attrs(builtin) inspect.classify_class_attrs(builtin)
def test_getmembers_descriptors(self): def test_getmembers_method(self):
# Old-style classes # Old-style classes
class A: class B:
dd = _BrokenDataDescriptor() def f(self):
md = _BrokenMethodDescriptor() 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), self.assertIn(('f', B.f), inspect.getmembers(B))
[('md', A.__dict__['md'])]) # contrary to spec, ismethod() is also True for unbound methods
self.assertEqual(inspect.getmembers(B, inspect.isdatadescriptor), # (see #1785)
[('dd', A.__dict__['dd'])]) 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 # New-style classes
class A(object): class B(object):
dd = _BrokenDataDescriptor() def f(self):
md = _BrokenMethodDescriptor()
def pred_wrapper(pred):
# A quick'n'dirty way to discard standard attributes of new-style
# classes.
class Empty(object):
pass 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), self.assertIn(('f', B.f), inspect.getmembers(B))
[('md', A.__dict__['md'])]) self.assertIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
self.assertEqual(inspect.getmembers(B, isdatadescriptor), b = B()
[('dd', A.__dict__['dd'])]) self.assertIn(('f', b.f), inspect.getmembers(b))
self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
class TestGetcallargsFunctions(unittest.TestCase): class TestGetcallargsFunctions(unittest.TestCase):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment