[Python-checkins] bpo-37191: Move TestPEP590 from test_capi to test_call (GH-13892)

Victor Stinner webhook-mailer at python.org
Fri Jun 7 11:51:35 EDT 2019


https://github.com/python/cpython/commit/740a84de73ad8d02655de0a084036f4b7e49a01b
commit: 740a84de73ad8d02655de0a084036f4b7e49a01b
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2019-06-07T17:51:28+02:00
summary:

bpo-37191: Move TestPEP590 from test_capi to test_call (GH-13892)

files:
M Lib/test/test_call.py
M Lib/test/test_capi.py

diff --git a/Lib/test/test_call.py b/Lib/test/test_call.py
index 9f0a75b84a03..b4ab74903edb 100644
--- a/Lib/test/test_call.py
+++ b/Lib/test/test_call.py
@@ -475,5 +475,128 @@ def __index__(self):
         # called, which changes the keywords dict.
         compile("pass", "", "exec", x, **x.kwargs)
 
+
+Py_TPFLAGS_HAVE_VECTORCALL = 1 << 11
+Py_TPFLAGS_METHOD_DESCRIPTOR = 1 << 17
+
+
+def testfunction(self):
+    """some doc"""
+    return self
+
+
+def testfunction_kw(self, *, kw):
+    """some doc"""
+    return self
+
+
+class TestPEP590(unittest.TestCase):
+
+    def test_method_descriptor_flag(self):
+        import functools
+        cached = functools.lru_cache(1)(testfunction)
+
+        self.assertFalse(type(repr).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
+        self.assertTrue(type(list.append).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
+        self.assertTrue(type(list.__add__).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
+        self.assertTrue(type(testfunction).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
+        self.assertTrue(type(cached).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
+
+        self.assertTrue(_testcapi.MethodDescriptorBase.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
+        self.assertTrue(_testcapi.MethodDescriptorDerived.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
+        self.assertFalse(_testcapi.MethodDescriptorNopGet.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
+
+        # Heap type should not inherit Py_TPFLAGS_METHOD_DESCRIPTOR
+        class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):
+            pass
+        self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
+
+    def test_vectorcall_flag(self):
+        self.assertTrue(_testcapi.MethodDescriptorBase.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
+        self.assertTrue(_testcapi.MethodDescriptorDerived.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
+        self.assertFalse(_testcapi.MethodDescriptorNopGet.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
+        self.assertTrue(_testcapi.MethodDescriptor2.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
+
+        # Heap type should not inherit Py_TPFLAGS_HAVE_VECTORCALL
+        class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):
+            pass
+        self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
+
+    def test_vectorcall_override(self):
+        # Check that tp_call can correctly override vectorcall.
+        # MethodDescriptorNopGet implements tp_call but it inherits from
+        # MethodDescriptorBase, which implements vectorcall. Since
+        # MethodDescriptorNopGet returns the args tuple when called, we check
+        # additionally that no new tuple is created for this call.
+        args = tuple(range(5))
+        f = _testcapi.MethodDescriptorNopGet()
+        self.assertIs(f(*args), args)
+
+    def test_vectorcall(self):
+        # Test a bunch of different ways to call objects:
+        # 1. vectorcall using PyVectorcall_Call()
+        #   (only for objects that support vectorcall directly)
+        # 2. normal call
+        # 3. vectorcall using _PyObject_Vectorcall()
+        # 4. call as bound method
+        # 5. call using functools.partial
+
+        # A list of (function, args, kwargs, result) calls to test
+        calls = [(len, (range(42),), {}, 42),
+                 (list.append, ([], 0), {}, None),
+                 ([].append, (0,), {}, None),
+                 (sum, ([36],), {"start":6}, 42),
+                 (testfunction, (42,), {}, 42),
+                 (testfunction_kw, (42,), {"kw":None}, 42),
+                 (_testcapi.MethodDescriptorBase(), (0,), {}, True),
+                 (_testcapi.MethodDescriptorDerived(), (0,), {}, True),
+                 (_testcapi.MethodDescriptor2(), (0,), {}, False)]
+
+        from _testcapi import pyobject_vectorcall, pyvectorcall_call
+        from types import MethodType
+        from functools import partial
+
+        def vectorcall(func, args, kwargs):
+            args = *args, *kwargs.values()
+            kwnames = tuple(kwargs)
+            return pyobject_vectorcall(func, args, kwnames)
+
+        for (func, args, kwargs, expected) in calls:
+            with self.subTest(str(func)):
+                if not kwargs:
+                    self.assertEqual(expected, pyvectorcall_call(func, args))
+                self.assertEqual(expected, pyvectorcall_call(func, args, kwargs))
+
+        # Add derived classes (which do not support vectorcall directly,
+        # but do support all other ways of calling).
+
+        class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):
+            pass
+
+        class MethodDescriptorOverridden(_testcapi.MethodDescriptorBase):
+            def __call__(self, n):
+                return 'new'
+
+        calls += [
+            (MethodDescriptorHeap(), (0,), {}, True),
+            (MethodDescriptorOverridden(), (0,), {}, 'new'),
+        ]
+
+        for (func, args, kwargs, expected) in calls:
+            with self.subTest(str(func)):
+                args1 = args[1:]
+                meth = MethodType(func, args[0])
+                wrapped = partial(func)
+                if not kwargs:
+                    self.assertEqual(expected, func(*args))
+                    self.assertEqual(expected, pyobject_vectorcall(func, args, None))
+                    self.assertEqual(expected, meth(*args1))
+                    self.assertEqual(expected, wrapped(*args))
+                self.assertEqual(expected, func(*args, **kwargs))
+                self.assertEqual(expected, vectorcall(func, args, kwargs))
+                self.assertEqual(expected, meth(*args1, **kwargs))
+                self.assertEqual(expected, wrapped(*args, **kwargs))
+
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
index 6a20f479c53f..45fabd599159 100644
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -27,18 +27,11 @@
 # Were we compiled --with-pydebug or with #define Py_DEBUG?
 Py_DEBUG = hasattr(sys, 'gettotalrefcount')
 
-Py_TPFLAGS_HAVE_VECTORCALL = 1 << 11
-Py_TPFLAGS_METHOD_DESCRIPTOR = 1 << 17
-
 
 def testfunction(self):
     """some doc"""
     return self
 
-def testfunction_kw(self, *, kw):
-    """some doc"""
-    return self
-
 
 class InstanceMethod:
     id = _testcapi.instancemethod(id)
@@ -471,114 +464,6 @@ def test_pendingcalls_non_threaded(self):
         self.pendingcalls_wait(l, n)
 
 
-class TestPEP590(unittest.TestCase):
-
-    def test_method_descriptor_flag(self):
-        import functools
-        cached = functools.lru_cache(1)(testfunction)
-
-        self.assertFalse(type(repr).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
-        self.assertTrue(type(list.append).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
-        self.assertTrue(type(list.__add__).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
-        self.assertTrue(type(testfunction).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
-        self.assertTrue(type(cached).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
-
-        self.assertTrue(_testcapi.MethodDescriptorBase.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
-        self.assertTrue(_testcapi.MethodDescriptorDerived.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
-        self.assertFalse(_testcapi.MethodDescriptorNopGet.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
-
-        # Heap type should not inherit Py_TPFLAGS_METHOD_DESCRIPTOR
-        class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):
-            pass
-        self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
-
-    def test_vectorcall_flag(self):
-        self.assertTrue(_testcapi.MethodDescriptorBase.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
-        self.assertTrue(_testcapi.MethodDescriptorDerived.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
-        self.assertFalse(_testcapi.MethodDescriptorNopGet.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
-        self.assertTrue(_testcapi.MethodDescriptor2.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
-
-        # Heap type should not inherit Py_TPFLAGS_HAVE_VECTORCALL
-        class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):
-            pass
-        self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
-
-    def test_vectorcall_override(self):
-        # Check that tp_call can correctly override vectorcall.
-        # MethodDescriptorNopGet implements tp_call but it inherits from
-        # MethodDescriptorBase, which implements vectorcall. Since
-        # MethodDescriptorNopGet returns the args tuple when called, we check
-        # additionally that no new tuple is created for this call.
-        args = tuple(range(5))
-        f = _testcapi.MethodDescriptorNopGet()
-        self.assertIs(f(*args), args)
-
-    def test_vectorcall(self):
-        # Test a bunch of different ways to call objects:
-        # 1. vectorcall using PyVectorcall_Call()
-        #   (only for objects that support vectorcall directly)
-        # 2. normal call
-        # 3. vectorcall using _PyObject_Vectorcall()
-        # 4. call as bound method
-        # 5. call using functools.partial
-
-        # A list of (function, args, kwargs, result) calls to test
-        calls = [(len, (range(42),), {}, 42),
-                 (list.append, ([], 0), {}, None),
-                 ([].append, (0,), {}, None),
-                 (sum, ([36],), {"start":6}, 42),
-                 (testfunction, (42,), {}, 42),
-                 (testfunction_kw, (42,), {"kw":None}, 42),
-                 (_testcapi.MethodDescriptorBase(), (0,), {}, True),
-                 (_testcapi.MethodDescriptorDerived(), (0,), {}, True),
-                 (_testcapi.MethodDescriptor2(), (0,), {}, False)]
-
-        from _testcapi import pyobject_vectorcall, pyvectorcall_call
-        from types import MethodType
-        from functools import partial
-
-        def vectorcall(func, args, kwargs):
-            args = *args, *kwargs.values()
-            kwnames = tuple(kwargs)
-            return pyobject_vectorcall(func, args, kwnames)
-
-        for (func, args, kwargs, expected) in calls:
-            with self.subTest(str(func)):
-                if not kwargs:
-                    self.assertEqual(expected, pyvectorcall_call(func, args))
-                self.assertEqual(expected, pyvectorcall_call(func, args, kwargs))
-
-        # Add derived classes (which do not support vectorcall directly,
-        # but do support all other ways of calling).
-
-        class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):
-            pass
-
-        class MethodDescriptorOverridden(_testcapi.MethodDescriptorBase):
-            def __call__(self, n):
-                return 'new'
-
-        calls += [
-            (MethodDescriptorHeap(), (0,), {}, True),
-            (MethodDescriptorOverridden(), (0,), {}, 'new'),
-        ]
-
-        for (func, args, kwargs, expected) in calls:
-            with self.subTest(str(func)):
-                args1 = args[1:]
-                meth = MethodType(func, args[0])
-                wrapped = partial(func)
-                if not kwargs:
-                    self.assertEqual(expected, func(*args))
-                    self.assertEqual(expected, pyobject_vectorcall(func, args, None))
-                    self.assertEqual(expected, meth(*args1))
-                    self.assertEqual(expected, wrapped(*args))
-                self.assertEqual(expected, func(*args, **kwargs))
-                self.assertEqual(expected, vectorcall(func, args, kwargs))
-                self.assertEqual(expected, meth(*args1, **kwargs))
-                self.assertEqual(expected, wrapped(*args, **kwargs))
-
-
 class SubinterpreterTest(unittest.TestCase):
 
     def test_subinterps(self):



More information about the Python-checkins mailing list