summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_capi.py
diff options
context:
space:
mode:
authorJeroen Demeyer <J.Demeyer@UGent.be>2019-05-29 18:31:52 (GMT)
committerPetr Viktorin <encukou@gmail.com>2019-05-29 18:31:52 (GMT)
commitaacc77fbd77640a8f03638216fa09372cc21673d (patch)
treefd64be1c4c1167a8bf708d1fd22c733cf3a9a30f /Lib/test/test_capi.py
parentd30da5dd9a8a965cf24a22bbaff8a5b1341c2944 (diff)
downloadcpython-aacc77fbd77640a8f03638216fa09372cc21673d.zip
cpython-aacc77fbd77640a8f03638216fa09372cc21673d.tar.gz
cpython-aacc77fbd77640a8f03638216fa09372cc21673d.tar.bz2
bpo-36974: implement PEP 590 (GH-13185)
Co-authored-by: Jeroen Demeyer <J.Demeyer@UGent.be> Co-authored-by: Mark Shannon <mark@hotpy.org>
Diffstat (limited to 'Lib/test/test_capi.py')
-rw-r--r--Lib/test/test_capi.py47
1 files changed, 47 insertions, 0 deletions
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
index f3d41a2..0813abb 100644
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -34,6 +34,11 @@ def testfunction(self):
"""some doc"""
return self
+def testfunction_kw(self, *, kw):
+ """some doc"""
+ return self
+
+
class InstanceMethod:
id = _testcapi.instancemethod(id)
testfunction = _testcapi.instancemethod(testfunction)
@@ -479,6 +484,48 @@ class TestPEP590(unittest.TestCase):
pass
self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
+ def test_vectorcall(self):
+ # Test a bunch of different ways to call objects:
+ # 1. normal call
+ # 2. vectorcall using _PyObject_Vectorcall()
+ # 3. vectorcall using PyVectorcall_Call()
+ # 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)]
+
+ 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)):
+ 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, pyvectorcall_call(func, args))
+ 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, pyvectorcall_call(func, args, kwargs))
+ self.assertEqual(expected, meth(*args1, **kwargs))
+ self.assertEqual(expected, wrapped(*args, **kwargs))
+
class SubinterpreterTest(unittest.TestCase):