1 import unittest
2 from test.support import cpython_only
3 try:
4 import _testcapi
5 except ImportError:
6 _testcapi = None
7 import struct
8 import collections
9 import itertools
10 import gc
11 import contextlib
12
13
14 class ESC[4;38;5;81mBadStr(ESC[4;38;5;149mstr):
15 def __eq__(self, other):
16 return True
17 def __hash__(self):
18 # Guaranteed different hash
19 return str.__hash__(self) ^ 3
20
21
22 class ESC[4;38;5;81mFunctionCalls(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
23
24 def test_kwargs_order(self):
25 # bpo-34320: **kwargs should preserve order of passed OrderedDict
26 od = collections.OrderedDict([('a', 1), ('b', 2)])
27 od.move_to_end('a')
28 expected = list(od.items())
29
30 def fn(**kw):
31 return kw
32
33 res = fn(**od)
34 self.assertIsInstance(res, dict)
35 self.assertEqual(list(res.items()), expected)
36
37 def test_frames_are_popped_after_failed_calls(self):
38 # GH-93252: stuff blows up if we don't pop the new frame after
39 # recovering from failed calls:
40 def f():
41 pass
42 for _ in range(1000):
43 try:
44 f(None)
45 except TypeError:
46 pass
47 # BOOM!
48
49
50 @cpython_only
51 class ESC[4;38;5;81mCFunctionCallsErrorMessages(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
52
53 def test_varargs0(self):
54 msg = r"__contains__\(\) takes exactly one argument \(0 given\)"
55 self.assertRaisesRegex(TypeError, msg, {}.__contains__)
56
57 def test_varargs2(self):
58 msg = r"__contains__\(\) takes exactly one argument \(2 given\)"
59 self.assertRaisesRegex(TypeError, msg, {}.__contains__, 0, 1)
60
61 def test_varargs3(self):
62 msg = r"^from_bytes\(\) takes at most 2 positional arguments \(3 given\)"
63 self.assertRaisesRegex(TypeError, msg, int.from_bytes, b'a', 'little', False)
64
65 def test_varargs1min(self):
66 msg = r"get expected at least 1 argument, got 0"
67 self.assertRaisesRegex(TypeError, msg, {}.get)
68
69 msg = r"expected 1 argument, got 0"
70 self.assertRaisesRegex(TypeError, msg, {}.__delattr__)
71
72 def test_varargs2min(self):
73 msg = r"getattr expected at least 2 arguments, got 0"
74 self.assertRaisesRegex(TypeError, msg, getattr)
75
76 def test_varargs1max(self):
77 msg = r"input expected at most 1 argument, got 2"
78 self.assertRaisesRegex(TypeError, msg, input, 1, 2)
79
80 def test_varargs2max(self):
81 msg = r"get expected at most 2 arguments, got 3"
82 self.assertRaisesRegex(TypeError, msg, {}.get, 1, 2, 3)
83
84 def test_varargs1_kw(self):
85 msg = r"__contains__\(\) takes no keyword arguments"
86 self.assertRaisesRegex(TypeError, msg, {}.__contains__, x=2)
87
88 def test_varargs2_kw(self):
89 msg = r"__contains__\(\) takes no keyword arguments"
90 self.assertRaisesRegex(TypeError, msg, {}.__contains__, x=2, y=2)
91
92 def test_varargs3_kw(self):
93 msg = r"bool\(\) takes no keyword arguments"
94 self.assertRaisesRegex(TypeError, msg, bool, x=2)
95
96 def test_varargs4_kw(self):
97 msg = r"^list[.]index\(\) takes no keyword arguments$"
98 self.assertRaisesRegex(TypeError, msg, [].index, x=2)
99
100 def test_varargs5_kw(self):
101 msg = r"^hasattr\(\) takes no keyword arguments$"
102 self.assertRaisesRegex(TypeError, msg, hasattr, x=2)
103
104 def test_varargs6_kw(self):
105 msg = r"^getattr\(\) takes no keyword arguments$"
106 self.assertRaisesRegex(TypeError, msg, getattr, x=2)
107
108 def test_varargs7_kw(self):
109 msg = r"^next\(\) takes no keyword arguments$"
110 self.assertRaisesRegex(TypeError, msg, next, x=2)
111
112 def test_varargs8_kw(self):
113 msg = r"^_struct[.]pack\(\) takes no keyword arguments$"
114 self.assertRaisesRegex(TypeError, msg, struct.pack, x=2)
115
116 def test_varargs9_kw(self):
117 msg = r"^_struct[.]pack_into\(\) takes no keyword arguments$"
118 self.assertRaisesRegex(TypeError, msg, struct.pack_into, x=2)
119
120 def test_varargs10_kw(self):
121 msg = r"^deque[.]index\(\) takes no keyword arguments$"
122 self.assertRaisesRegex(TypeError, msg, collections.deque().index, x=2)
123
124 def test_varargs11_kw(self):
125 msg = r"^Struct[.]pack\(\) takes no keyword arguments$"
126 self.assertRaisesRegex(TypeError, msg, struct.Struct.pack, struct.Struct(""), x=2)
127
128 def test_varargs12_kw(self):
129 msg = r"^staticmethod\(\) takes no keyword arguments$"
130 self.assertRaisesRegex(TypeError, msg, staticmethod, func=id)
131
132 def test_varargs13_kw(self):
133 msg = r"^classmethod\(\) takes no keyword arguments$"
134 self.assertRaisesRegex(TypeError, msg, classmethod, func=id)
135
136 def test_varargs14_kw(self):
137 msg = r"^product\(\) takes at most 1 keyword argument \(2 given\)$"
138 self.assertRaisesRegex(TypeError, msg,
139 itertools.product, 0, repeat=1, foo=2)
140
141 def test_varargs15_kw(self):
142 msg = r"^ImportError\(\) takes at most 2 keyword arguments \(3 given\)$"
143 self.assertRaisesRegex(TypeError, msg,
144 ImportError, 0, name=1, path=2, foo=3)
145
146 def test_varargs16_kw(self):
147 msg = r"^min\(\) takes at most 2 keyword arguments \(3 given\)$"
148 self.assertRaisesRegex(TypeError, msg,
149 min, 0, default=1, key=2, foo=3)
150
151 def test_varargs17_kw(self):
152 msg = r"'foo' is an invalid keyword argument for print\(\)$"
153 self.assertRaisesRegex(TypeError, msg,
154 print, 0, sep=1, end=2, file=3, flush=4, foo=5)
155
156 def test_varargs18_kw(self):
157 # _PyArg_UnpackKeywordsWithVararg()
158 msg = r"invalid keyword argument for print\(\)$"
159 with self.assertRaisesRegex(TypeError, msg):
160 print(0, 1, **{BadStr('foo'): ','})
161
162 def test_varargs19_kw(self):
163 # _PyArg_UnpackKeywords()
164 msg = r"invalid keyword argument for round\(\)$"
165 with self.assertRaisesRegex(TypeError, msg):
166 round(1.75, **{BadStr('foo'): 1})
167
168 def test_oldargs0_1(self):
169 msg = r"keys\(\) takes no arguments \(1 given\)"
170 self.assertRaisesRegex(TypeError, msg, {}.keys, 0)
171
172 def test_oldargs0_2(self):
173 msg = r"keys\(\) takes no arguments \(2 given\)"
174 self.assertRaisesRegex(TypeError, msg, {}.keys, 0, 1)
175
176 def test_oldargs0_1_kw(self):
177 msg = r"keys\(\) takes no keyword arguments"
178 self.assertRaisesRegex(TypeError, msg, {}.keys, x=2)
179
180 def test_oldargs0_2_kw(self):
181 msg = r"keys\(\) takes no keyword arguments"
182 self.assertRaisesRegex(TypeError, msg, {}.keys, x=2, y=2)
183
184 def test_oldargs1_0(self):
185 msg = r"count\(\) takes exactly one argument \(0 given\)"
186 self.assertRaisesRegex(TypeError, msg, [].count)
187
188 def test_oldargs1_2(self):
189 msg = r"count\(\) takes exactly one argument \(2 given\)"
190 self.assertRaisesRegex(TypeError, msg, [].count, 1, 2)
191
192 def test_oldargs1_0_kw(self):
193 msg = r"count\(\) takes no keyword arguments"
194 self.assertRaisesRegex(TypeError, msg, [].count, x=2)
195
196 def test_oldargs1_1_kw(self):
197 msg = r"count\(\) takes no keyword arguments"
198 self.assertRaisesRegex(TypeError, msg, [].count, {}, x=2)
199
200 def test_oldargs1_2_kw(self):
201 msg = r"count\(\) takes no keyword arguments"
202 self.assertRaisesRegex(TypeError, msg, [].count, x=2, y=2)
203
204
205
206 class ESC[4;38;5;81mTestCallingConventions(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
207 """Test calling using various C calling conventions (METH_*) from Python
208
209 Subclasses test several kinds of functions (module-level, methods,
210 class methods static methods) using these attributes:
211 obj: the object that contains tested functions (as attributes)
212 expected_self: expected "self" argument to the C function
213
214 The base class tests module-level functions.
215 """
216
217 def setUp(self):
218 self.obj = self.expected_self = _testcapi
219
220 def test_varargs(self):
221 self.assertEqual(
222 self.obj.meth_varargs(1, 2, 3),
223 (self.expected_self, (1, 2, 3)),
224 )
225
226 def test_varargs_ext(self):
227 self.assertEqual(
228 self.obj.meth_varargs(*(1, 2, 3)),
229 (self.expected_self, (1, 2, 3)),
230 )
231
232 def test_varargs_error_kw(self):
233 msg = r"meth_varargs\(\) takes no keyword arguments"
234 self.assertRaisesRegex(
235 TypeError, msg, lambda: self.obj.meth_varargs(k=1),
236 )
237
238 def test_varargs_keywords(self):
239 self.assertEqual(
240 self.obj.meth_varargs_keywords(1, 2, a=3, b=4),
241 (self.expected_self, (1, 2), {'a': 3, 'b': 4})
242 )
243
244 def test_varargs_keywords_ext(self):
245 self.assertEqual(
246 self.obj.meth_varargs_keywords(*[1, 2], **{'a': 3, 'b': 4}),
247 (self.expected_self, (1, 2), {'a': 3, 'b': 4})
248 )
249
250 def test_o(self):
251 self.assertEqual(self.obj.meth_o(1), (self.expected_self, 1))
252
253 def test_o_ext(self):
254 self.assertEqual(self.obj.meth_o(*[1]), (self.expected_self, 1))
255
256 def test_o_error_no_arg(self):
257 msg = r"meth_o\(\) takes exactly one argument \(0 given\)"
258 self.assertRaisesRegex(TypeError, msg, self.obj.meth_o)
259
260 def test_o_error_two_args(self):
261 msg = r"meth_o\(\) takes exactly one argument \(2 given\)"
262 self.assertRaisesRegex(
263 TypeError, msg, lambda: self.obj.meth_o(1, 2),
264 )
265
266 def test_o_error_ext(self):
267 msg = r"meth_o\(\) takes exactly one argument \(3 given\)"
268 self.assertRaisesRegex(
269 TypeError, msg, lambda: self.obj.meth_o(*(1, 2, 3)),
270 )
271
272 def test_o_error_kw(self):
273 msg = r"meth_o\(\) takes no keyword arguments"
274 self.assertRaisesRegex(
275 TypeError, msg, lambda: self.obj.meth_o(k=1),
276 )
277
278 def test_o_error_arg_kw(self):
279 msg = r"meth_o\(\) takes no keyword arguments"
280 self.assertRaisesRegex(
281 TypeError, msg, lambda: self.obj.meth_o(k=1),
282 )
283
284 def test_noargs(self):
285 self.assertEqual(self.obj.meth_noargs(), self.expected_self)
286
287 def test_noargs_ext(self):
288 self.assertEqual(self.obj.meth_noargs(*[]), self.expected_self)
289
290 def test_noargs_error_arg(self):
291 msg = r"meth_noargs\(\) takes no arguments \(1 given\)"
292 self.assertRaisesRegex(
293 TypeError, msg, lambda: self.obj.meth_noargs(1),
294 )
295
296 def test_noargs_error_arg2(self):
297 msg = r"meth_noargs\(\) takes no arguments \(2 given\)"
298 self.assertRaisesRegex(
299 TypeError, msg, lambda: self.obj.meth_noargs(1, 2),
300 )
301
302 def test_noargs_error_ext(self):
303 msg = r"meth_noargs\(\) takes no arguments \(3 given\)"
304 self.assertRaisesRegex(
305 TypeError, msg, lambda: self.obj.meth_noargs(*(1, 2, 3)),
306 )
307
308 def test_noargs_error_kw(self):
309 msg = r"meth_noargs\(\) takes no keyword arguments"
310 self.assertRaisesRegex(
311 TypeError, msg, lambda: self.obj.meth_noargs(k=1),
312 )
313
314 def test_fastcall(self):
315 self.assertEqual(
316 self.obj.meth_fastcall(1, 2, 3),
317 (self.expected_self, (1, 2, 3)),
318 )
319
320 def test_fastcall_ext(self):
321 self.assertEqual(
322 self.obj.meth_fastcall(*(1, 2, 3)),
323 (self.expected_self, (1, 2, 3)),
324 )
325
326 def test_fastcall_error_kw(self):
327 msg = r"meth_fastcall\(\) takes no keyword arguments"
328 self.assertRaisesRegex(
329 TypeError, msg, lambda: self.obj.meth_fastcall(k=1),
330 )
331
332 def test_fastcall_keywords(self):
333 self.assertEqual(
334 self.obj.meth_fastcall_keywords(1, 2, a=3, b=4),
335 (self.expected_self, (1, 2), {'a': 3, 'b': 4})
336 )
337
338 def test_fastcall_keywords_ext(self):
339 self.assertEqual(
340 self.obj.meth_fastcall_keywords(*(1, 2), **{'a': 3, 'b': 4}),
341 (self.expected_self, (1, 2), {'a': 3, 'b': 4})
342 )
343
344
345 class ESC[4;38;5;81mTestCallingConventionsInstance(ESC[4;38;5;149mTestCallingConventions):
346 """Test calling instance methods using various calling conventions"""
347
348 def setUp(self):
349 self.obj = self.expected_self = _testcapi.MethInstance()
350
351
352 class ESC[4;38;5;81mTestCallingConventionsClass(ESC[4;38;5;149mTestCallingConventions):
353 """Test calling class methods using various calling conventions"""
354
355 def setUp(self):
356 self.obj = self.expected_self = _testcapi.MethClass
357
358
359 class ESC[4;38;5;81mTestCallingConventionsClassInstance(ESC[4;38;5;149mTestCallingConventions):
360 """Test calling class methods on instance"""
361
362 def setUp(self):
363 self.obj = _testcapi.MethClass()
364 self.expected_self = _testcapi.MethClass
365
366
367 class ESC[4;38;5;81mTestCallingConventionsStatic(ESC[4;38;5;149mTestCallingConventions):
368 """Test calling static methods using various calling conventions"""
369
370 def setUp(self):
371 self.obj = _testcapi.MethStatic()
372 self.expected_self = None
373
374
375 def pyfunc(arg1, arg2):
376 return [arg1, arg2]
377
378
379 def pyfunc_noarg():
380 return "noarg"
381
382
383 class ESC[4;38;5;81mPythonClass:
384 def method(self, arg1, arg2):
385 return [arg1, arg2]
386
387 def method_noarg(self):
388 return "noarg"
389
390 @classmethod
391 def class_method(cls):
392 return "classmethod"
393
394 @staticmethod
395 def static_method():
396 return "staticmethod"
397
398
399 PYTHON_INSTANCE = PythonClass()
400
401 NULL_OR_EMPTY = object()
402
403 class ESC[4;38;5;81mFastCallTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
404 """Test calling using various callables from C
405 """
406
407 # Test calls with positional arguments
408 CALLS_POSARGS = [
409 # (func, args: tuple, result)
410
411 # Python function with 2 arguments
412 (pyfunc, (1, 2), [1, 2]),
413
414 # Python function without argument
415 (pyfunc_noarg, (), "noarg"),
416
417 # Python class methods
418 (PythonClass.class_method, (), "classmethod"),
419 (PythonClass.static_method, (), "staticmethod"),
420
421 # Python instance methods
422 (PYTHON_INSTANCE.method, (1, 2), [1, 2]),
423 (PYTHON_INSTANCE.method_noarg, (), "noarg"),
424 (PYTHON_INSTANCE.class_method, (), "classmethod"),
425 (PYTHON_INSTANCE.static_method, (), "staticmethod"),
426
427 # C callables are added later
428 ]
429
430 # Test calls with positional and keyword arguments
431 CALLS_KWARGS = [
432 # (func, args: tuple, kwargs: dict, result)
433
434 # Python function with 2 arguments
435 (pyfunc, (1,), {'arg2': 2}, [1, 2]),
436 (pyfunc, (), {'arg1': 1, 'arg2': 2}, [1, 2]),
437
438 # Python instance methods
439 (PYTHON_INSTANCE.method, (1,), {'arg2': 2}, [1, 2]),
440 (PYTHON_INSTANCE.method, (), {'arg1': 1, 'arg2': 2}, [1, 2]),
441
442 # C callables are added later
443 ]
444
445 # Add all the calling conventions and variants of C callables
446 _instance = _testcapi.MethInstance()
447 for obj, expected_self in (
448 (_testcapi, _testcapi), # module-level function
449 (_instance, _instance), # bound method
450 (_testcapi.MethClass, _testcapi.MethClass), # class method on class
451 (_testcapi.MethClass(), _testcapi.MethClass), # class method on inst.
452 (_testcapi.MethStatic, None), # static method
453 ):
454 CALLS_POSARGS.extend([
455 (obj.meth_varargs, (1, 2), (expected_self, (1, 2))),
456 (obj.meth_varargs_keywords,
457 (1, 2), (expected_self, (1, 2), NULL_OR_EMPTY)),
458 (obj.meth_fastcall, (1, 2), (expected_self, (1, 2))),
459 (obj.meth_fastcall, (), (expected_self, ())),
460 (obj.meth_fastcall_keywords,
461 (1, 2), (expected_self, (1, 2), NULL_OR_EMPTY)),
462 (obj.meth_fastcall_keywords,
463 (), (expected_self, (), NULL_OR_EMPTY)),
464 (obj.meth_noargs, (), expected_self),
465 (obj.meth_o, (123, ), (expected_self, 123)),
466 ])
467
468 CALLS_KWARGS.extend([
469 (obj.meth_varargs_keywords,
470 (1, 2), {'x': 'y'}, (expected_self, (1, 2), {'x': 'y'})),
471 (obj.meth_varargs_keywords,
472 (), {'x': 'y'}, (expected_self, (), {'x': 'y'})),
473 (obj.meth_varargs_keywords,
474 (1, 2), {}, (expected_self, (1, 2), NULL_OR_EMPTY)),
475 (obj.meth_fastcall_keywords,
476 (1, 2), {'x': 'y'}, (expected_self, (1, 2), {'x': 'y'})),
477 (obj.meth_fastcall_keywords,
478 (), {'x': 'y'}, (expected_self, (), {'x': 'y'})),
479 (obj.meth_fastcall_keywords,
480 (1, 2), {}, (expected_self, (1, 2), NULL_OR_EMPTY)),
481 ])
482
483 def check_result(self, result, expected):
484 if isinstance(expected, tuple) and expected[-1] is NULL_OR_EMPTY:
485 if result[-1] in ({}, None):
486 expected = (*expected[:-1], result[-1])
487 self.assertEqual(result, expected)
488
489 def test_fastcall(self):
490 # Test _PyObject_FastCall()
491
492 for func, args, expected in self.CALLS_POSARGS:
493 with self.subTest(func=func, args=args):
494 result = _testcapi.pyobject_fastcall(func, args)
495 self.check_result(result, expected)
496
497 if not args:
498 # args=NULL, nargs=0
499 result = _testcapi.pyobject_fastcall(func, None)
500 self.check_result(result, expected)
501
502 def test_vectorcall_dict(self):
503 # Test PyObject_VectorcallDict()
504
505 for func, args, expected in self.CALLS_POSARGS:
506 with self.subTest(func=func, args=args):
507 # kwargs=NULL
508 result = _testcapi.pyobject_fastcalldict(func, args, None)
509 self.check_result(result, expected)
510
511 if not args:
512 # args=NULL, nargs=0, kwargs=NULL
513 result = _testcapi.pyobject_fastcalldict(func, None, None)
514 self.check_result(result, expected)
515
516 for func, args, kwargs, expected in self.CALLS_KWARGS:
517 with self.subTest(func=func, args=args, kwargs=kwargs):
518 result = _testcapi.pyobject_fastcalldict(func, args, kwargs)
519 self.check_result(result, expected)
520
521 def test_vectorcall(self):
522 # Test PyObject_Vectorcall()
523
524 for func, args, expected in self.CALLS_POSARGS:
525 with self.subTest(func=func, args=args):
526 # kwnames=NULL
527 result = _testcapi.pyobject_vectorcall(func, args, None)
528 self.check_result(result, expected)
529
530 # kwnames=()
531 result = _testcapi.pyobject_vectorcall(func, args, ())
532 self.check_result(result, expected)
533
534 if not args:
535 # kwnames=NULL
536 result = _testcapi.pyobject_vectorcall(func, None, None)
537 self.check_result(result, expected)
538
539 # kwnames=()
540 result = _testcapi.pyobject_vectorcall(func, None, ())
541 self.check_result(result, expected)
542
543 for func, args, kwargs, expected in self.CALLS_KWARGS:
544 with self.subTest(func=func, args=args, kwargs=kwargs):
545 kwnames = tuple(kwargs.keys())
546 args = args + tuple(kwargs.values())
547 result = _testcapi.pyobject_vectorcall(func, args, kwnames)
548 self.check_result(result, expected)
549
550 def test_fastcall_clearing_dict(self):
551 # Test bpo-36907: the point of the test is just checking that this
552 # does not crash.
553 class ESC[4;38;5;81mIntWithDict:
554 __slots__ = ["kwargs"]
555 def __init__(self, **kwargs):
556 self.kwargs = kwargs
557 def __index__(self):
558 self.kwargs.clear()
559 gc.collect()
560 return 0
561 x = IntWithDict(optimize=IntWithDict())
562 # We test the argument handling of "compile" here, the compilation
563 # itself is not relevant. When we pass flags=x below, x.__index__() is
564 # called, which changes the keywords dict.
565 compile("pass", "", "exec", x, **x.kwargs)
566
567
568 Py_TPFLAGS_HAVE_VECTORCALL = 1 << 11
569 Py_TPFLAGS_METHOD_DESCRIPTOR = 1 << 17
570
571
572 def testfunction(self):
573 """some doc"""
574 return self
575
576
577 def testfunction_kw(self, *, kw):
578 """some doc"""
579 return self
580
581
582 class ESC[4;38;5;81mTestPEP590(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
583
584 def test_method_descriptor_flag(self):
585 import functools
586 cached = functools.lru_cache(1)(testfunction)
587
588 self.assertFalse(type(repr).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
589 self.assertTrue(type(list.append).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
590 self.assertTrue(type(list.__add__).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
591 self.assertTrue(type(testfunction).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
592 self.assertTrue(type(cached).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
593
594 self.assertTrue(_testcapi.MethodDescriptorBase.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
595 self.assertTrue(_testcapi.MethodDescriptorDerived.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
596 self.assertFalse(_testcapi.MethodDescriptorNopGet.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
597
598 # Mutable heap types should not inherit Py_TPFLAGS_METHOD_DESCRIPTOR
599 class ESC[4;38;5;81mMethodDescriptorHeap(ESC[4;38;5;149m_testcapiESC[4;38;5;149m.ESC[4;38;5;149mMethodDescriptorBase):
600 pass
601 self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR)
602
603 def test_vectorcall_flag(self):
604 self.assertTrue(_testcapi.MethodDescriptorBase.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
605 self.assertTrue(_testcapi.MethodDescriptorDerived.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
606 self.assertFalse(_testcapi.MethodDescriptorNopGet.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
607 self.assertTrue(_testcapi.MethodDescriptor2.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
608
609 # Mutable heap types should not inherit Py_TPFLAGS_HAVE_VECTORCALL
610 class ESC[4;38;5;81mMethodDescriptorHeap(ESC[4;38;5;149m_testcapiESC[4;38;5;149m.ESC[4;38;5;149mMethodDescriptorBase):
611 pass
612 self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL)
613
614 def test_vectorcall_override(self):
615 # Check that tp_call can correctly override vectorcall.
616 # MethodDescriptorNopGet implements tp_call but it inherits from
617 # MethodDescriptorBase, which implements vectorcall. Since
618 # MethodDescriptorNopGet returns the args tuple when called, we check
619 # additionally that no new tuple is created for this call.
620 args = tuple(range(5))
621 f = _testcapi.MethodDescriptorNopGet()
622 self.assertIs(f(*args), args)
623
624 def test_vectorcall(self):
625 # Test a bunch of different ways to call objects:
626 # 1. vectorcall using PyVectorcall_Call()
627 # (only for objects that support vectorcall directly)
628 # 2. normal call
629 # 3. vectorcall using PyObject_Vectorcall()
630 # 4. call as bound method
631 # 5. call using functools.partial
632
633 # A list of (function, args, kwargs, result) calls to test
634 calls = [(len, (range(42),), {}, 42),
635 (list.append, ([], 0), {}, None),
636 ([].append, (0,), {}, None),
637 (sum, ([36],), {"start":6}, 42),
638 (testfunction, (42,), {}, 42),
639 (testfunction_kw, (42,), {"kw":None}, 42),
640 (_testcapi.MethodDescriptorBase(), (0,), {}, True),
641 (_testcapi.MethodDescriptorDerived(), (0,), {}, True),
642 (_testcapi.MethodDescriptor2(), (0,), {}, False)]
643
644 from _testcapi import pyobject_vectorcall, pyvectorcall_call
645 from types import MethodType
646 from functools import partial
647
648 def vectorcall(func, args, kwargs):
649 args = *args, *kwargs.values()
650 kwnames = tuple(kwargs)
651 return pyobject_vectorcall(func, args, kwnames)
652
653 for (func, args, kwargs, expected) in calls:
654 with self.subTest(str(func)):
655 if not kwargs:
656 self.assertEqual(expected, pyvectorcall_call(func, args))
657 self.assertEqual(expected, pyvectorcall_call(func, args, kwargs))
658
659 # Add derived classes (which do not support vectorcall directly,
660 # but do support all other ways of calling).
661
662 class ESC[4;38;5;81mMethodDescriptorHeap(ESC[4;38;5;149m_testcapiESC[4;38;5;149m.ESC[4;38;5;149mMethodDescriptorBase):
663 pass
664
665 class ESC[4;38;5;81mMethodDescriptorOverridden(ESC[4;38;5;149m_testcapiESC[4;38;5;149m.ESC[4;38;5;149mMethodDescriptorBase):
666 def __call__(self, n):
667 return 'new'
668
669 class ESC[4;38;5;81mSuperBase:
670 def __call__(self, *args):
671 return super().__call__(*args)
672
673 class ESC[4;38;5;81mMethodDescriptorSuper(ESC[4;38;5;149mSuperBase, ESC[4;38;5;149m_testcapiESC[4;38;5;149m.ESC[4;38;5;149mMethodDescriptorBase):
674 def __call__(self, *args):
675 return super().__call__(*args)
676
677 calls += [
678 (dict.update, ({},), {"key":True}, None),
679 ({}.update, ({},), {"key":True}, None),
680 (MethodDescriptorHeap(), (0,), {}, True),
681 (MethodDescriptorOverridden(), (0,), {}, 'new'),
682 (MethodDescriptorSuper(), (0,), {}, True),
683 ]
684
685 for (func, args, kwargs, expected) in calls:
686 with self.subTest(str(func)):
687 args1 = args[1:]
688 meth = MethodType(func, args[0])
689 wrapped = partial(func)
690 if not kwargs:
691 self.assertEqual(expected, func(*args))
692 self.assertEqual(expected, pyobject_vectorcall(func, args, None))
693 self.assertEqual(expected, meth(*args1))
694 self.assertEqual(expected, wrapped(*args))
695 self.assertEqual(expected, func(*args, **kwargs))
696 self.assertEqual(expected, vectorcall(func, args, kwargs))
697 self.assertEqual(expected, meth(*args1, **kwargs))
698 self.assertEqual(expected, wrapped(*args, **kwargs))
699
700
701 class ESC[4;38;5;81mA:
702 def method_two_args(self, x, y):
703 pass
704
705 @staticmethod
706 def static_no_args():
707 pass
708
709 @staticmethod
710 def positional_only(arg, /):
711 pass
712
713 @cpython_only
714 class ESC[4;38;5;81mTestErrorMessagesUseQualifiedName(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
715
716 @contextlib.contextmanager
717 def check_raises_type_error(self, message):
718 with self.assertRaises(TypeError) as cm:
719 yield
720 self.assertEqual(str(cm.exception), message)
721
722 def test_missing_arguments(self):
723 msg = "A.method_two_args() missing 1 required positional argument: 'y'"
724 with self.check_raises_type_error(msg):
725 A().method_two_args("x")
726
727 def test_too_many_positional(self):
728 msg = "A.static_no_args() takes 0 positional arguments but 1 was given"
729 with self.check_raises_type_error(msg):
730 A.static_no_args("oops it's an arg")
731
732 def test_positional_only_passed_as_keyword(self):
733 msg = "A.positional_only() got some positional-only arguments passed as keyword arguments: 'arg'"
734 with self.check_raises_type_error(msg):
735 A.positional_only(arg="x")
736
737 def test_unexpected_keyword(self):
738 msg = "A.method_two_args() got an unexpected keyword argument 'bad'"
739 with self.check_raises_type_error(msg):
740 A().method_two_args(bad="x")
741
742 def test_multiple_values(self):
743 msg = "A.method_two_args() got multiple values for argument 'x'"
744 with self.check_raises_type_error(msg):
745 A().method_two_args("x", "y", x="oops")
746
747
748 if __name__ == "__main__":
749 unittest.main()