mirror of
https://github.com/python/cpython.git
synced 2025-07-25 12:14:38 +00:00
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
2 changed files with 22 additions and 59 deletions
|
@ -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):
|
||||||
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),
|
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(A, inspect.isdatadescriptor),
|
# (see #1785)
|
||||||
[('dd', A.__dict__['dd'])])
|
self.assertIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
|
||||||
|
b = B()
|
||||||
class B(A):
|
self.assertIn(('f', b.f), inspect.getmembers(b))
|
||||||
pass
|
self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
|
||||||
|
|
||||||
self.assertEqual(inspect.getmembers(B, inspect.ismethoddescriptor),
|
|
||||||
[('md', A.__dict__['md'])])
|
|
||||||
self.assertEqual(inspect.getmembers(B, inspect.isdatadescriptor),
|
|
||||||
[('dd', A.__dict__['dd'])])
|
|
||||||
|
|
||||||
# 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)
|
self.assertIn(('f', B.f), inspect.getmembers(B))
|
||||||
isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
|
self.assertIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
|
||||||
|
b = B()
|
||||||
self.assertEqual(inspect.getmembers(A, 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(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'])])
|
|
||||||
|
|
||||||
|
|
||||||
class TestGetcallargsFunctions(unittest.TestCase):
|
class TestGetcallargsFunctions(unittest.TestCase):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue