diff options
author | Weipeng Hong <hongweichen8888@sina.com> | 2022-01-23 17:40:38 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-23 17:40:38 (GMT) |
commit | 691506f4e9408a1205166f99640946ad7822e302 (patch) | |
tree | d94c7f67a708cfa41bb223a6cdc7ece845dedcf2 | |
parent | 76dc047a0e88d10aad0405228d56e94438cdd91c (diff) | |
download | cpython-691506f4e9408a1205166f99640946ad7822e302.zip cpython-691506f4e9408a1205166f99640946ad7822e302.tar.gz cpython-691506f4e9408a1205166f99640946ad7822e302.tar.bz2 |
bpo-46103: Fix inspect.getmembers to only get __bases__ from class (GH-30147)
-rw-r--r-- | Lib/inspect.py | 26 | ||||
-rw-r--r-- | Lib/test/test_inspect.py | 5 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2021-12-16-23-42-54.bpo-46103.LMnZAN.rst | 2 |
3 files changed, 20 insertions, 13 deletions
diff --git a/Lib/inspect.py b/Lib/inspect.py index 879a577..d47f5b7 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -540,23 +540,23 @@ def isabstract(object): return False def _getmembers(object, predicate, getter): + results = [] + processed = set() + names = dir(object) if isclass(object): mro = (object,) + getmro(object) + # add any DynamicClassAttributes to the list of names if object is a class; + # this may result in duplicate entries if, for example, a virtual + # attribute with the same name as a DynamicClassAttribute exists + try: + for base in object.__bases__: + for k, v in base.__dict__.items(): + if isinstance(v, types.DynamicClassAttribute): + names.append(k) + except AttributeError: + pass else: mro = () - results = [] - processed = set() - names = dir(object) - # :dd any DynamicClassAttributes to the list of names if object is a class; - # this may result in duplicate entries if, for example, a virtual - # attribute with the same name as a DynamicClassAttribute exists - try: - for base in object.__bases__: - for k, v in base.__dict__.items(): - if isinstance(v, types.DynamicClassAttribute): - names.append(k) - except AttributeError: - pass for key in names: # First try to get the value via getattr. Some descriptors don't # like calling their __get__ (see bug #1785), so fall back to diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index cdbb9eb..76fa6f7 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1215,8 +1215,13 @@ class TestClassesAndFunctions(unittest.TestCase): @types.DynamicClassAttribute def eggs(self): return 'spam' + class B: + def __getattr__(self, attribute): + return None self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A)) self.assertIn(('eggs', 'spam'), inspect.getmembers(A())) + b = B() + self.assertIn(('__getattr__', b.__getattr__), inspect.getmembers(b)) def test_getmembers_static(self): class A: diff --git a/Misc/NEWS.d/next/Library/2021-12-16-23-42-54.bpo-46103.LMnZAN.rst b/Misc/NEWS.d/next/Library/2021-12-16-23-42-54.bpo-46103.LMnZAN.rst new file mode 100644 index 0000000..3becbc3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-12-16-23-42-54.bpo-46103.LMnZAN.rst @@ -0,0 +1,2 @@ +Now :func:`inspect.getmembers` only gets :attr:`__bases__` attribute from +class type. Patch by Weipeng Hong. |