diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2012-01-18 16:39:01 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2012-01-18 16:39:01 (GMT) |
commit | e09bc1e8f54620e938b7e076830b872a8daabd2c (patch) | |
tree | 79bee47d17f3651373481d90b05e1bcdc46539f3 | |
parent | a8f75da8f2231a7e313792b74eaf06485f7cb86c (diff) | |
download | cpython-e09bc1e8f54620e938b7e076830b872a8daabd2c.zip cpython-e09bc1e8f54620e938b7e076830b872a8daabd2c.tar.gz cpython-e09bc1e8f54620e938b7e076830b872a8daabd2c.tar.bz2 |
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.
-rw-r--r-- | Lib/inspect.py | 19 | ||||
-rw-r--r-- | Lib/test/test_inspect.py | 62 |
2 files changed, 22 insertions, 59 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py index cb07b9d..66d5186 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -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() diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 97de7a0..30b1556 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -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() - - 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 + class B: + def f(self): + 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): |