1import unittest 2from test.support import cpython_only 3try: 4 import _testcapi 5except ImportError: 6 _testcapi = None 7import struct 8import collections 9import itertools 10import gc 11import contextlib 12 13 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 30@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 41 def test_varargs3(self): 42 msg = r"^from_bytes\(\) takes exactly 2 positional arguments \(3 given\)" 43 self.assertRaisesRegex(TypeError, msg, int.from_bytes, b'a', 'little', False) 44 45 def test_varargs1min(self): 46 msg = r"get expected at least 1 argument, got 0" 47 self.assertRaisesRegex(TypeError, msg, {}.get) 48 49 msg = r"expected 1 argument, got 0" 50 self.assertRaisesRegex(TypeError, msg, {}.__delattr__) 51 52 def test_varargs2min(self): 53 msg = r"getattr expected at least 2 arguments, got 0" 54 self.assertRaisesRegex(TypeError, msg, getattr) 55 56 def test_varargs1max(self): 57 msg = r"input expected at most 1 argument, got 2" 58 self.assertRaisesRegex(TypeError, msg, input, 1, 2) 59 60 def test_varargs2max(self): 61 msg = r"get expected at most 2 arguments, got 3" 62 self.assertRaisesRegex(TypeError, msg, {}.get, 1, 2, 3) 63 64 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 72 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): 77 msg = r"^list[.]index\(\) takes no keyword arguments$" 78 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 84 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): 93 msg = r"^_struct[.]pack\(\) takes no keyword arguments$" 94 self.assertRaisesRegex(TypeError, msg, struct.pack, x=2) 95 96 def test_varargs9_kw(self): 97 msg = r"^_struct[.]pack_into\(\) takes no keyword arguments$" 98 self.assertRaisesRegex(TypeError, msg, struct.pack_into, x=2) 99 100 def test_varargs10_kw(self): 101 msg = r"^deque[.]index\(\) takes no keyword arguments$" 102 self.assertRaisesRegex(TypeError, msg, collections.deque().index, x=2) 103 104 def test_varargs11_kw(self): 105 msg = r"^Struct[.]pack\(\) takes no keyword arguments$" 106 self.assertRaisesRegex(TypeError, msg, struct.Struct.pack, struct.Struct(""), x=2) 107 108 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 116 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 136 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 173 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 343def 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 369NULL_OR_EMPTY = object() 370 371class FastCallTests(unittest.TestCase): 372 """Test calling using various callables from C 373 """ 374 375 # Test calls with positional arguments 376 CALLS_POSARGS = [ 377 # (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 395 # C callables are added later 396 ] 397 398 # Test calls with positional and keyword arguments 399 CALLS_KWARGS = [ 400 # (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 410 # C callables are added later 411 ] 412 413 # 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 ]) 450 451 def check_result(self, result, expected): 452 if isinstance(expected, tuple) and expected[-1] is NULL_OR_EMPTY: 453 if result[-1] in ({}, None): 454 expected = (*expected[:-1], result[-1]) 455 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 470 def test_vectorcall_dict(self): 471 # Test PyObject_VectorcallDict() 472 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 479 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 484 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 489 def test_vectorcall(self): 490 # Test PyObject_Vectorcall() 491 492 for func, args, expected in self.CALLS_POSARGS: 493 with self.subTest(func=func, args=args): 494 # kwnames=NULL 495 result = _testcapi.pyobject_vectorcall(func, args, None) 496 self.check_result(result, expected) 497 498 # kwnames=() 499 result = _testcapi.pyobject_vectorcall(func, args, ()) 500 self.check_result(result, expected) 501 502 if not args: 503 # kwnames=NULL 504 result = _testcapi.pyobject_vectorcall(func, None, None) 505 self.check_result(result, expected) 506 507 # kwnames=() 508 result = _testcapi.pyobject_vectorcall(func, None, ()) 509 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()) 515 result = _testcapi.pyobject_vectorcall(func, args, kwnames) 516 self.check_result(result, expected) 517 518 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) 534 535 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 597 # 3. vectorcall using PyObject_Vectorcall() 598 # 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 637 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 645 calls += [ 646 (dict.update, ({},), {"key":True}, None), 647 ({}.update, ({},), {"key":True}, None), 648 (MethodDescriptorHeap(), (0,), {}, True), 649 (MethodDescriptorOverridden(), (0,), {}, 'new'), 650 (MethodDescriptorSuper(), (0,), {}, True), 651 ] 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 669class 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 716if __name__ == "__main__": 717 unittest.main() 718