]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-46103: Fix inspect.getmembers to only get __bases__ from class (GH-30147)
authorWeipeng Hong <hongweichen8888@sina.com>
Sun, 23 Jan 2022 17:40:38 +0000 (01:40 +0800)
committerGitHub <noreply@github.com>
Sun, 23 Jan 2022 17:40:38 +0000 (09:40 -0800)
Lib/inspect.py
Lib/test/test_inspect.py
Misc/NEWS.d/next/Library/2021-12-16-23-42-54.bpo-46103.LMnZAN.rst [new file with mode: 0644]

index 879a577d43fbedcf6131ec7c1e846db9ad1c7faa..d47f5b717471ce5646bbd00937c76e809a2ff240 100644 (file)
@@ -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
index cdbb9eb6a8f7cd239061fa33e1ed0e8cf614220e..76fa6f7e2dab8495adafdcc40a342d2c8727254b 100644 (file)
@@ -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 (file)
index 0000000..3becbc3
--- /dev/null
@@ -0,0 +1,2 @@
+Now :func:`inspect.getmembers` only gets :attr:`__bases__` attribute from
+class type. Patch by Weipeng Hong.