blob: 3f459222748b3a86c88489ceafa7a554bf7744b8 [file] [log] [blame]
Jeremy Hyltonbea39472001-05-29 16:26:20 +00001import unittest
Serhiy Storchaka5eb788b2017-06-06 18:45:22 +03002from test.support import cpython_only
Victor Stinner3b5cf852017-06-09 16:48:45 +02003try:
4 import _testcapi
5except ImportError:
6 _testcapi = None
Sylvain96c7c062017-06-15 17:05:23 +02007import struct
8import collections
Oren Milmanbf9075a2017-08-23 21:16:48 +03009import itertools
Jeroen Demeyer77aa3962019-05-22 13:09:35 +020010import gc
Dennis Sweeneyb5cc2082020-05-22 16:40:17 -040011import contextlib
Jeremy Hyltonbea39472001-05-29 16:26:20 +000012
INADA Naoki2aaf98c2018-09-26 12:59:00 +090013
14class FunctionCalls(unittest.TestCase):
15
16 def test_kwargs_order(self):
17 # bpo-34320: **kwargs should preserve order of passed OrderedDict
18 od = collections.OrderedDict([('a', 1), ('b', 2)])
19 od.move_to_end('a')
20 expected = list(od.items())
21
22 def fn(**kw):
23 return kw
24
25 res = fn(**od)
26 self.assertIsInstance(res, dict)
27 self.assertEqual(list(res.items()), expected)
28
29
Serhiy Storchaka5eb788b2017-06-06 18:45:22 +030030@cpython_only
31class CFunctionCallsErrorMessages(unittest.TestCase):
32
33 def test_varargs0(self):
34 msg = r"__contains__\(\) takes exactly one argument \(0 given\)"
35 self.assertRaisesRegex(TypeError, msg, {}.__contains__)
36
37 def test_varargs2(self):
38 msg = r"__contains__\(\) takes exactly one argument \(2 given\)"
39 self.assertRaisesRegex(TypeError, msg, {}.__contains__, 0, 1)
40
Serhiy Storchakaf9f1cca2017-06-09 19:27:06 +030041 def test_varargs3(self):
Serhiy Storchakaf2f55e72019-03-13 23:03:22 +020042 msg = r"^from_bytes\(\) takes exactly 2 positional arguments \(3 given\)"
Serhiy Storchakaf9f1cca2017-06-09 19:27:06 +030043 self.assertRaisesRegex(TypeError, msg, int.from_bytes, b'a', 'little', False)
44
Xtreak63262782018-12-21 20:15:13 +053045 def test_varargs1min(self):
Xtreak1426daa2018-07-23 01:43:26 +053046 msg = r"get expected at least 1 argument, got 0"
47 self.assertRaisesRegex(TypeError, msg, {}.get)
48
Xtreak63262782018-12-21 20:15:13 +053049 msg = r"expected 1 argument, got 0"
50 self.assertRaisesRegex(TypeError, msg, {}.__delattr__)
51
52 def test_varargs2min(self):
Xtreak1426daa2018-07-23 01:43:26 +053053 msg = r"getattr expected at least 2 arguments, got 0"
54 self.assertRaisesRegex(TypeError, msg, getattr)
55
Xtreak63262782018-12-21 20:15:13 +053056 def test_varargs1max(self):
Xtreak1426daa2018-07-23 01:43:26 +053057 msg = r"input expected at most 1 argument, got 2"
58 self.assertRaisesRegex(TypeError, msg, input, 1, 2)
59
Xtreak63262782018-12-21 20:15:13 +053060 def test_varargs2max(self):
Xtreak1426daa2018-07-23 01:43:26 +053061 msg = r"get expected at most 2 arguments, got 3"
62 self.assertRaisesRegex(TypeError, msg, {}.get, 1, 2, 3)
63
Serhiy Storchaka5eb788b2017-06-06 18:45:22 +030064 def test_varargs1_kw(self):
65 msg = r"__contains__\(\) takes no keyword arguments"
66 self.assertRaisesRegex(TypeError, msg, {}.__contains__, x=2)
67
68 def test_varargs2_kw(self):
69 msg = r"__contains__\(\) takes no keyword arguments"
70 self.assertRaisesRegex(TypeError, msg, {}.__contains__, x=2, y=2)
71
Sylvain74453812017-06-10 06:51:48 +020072 def test_varargs3_kw(self):
73 msg = r"bool\(\) takes no keyword arguments"
74 self.assertRaisesRegex(TypeError, msg, bool, x=2)
75
76 def test_varargs4_kw(self):
Jeroen Demeyerbf17d412019-11-05 16:48:04 +010077 msg = r"^list[.]index\(\) takes no keyword arguments$"
Sylvain74453812017-06-10 06:51:48 +020078 self.assertRaisesRegex(TypeError, msg, [].index, x=2)
79
80 def test_varargs5_kw(self):
81 msg = r"^hasattr\(\) takes no keyword arguments$"
82 self.assertRaisesRegex(TypeError, msg, hasattr, x=2)
83
Sylvain96c7c062017-06-15 17:05:23 +020084 def test_varargs6_kw(self):
85 msg = r"^getattr\(\) takes no keyword arguments$"
86 self.assertRaisesRegex(TypeError, msg, getattr, x=2)
87
88 def test_varargs7_kw(self):
89 msg = r"^next\(\) takes no keyword arguments$"
90 self.assertRaisesRegex(TypeError, msg, next, x=2)
91
92 def test_varargs8_kw(self):
Jeroen Demeyerbf17d412019-11-05 16:48:04 +010093 msg = r"^_struct[.]pack\(\) takes no keyword arguments$"
Sylvain96c7c062017-06-15 17:05:23 +020094 self.assertRaisesRegex(TypeError, msg, struct.pack, x=2)
95
96 def test_varargs9_kw(self):
Jeroen Demeyerbf17d412019-11-05 16:48:04 +010097 msg = r"^_struct[.]pack_into\(\) takes no keyword arguments$"
Sylvain96c7c062017-06-15 17:05:23 +020098 self.assertRaisesRegex(TypeError, msg, struct.pack_into, x=2)
99
100 def test_varargs10_kw(self):
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100101 msg = r"^deque[.]index\(\) takes no keyword arguments$"
Sylvain96c7c062017-06-15 17:05:23 +0200102 self.assertRaisesRegex(TypeError, msg, collections.deque().index, x=2)
103
104 def test_varargs11_kw(self):
Jeroen Demeyerbf17d412019-11-05 16:48:04 +0100105 msg = r"^Struct[.]pack\(\) takes no keyword arguments$"
Sylvain96c7c062017-06-15 17:05:23 +0200106 self.assertRaisesRegex(TypeError, msg, struct.Struct.pack, struct.Struct(""), x=2)
107
Sylvain96480882017-07-09 05:45:06 +0200108 def test_varargs12_kw(self):
109 msg = r"^staticmethod\(\) takes no keyword arguments$"
110 self.assertRaisesRegex(TypeError, msg, staticmethod, func=id)
111
112 def test_varargs13_kw(self):
113 msg = r"^classmethod\(\) takes no keyword arguments$"
114 self.assertRaisesRegex(TypeError, msg, classmethod, func=id)
115
Oren Milmanbf9075a2017-08-23 21:16:48 +0300116 def test_varargs14_kw(self):
117 msg = r"^product\(\) takes at most 1 keyword argument \(2 given\)$"
118 self.assertRaisesRegex(TypeError, msg,
119 itertools.product, 0, repeat=1, foo=2)
120
121 def test_varargs15_kw(self):
122 msg = r"^ImportError\(\) takes at most 2 keyword arguments \(3 given\)$"
123 self.assertRaisesRegex(TypeError, msg,
124 ImportError, 0, name=1, path=2, foo=3)
125
126 def test_varargs16_kw(self):
127 msg = r"^min\(\) takes at most 2 keyword arguments \(3 given\)$"
128 self.assertRaisesRegex(TypeError, msg,
129 min, 0, default=1, key=2, foo=3)
130
131 def test_varargs17_kw(self):
132 msg = r"^print\(\) takes at most 4 keyword arguments \(5 given\)$"
133 self.assertRaisesRegex(TypeError, msg,
134 print, 0, sep=1, end=2, file=3, flush=4, foo=5)
135
Serhiy Storchaka5eb788b2017-06-06 18:45:22 +0300136 def test_oldargs0_1(self):
137 msg = r"keys\(\) takes no arguments \(1 given\)"
138 self.assertRaisesRegex(TypeError, msg, {}.keys, 0)
139
140 def test_oldargs0_2(self):
141 msg = r"keys\(\) takes no arguments \(2 given\)"
142 self.assertRaisesRegex(TypeError, msg, {}.keys, 0, 1)
143
144 def test_oldargs0_1_kw(self):
145 msg = r"keys\(\) takes no keyword arguments"
146 self.assertRaisesRegex(TypeError, msg, {}.keys, x=2)
147
148 def test_oldargs0_2_kw(self):
149 msg = r"keys\(\) takes no keyword arguments"
150 self.assertRaisesRegex(TypeError, msg, {}.keys, x=2, y=2)
151
152 def test_oldargs1_0(self):
153 msg = r"count\(\) takes exactly one argument \(0 given\)"
154 self.assertRaisesRegex(TypeError, msg, [].count)
155
156 def test_oldargs1_2(self):
157 msg = r"count\(\) takes exactly one argument \(2 given\)"
158 self.assertRaisesRegex(TypeError, msg, [].count, 1, 2)
159
160 def test_oldargs1_0_kw(self):
161 msg = r"count\(\) takes no keyword arguments"
162 self.assertRaisesRegex(TypeError, msg, [].count, x=2)
163
164 def test_oldargs1_1_kw(self):
165 msg = r"count\(\) takes no keyword arguments"
166 self.assertRaisesRegex(TypeError, msg, [].count, {}, x=2)
167
168 def test_oldargs1_2_kw(self):
169 msg = r"count\(\) takes no keyword arguments"
170 self.assertRaisesRegex(TypeError, msg, [].count, x=2, y=2)
171
172
Petr Viktorinf9583772019-09-10 12:21:09 +0100173
174class TestCallingConventions(unittest.TestCase):
175 """Test calling using various C calling conventions (METH_*) from Python
176
177 Subclasses test several kinds of functions (module-level, methods,
178 class methods static methods) using these attributes:
179 obj: the object that contains tested functions (as attributes)
180 expected_self: expected "self" argument to the C function
181
182 The base class tests module-level functions.
183 """
184
185 def setUp(self):
186 self.obj = self.expected_self = _testcapi
187
188 def test_varargs(self):
189 self.assertEqual(
190 self.obj.meth_varargs(1, 2, 3),
191 (self.expected_self, (1, 2, 3)),
192 )
193
194 def test_varargs_ext(self):
195 self.assertEqual(
196 self.obj.meth_varargs(*(1, 2, 3)),
197 (self.expected_self, (1, 2, 3)),
198 )
199
200 def test_varargs_error_kw(self):
201 msg = r"meth_varargs\(\) takes no keyword arguments"
202 self.assertRaisesRegex(
203 TypeError, msg, lambda: self.obj.meth_varargs(k=1),
204 )
205
206 def test_varargs_keywords(self):
207 self.assertEqual(
208 self.obj.meth_varargs_keywords(1, 2, a=3, b=4),
209 (self.expected_self, (1, 2), {'a': 3, 'b': 4})
210 )
211
212 def test_varargs_keywords_ext(self):
213 self.assertEqual(
214 self.obj.meth_varargs_keywords(*[1, 2], **{'a': 3, 'b': 4}),
215 (self.expected_self, (1, 2), {'a': 3, 'b': 4})
216 )
217
218 def test_o(self):
219 self.assertEqual(self.obj.meth_o(1), (self.expected_self, 1))
220
221 def test_o_ext(self):
222 self.assertEqual(self.obj.meth_o(*[1]), (self.expected_self, 1))
223
224 def test_o_error_no_arg(self):
225 msg = r"meth_o\(\) takes exactly one argument \(0 given\)"
226 self.assertRaisesRegex(TypeError, msg, self.obj.meth_o)
227
228 def test_o_error_two_args(self):
229 msg = r"meth_o\(\) takes exactly one argument \(2 given\)"
230 self.assertRaisesRegex(
231 TypeError, msg, lambda: self.obj.meth_o(1, 2),
232 )
233
234 def test_o_error_ext(self):
235 msg = r"meth_o\(\) takes exactly one argument \(3 given\)"
236 self.assertRaisesRegex(
237 TypeError, msg, lambda: self.obj.meth_o(*(1, 2, 3)),
238 )
239
240 def test_o_error_kw(self):
241 msg = r"meth_o\(\) takes no keyword arguments"
242 self.assertRaisesRegex(
243 TypeError, msg, lambda: self.obj.meth_o(k=1),
244 )
245
246 def test_o_error_arg_kw(self):
247 msg = r"meth_o\(\) takes no keyword arguments"
248 self.assertRaisesRegex(
249 TypeError, msg, lambda: self.obj.meth_o(k=1),
250 )
251
252 def test_noargs(self):
253 self.assertEqual(self.obj.meth_noargs(), self.expected_self)
254
255 def test_noargs_ext(self):
256 self.assertEqual(self.obj.meth_noargs(*[]), self.expected_self)
257
258 def test_noargs_error_arg(self):
259 msg = r"meth_noargs\(\) takes no arguments \(1 given\)"
260 self.assertRaisesRegex(
261 TypeError, msg, lambda: self.obj.meth_noargs(1),
262 )
263
264 def test_noargs_error_arg2(self):
265 msg = r"meth_noargs\(\) takes no arguments \(2 given\)"
266 self.assertRaisesRegex(
267 TypeError, msg, lambda: self.obj.meth_noargs(1, 2),
268 )
269
270 def test_noargs_error_ext(self):
271 msg = r"meth_noargs\(\) takes no arguments \(3 given\)"
272 self.assertRaisesRegex(
273 TypeError, msg, lambda: self.obj.meth_noargs(*(1, 2, 3)),
274 )
275
276 def test_noargs_error_kw(self):
277 msg = r"meth_noargs\(\) takes no keyword arguments"
278 self.assertRaisesRegex(
279 TypeError, msg, lambda: self.obj.meth_noargs(k=1),
280 )
281
282 def test_fastcall(self):
283 self.assertEqual(
284 self.obj.meth_fastcall(1, 2, 3),
285 (self.expected_self, (1, 2, 3)),
286 )
287
288 def test_fastcall_ext(self):
289 self.assertEqual(
290 self.obj.meth_fastcall(*(1, 2, 3)),
291 (self.expected_self, (1, 2, 3)),
292 )
293
294 def test_fastcall_error_kw(self):
295 msg = r"meth_fastcall\(\) takes no keyword arguments"
296 self.assertRaisesRegex(
297 TypeError, msg, lambda: self.obj.meth_fastcall(k=1),
298 )
299
300 def test_fastcall_keywords(self):
301 self.assertEqual(
302 self.obj.meth_fastcall_keywords(1, 2, a=3, b=4),
303 (self.expected_self, (1, 2), {'a': 3, 'b': 4})
304 )
305
306 def test_fastcall_keywords_ext(self):
307 self.assertEqual(
308 self.obj.meth_fastcall_keywords(*(1, 2), **{'a': 3, 'b': 4}),
309 (self.expected_self, (1, 2), {'a': 3, 'b': 4})
310 )
311
312
313class TestCallingConventionsInstance(TestCallingConventions):
314 """Test calling instance methods using various calling conventions"""
315
316 def setUp(self):
317 self.obj = self.expected_self = _testcapi.MethInstance()
318
319
320class TestCallingConventionsClass(TestCallingConventions):
321 """Test calling class methods using various calling conventions"""
322
323 def setUp(self):
324 self.obj = self.expected_self = _testcapi.MethClass
325
326
327class TestCallingConventionsClassInstance(TestCallingConventions):
328 """Test calling class methods on instance"""
329
330 def setUp(self):
331 self.obj = _testcapi.MethClass()
332 self.expected_self = _testcapi.MethClass
333
334
335class TestCallingConventionsStatic(TestCallingConventions):
336 """Test calling static methods using various calling conventions"""
337
338 def setUp(self):
339 self.obj = _testcapi.MethStatic()
340 self.expected_self = None
341
342
Victor Stinner3b5cf852017-06-09 16:48:45 +0200343def pyfunc(arg1, arg2):
344 return [arg1, arg2]
345
346
347def pyfunc_noarg():
348 return "noarg"
349
350
351class PythonClass:
352 def method(self, arg1, arg2):
353 return [arg1, arg2]
354
355 def method_noarg(self):
356 return "noarg"
357
358 @classmethod
359 def class_method(cls):
360 return "classmethod"
361
362 @staticmethod
363 def static_method():
364 return "staticmethod"
365
366
367PYTHON_INSTANCE = PythonClass()
368
Petr Viktorinf9583772019-09-10 12:21:09 +0100369NULL_OR_EMPTY = object()
Victor Stinner3b5cf852017-06-09 16:48:45 +0200370
Victor Stinner3b5cf852017-06-09 16:48:45 +0200371class FastCallTests(unittest.TestCase):
Petr Viktorinf9583772019-09-10 12:21:09 +0100372 """Test calling using various callables from C
373 """
374
Victor Stinner3b5cf852017-06-09 16:48:45 +0200375 # Test calls with positional arguments
Petr Viktorinf9583772019-09-10 12:21:09 +0100376 CALLS_POSARGS = [
Victor Stinner3b5cf852017-06-09 16:48:45 +0200377 # (func, args: tuple, result)
378
379 # Python function with 2 arguments
380 (pyfunc, (1, 2), [1, 2]),
381
382 # Python function without argument
383 (pyfunc_noarg, (), "noarg"),
384
385 # Python class methods
386 (PythonClass.class_method, (), "classmethod"),
387 (PythonClass.static_method, (), "staticmethod"),
388
389 # Python instance methods
390 (PYTHON_INSTANCE.method, (1, 2), [1, 2]),
391 (PYTHON_INSTANCE.method_noarg, (), "noarg"),
392 (PYTHON_INSTANCE.class_method, (), "classmethod"),
393 (PYTHON_INSTANCE.static_method, (), "staticmethod"),
394
Petr Viktorinf9583772019-09-10 12:21:09 +0100395 # C callables are added later
396 ]
Victor Stinner3b5cf852017-06-09 16:48:45 +0200397
398 # Test calls with positional and keyword arguments
Petr Viktorinf9583772019-09-10 12:21:09 +0100399 CALLS_KWARGS = [
Victor Stinner3b5cf852017-06-09 16:48:45 +0200400 # (func, args: tuple, kwargs: dict, result)
401
402 # Python function with 2 arguments
403 (pyfunc, (1,), {'arg2': 2}, [1, 2]),
404 (pyfunc, (), {'arg1': 1, 'arg2': 2}, [1, 2]),
405
406 # Python instance methods
407 (PYTHON_INSTANCE.method, (1,), {'arg2': 2}, [1, 2]),
408 (PYTHON_INSTANCE.method, (), {'arg1': 1, 'arg2': 2}, [1, 2]),
409
Petr Viktorinf9583772019-09-10 12:21:09 +0100410 # C callables are added later
411 ]
Victor Stinner3b5cf852017-06-09 16:48:45 +0200412
Petr Viktorinf9583772019-09-10 12:21:09 +0100413 # Add all the calling conventions and variants of C callables
414 _instance = _testcapi.MethInstance()
415 for obj, expected_self in (
416 (_testcapi, _testcapi), # module-level function
417 (_instance, _instance), # bound method
418 (_testcapi.MethClass, _testcapi.MethClass), # class method on class
419 (_testcapi.MethClass(), _testcapi.MethClass), # class method on inst.
420 (_testcapi.MethStatic, None), # static method
421 ):
422 CALLS_POSARGS.extend([
423 (obj.meth_varargs, (1, 2), (expected_self, (1, 2))),
424 (obj.meth_varargs_keywords,
425 (1, 2), (expected_self, (1, 2), NULL_OR_EMPTY)),
426 (obj.meth_fastcall, (1, 2), (expected_self, (1, 2))),
427 (obj.meth_fastcall, (), (expected_self, ())),
428 (obj.meth_fastcall_keywords,
429 (1, 2), (expected_self, (1, 2), NULL_OR_EMPTY)),
430 (obj.meth_fastcall_keywords,
431 (), (expected_self, (), NULL_OR_EMPTY)),
432 (obj.meth_noargs, (), expected_self),
433 (obj.meth_o, (123, ), (expected_self, 123)),
434 ])
435
436 CALLS_KWARGS.extend([
437 (obj.meth_varargs_keywords,
438 (1, 2), {'x': 'y'}, (expected_self, (1, 2), {'x': 'y'})),
439 (obj.meth_varargs_keywords,
440 (), {'x': 'y'}, (expected_self, (), {'x': 'y'})),
441 (obj.meth_varargs_keywords,
442 (1, 2), {}, (expected_self, (1, 2), NULL_OR_EMPTY)),
443 (obj.meth_fastcall_keywords,
444 (1, 2), {'x': 'y'}, (expected_self, (1, 2), {'x': 'y'})),
445 (obj.meth_fastcall_keywords,
446 (), {'x': 'y'}, (expected_self, (), {'x': 'y'})),
447 (obj.meth_fastcall_keywords,
448 (1, 2), {}, (expected_self, (1, 2), NULL_OR_EMPTY)),
449 ])
Victor Stinner3b5cf852017-06-09 16:48:45 +0200450
451 def check_result(self, result, expected):
Petr Viktorinf9583772019-09-10 12:21:09 +0100452 if isinstance(expected, tuple) and expected[-1] is NULL_OR_EMPTY:
453 if result[-1] in ({}, None):
454 expected = (*expected[:-1], result[-1])
Victor Stinner3b5cf852017-06-09 16:48:45 +0200455 self.assertEqual(result, expected)
456
457 def test_fastcall(self):
458 # Test _PyObject_FastCall()
459
460 for func, args, expected in self.CALLS_POSARGS:
461 with self.subTest(func=func, args=args):
462 result = _testcapi.pyobject_fastcall(func, args)
463 self.check_result(result, expected)
464
465 if not args:
466 # args=NULL, nargs=0
467 result = _testcapi.pyobject_fastcall(func, None)
468 self.check_result(result, expected)
469
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200470 def test_vectorcall_dict(self):
Petr Viktorinffd97532020-02-11 17:46:57 +0100471 # Test PyObject_VectorcallDict()
Victor Stinner3b5cf852017-06-09 16:48:45 +0200472
473 for func, args, expected in self.CALLS_POSARGS:
474 with self.subTest(func=func, args=args):
475 # kwargs=NULL
476 result = _testcapi.pyobject_fastcalldict(func, args, None)
477 self.check_result(result, expected)
478
Victor Stinner3b5cf852017-06-09 16:48:45 +0200479 if not args:
480 # args=NULL, nargs=0, kwargs=NULL
481 result = _testcapi.pyobject_fastcalldict(func, None, None)
482 self.check_result(result, expected)
483
Victor Stinner3b5cf852017-06-09 16:48:45 +0200484 for func, args, kwargs, expected in self.CALLS_KWARGS:
485 with self.subTest(func=func, args=args, kwargs=kwargs):
486 result = _testcapi.pyobject_fastcalldict(func, args, kwargs)
487 self.check_result(result, expected)
488
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200489 def test_vectorcall(self):
Petr Viktorinffd97532020-02-11 17:46:57 +0100490 # Test PyObject_Vectorcall()
Victor Stinner3b5cf852017-06-09 16:48:45 +0200491
492 for func, args, expected in self.CALLS_POSARGS:
493 with self.subTest(func=func, args=args):
494 # kwnames=NULL
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200495 result = _testcapi.pyobject_vectorcall(func, args, None)
Victor Stinner3b5cf852017-06-09 16:48:45 +0200496 self.check_result(result, expected)
497
498 # kwnames=()
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200499 result = _testcapi.pyobject_vectorcall(func, args, ())
Victor Stinner3b5cf852017-06-09 16:48:45 +0200500 self.check_result(result, expected)
501
502 if not args:
503 # kwnames=NULL
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200504 result = _testcapi.pyobject_vectorcall(func, None, None)
Victor Stinner3b5cf852017-06-09 16:48:45 +0200505 self.check_result(result, expected)
506
507 # kwnames=()
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200508 result = _testcapi.pyobject_vectorcall(func, None, ())
Victor Stinner3b5cf852017-06-09 16:48:45 +0200509 self.check_result(result, expected)
510
511 for func, args, kwargs, expected in self.CALLS_KWARGS:
512 with self.subTest(func=func, args=args, kwargs=kwargs):
513 kwnames = tuple(kwargs.keys())
514 args = args + tuple(kwargs.values())
Jeroen Demeyeraacc77f2019-05-29 20:31:52 +0200515 result = _testcapi.pyobject_vectorcall(func, args, kwnames)
Victor Stinner3b5cf852017-06-09 16:48:45 +0200516 self.check_result(result, expected)
517
Jeroen Demeyer77aa3962019-05-22 13:09:35 +0200518 def test_fastcall_clearing_dict(self):
519 # Test bpo-36907: the point of the test is just checking that this
520 # does not crash.
521 class IntWithDict:
522 __slots__ = ["kwargs"]
523 def __init__(self, **kwargs):
524 self.kwargs = kwargs
525 def __index__(self):
526 self.kwargs.clear()
527 gc.collect()
528 return 0
529 x = IntWithDict(dont_inherit=IntWithDict())
530 # We test the argument handling of "compile" here, the compilation
531 # itself is not relevant. When we pass flags=x below, x.__index__() is
532 # called, which changes the keywords dict.
533 compile("pass", "", "exec", x, **x.kwargs)
Victor Stinner3b5cf852017-06-09 16:48:45 +0200534
Victor Stinner740a84d2019-06-07 17:51:28 +0200535
536Py_TPFLAGS_HAVE_VECTORCALL = 1 << 11
537Py_TPFLAGS_METHOD_DESCRIPTOR = 1 << 17
538
539
540def testfunction(self):
541 """some doc"""
542 return self
543
544
545def testfunction_kw(self, *, kw):
546 """some doc"""
547 return self
548
549
550class TestPEP590(unittest.TestCase):
551
552 def test_method_descriptor_flag(self):
553 import functools
554 cached = functools.lru_cache(1)(testfunction)
555
556 self.assertFalse(type(repr).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
557 self.assertTrue(type(list.append).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
558 self.assertTrue(type(list.__add__).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
559 self.assertTrue(type(testfunction).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
560 self.assertTrue(type(cached).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
561
562 self.assertTrue(_testcapi.MethodDescriptorBase.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
563 self.assertTrue(_testcapi.MethodDescriptorDerived.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
564 self.assertFalse(_testcapi.MethodDescriptorNopGet.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
565
566 # Heap type should not inherit Py_TPFLAGS_METHOD_DESCRIPTOR
567 class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):
568 pass
569 self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
570
571 def test_vectorcall_flag(self):
572 self.assertTrue(_testcapi.MethodDescriptorBase.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
573 self.assertTrue(_testcapi.MethodDescriptorDerived.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
574 self.assertFalse(_testcapi.MethodDescriptorNopGet.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
575 self.assertTrue(_testcapi.MethodDescriptor2.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
576
577 # Heap type should not inherit Py_TPFLAGS_HAVE_VECTORCALL
578 class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):
579 pass
580 self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
581
582 def test_vectorcall_override(self):
583 # Check that tp_call can correctly override vectorcall.
584 # MethodDescriptorNopGet implements tp_call but it inherits from
585 # MethodDescriptorBase, which implements vectorcall. Since
586 # MethodDescriptorNopGet returns the args tuple when called, we check
587 # additionally that no new tuple is created for this call.
588 args = tuple(range(5))
589 f = _testcapi.MethodDescriptorNopGet()
590 self.assertIs(f(*args), args)
591
592 def test_vectorcall(self):
593 # Test a bunch of different ways to call objects:
594 # 1. vectorcall using PyVectorcall_Call()
595 # (only for objects that support vectorcall directly)
596 # 2. normal call
Petr Viktorinffd97532020-02-11 17:46:57 +0100597 # 3. vectorcall using PyObject_Vectorcall()
Victor Stinner740a84d2019-06-07 17:51:28 +0200598 # 4. call as bound method
599 # 5. call using functools.partial
600
601 # A list of (function, args, kwargs, result) calls to test
602 calls = [(len, (range(42),), {}, 42),
603 (list.append, ([], 0), {}, None),
604 ([].append, (0,), {}, None),
605 (sum, ([36],), {"start":6}, 42),
606 (testfunction, (42,), {}, 42),
607 (testfunction_kw, (42,), {"kw":None}, 42),
608 (_testcapi.MethodDescriptorBase(), (0,), {}, True),
609 (_testcapi.MethodDescriptorDerived(), (0,), {}, True),
610 (_testcapi.MethodDescriptor2(), (0,), {}, False)]
611
612 from _testcapi import pyobject_vectorcall, pyvectorcall_call
613 from types import MethodType
614 from functools import partial
615
616 def vectorcall(func, args, kwargs):
617 args = *args, *kwargs.values()
618 kwnames = tuple(kwargs)
619 return pyobject_vectorcall(func, args, kwnames)
620
621 for (func, args, kwargs, expected) in calls:
622 with self.subTest(str(func)):
623 if not kwargs:
624 self.assertEqual(expected, pyvectorcall_call(func, args))
625 self.assertEqual(expected, pyvectorcall_call(func, args, kwargs))
626
627 # Add derived classes (which do not support vectorcall directly,
628 # but do support all other ways of calling).
629
630 class MethodDescriptorHeap(_testcapi.MethodDescriptorBase):
631 pass
632
633 class MethodDescriptorOverridden(_testcapi.MethodDescriptorBase):
634 def __call__(self, n):
635 return 'new'
636
Jeroen Demeyera8b27e62019-06-24 12:41:05 +0200637 class SuperBase:
638 def __call__(self, *args):
639 return super().__call__(*args)
640
641 class MethodDescriptorSuper(SuperBase, _testcapi.MethodDescriptorBase):
642 def __call__(self, *args):
643 return super().__call__(*args)
644
Victor Stinner740a84d2019-06-07 17:51:28 +0200645 calls += [
Jeroen Demeyer0d722f32019-07-05 14:48:24 +0200646 (dict.update, ({},), {"key":True}, None),
647 ({}.update, ({},), {"key":True}, None),
Victor Stinner740a84d2019-06-07 17:51:28 +0200648 (MethodDescriptorHeap(), (0,), {}, True),
649 (MethodDescriptorOverridden(), (0,), {}, 'new'),
Jeroen Demeyera8b27e62019-06-24 12:41:05 +0200650 (MethodDescriptorSuper(), (0,), {}, True),
Victor Stinner740a84d2019-06-07 17:51:28 +0200651 ]
652
653 for (func, args, kwargs, expected) in calls:
654 with self.subTest(str(func)):
655 args1 = args[1:]
656 meth = MethodType(func, args[0])
657 wrapped = partial(func)
658 if not kwargs:
659 self.assertEqual(expected, func(*args))
660 self.assertEqual(expected, pyobject_vectorcall(func, args, None))
661 self.assertEqual(expected, meth(*args1))
662 self.assertEqual(expected, wrapped(*args))
663 self.assertEqual(expected, func(*args, **kwargs))
664 self.assertEqual(expected, vectorcall(func, args, kwargs))
665 self.assertEqual(expected, meth(*args1, **kwargs))
666 self.assertEqual(expected, wrapped(*args, **kwargs))
667
668
Dennis Sweeneyb5cc2082020-05-22 16:40:17 -0400669class A:
670 def method_two_args(self, x, y):
671 pass
672
673 @staticmethod
674 def static_no_args():
675 pass
676
677 @staticmethod
678 def positional_only(arg, /):
679 pass
680
681@cpython_only
682class TestErrorMessagesUseQualifiedName(unittest.TestCase):
683
684 @contextlib.contextmanager
685 def check_raises_type_error(self, message):
686 with self.assertRaises(TypeError) as cm:
687 yield
688 self.assertEqual(str(cm.exception), message)
689
690 def test_missing_arguments(self):
691 msg = "A.method_two_args() missing 1 required positional argument: 'y'"
692 with self.check_raises_type_error(msg):
693 A().method_two_args("x")
694
695 def test_too_many_positional(self):
696 msg = "A.static_no_args() takes 0 positional arguments but 1 was given"
697 with self.check_raises_type_error(msg):
698 A.static_no_args("oops it's an arg")
699
700 def test_positional_only_passed_as_keyword(self):
701 msg = "A.positional_only() got some positional-only arguments passed as keyword arguments: 'arg'"
702 with self.check_raises_type_error(msg):
703 A.positional_only(arg="x")
704
705 def test_unexpected_keyword(self):
706 msg = "A.method_two_args() got an unexpected keyword argument 'bad'"
707 with self.check_raises_type_error(msg):
708 A().method_two_args(bad="x")
709
710 def test_multiple_values(self):
711 msg = "A.method_two_args() got multiple values for argument 'x'"
712 with self.check_raises_type_error(msg):
713 A().method_two_args("x", "y", x="oops")
714
715
Fred Drake2e2be372001-09-20 21:33:42 +0000716if __name__ == "__main__":
Zachary Ware38c707e2015-04-13 15:00:43 -0500717 unittest.main()