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 BadStr(str): 15 def __eq__(self, other): 16 return True 17 def __hash__(self): 18 # Guaranteed different hash 19 return str.__hash__(self) ^ 3 20 21 22class FunctionCalls(unittest.TestCase): 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 51class CFunctionCallsErrorMessages(unittest.TestCase): 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 206class TestCallingConventions(unittest.TestCase): 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 345class TestCallingConventionsInstance(TestCallingConventions): 346 """Test calling instance methods using various calling conventions""" 347 348 def setUp(self): 349 self.obj = self.expected_self = _testcapi.MethInstance() 350 351 352class TestCallingConventionsClass(TestCallingConventions): 353 """Test calling class methods using various calling conventions""" 354 355 def setUp(self): 356 self.obj = self.expected_self = _testcapi.MethClass 357 358 359class TestCallingConventionsClassInstance(TestCallingConventions): 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 367class TestCallingConventionsStatic(TestCallingConventions): 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 375def pyfunc(arg1, arg2): 376 return [arg1, arg2] 377 378 379def pyfunc_noarg(): 380 return "noarg" 381 382 383class PythonClass: 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 399PYTHON_INSTANCE = PythonClass() 400 401NULL_OR_EMPTY = object() 402 403class FastCallTests(unittest.TestCase): 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 IntWithDict: 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 568Py_TPFLAGS_HAVE_VECTORCALL = 1 << 11 569Py_TPFLAGS_METHOD_DESCRIPTOR = 1 << 17 570 571 572def testfunction(self): 573 """some doc""" 574 return self 575 576 577def testfunction_kw(self, *, kw): 578 """some doc""" 579 return self 580 581 582class TestPEP590(unittest.TestCase): 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 MethodDescriptorHeap(_testcapi.MethodDescriptorBase): 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 MethodDescriptorHeap(_testcapi.MethodDescriptorBase): 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 MethodDescriptorHeap(_testcapi.MethodDescriptorBase): 663 pass 664 665 class MethodDescriptorOverridden(_testcapi.MethodDescriptorBase): 666 def __call__(self, n): 667 return 'new' 668 669 class SuperBase: 670 def __call__(self, *args): 671 return super().__call__(*args) 672 673 class MethodDescriptorSuper(SuperBase, _testcapi.MethodDescriptorBase): 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 701class A: 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 714class TestErrorMessagesUseQualifiedName(unittest.TestCase): 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 748if __name__ == "__main__": 749 unittest.main() 750