1import unittest 2from test.support import (cpython_only, is_wasi, requires_limited_api, Py_DEBUG, 3 set_recursion_limit, skip_on_s390x, import_helper) 4try: 5 import _testcapi 6except ImportError: 7 _testcapi = None 8try: 9 import _testlimitedcapi 10except ImportError: 11 _testlimitedcapi = None 12import struct 13import collections 14import itertools 15import gc 16import contextlib 17import sys 18import types 19 20 21class BadStr(str): 22 def __eq__(self, other): 23 return True 24 def __hash__(self): 25 # Guaranteed different hash 26 return str.__hash__(self) ^ 3 27 28 29class FunctionCalls(unittest.TestCase): 30 31 def test_kwargs_order(self): 32 # bpo-34320: **kwargs should preserve order of passed OrderedDict 33 od = collections.OrderedDict([('a', 1), ('b', 2)]) 34 od.move_to_end('a') 35 expected = list(od.items()) 36 37 def fn(**kw): 38 return kw 39 40 res = fn(**od) 41 self.assertIsInstance(res, dict) 42 self.assertEqual(list(res.items()), expected) 43 44 def test_frames_are_popped_after_failed_calls(self): 45 # GH-93252: stuff blows up if we don't pop the new frame after 46 # recovering from failed calls: 47 def f(): 48 pass 49 class C: 50 def m(self): 51 pass 52 callables = [f, C.m, [].__len__] 53 for c in callables: 54 for _ in range(1000): 55 try: 56 c(None) 57 except TypeError: 58 pass 59 # BOOM! 60 61 62@cpython_only 63class CFunctionCallsErrorMessages(unittest.TestCase): 64 65 def test_varargs0(self): 66 msg = r"__contains__\(\) takes exactly one argument \(0 given\)" 67 self.assertRaisesRegex(TypeError, msg, {}.__contains__) 68 69 def test_varargs2(self): 70 msg = r"__contains__\(\) takes exactly one argument \(2 given\)" 71 self.assertRaisesRegex(TypeError, msg, {}.__contains__, 0, 1) 72 73 def test_varargs3(self): 74 msg = r"^from_bytes\(\) takes at most 2 positional arguments \(3 given\)" 75 self.assertRaisesRegex(TypeError, msg, int.from_bytes, b'a', 'little', False) 76 77 def test_varargs1min(self): 78 msg = (r"get\(\) takes at least 1 argument \(0 given\)|" 79 r"get expected at least 1 argument, got 0") 80 self.assertRaisesRegex(TypeError, msg, {}.get) 81 82 msg = r"expected 1 argument, got 0" 83 self.assertRaisesRegex(TypeError, msg, {}.__delattr__) 84 85 def test_varargs2min(self): 86 msg = r"getattr expected at least 2 arguments, got 0" 87 self.assertRaisesRegex(TypeError, msg, getattr) 88 89 def test_varargs1max(self): 90 msg = (r"input\(\) takes at most 1 argument \(2 given\)|" 91 r"input expected at most 1 argument, got 2") 92 self.assertRaisesRegex(TypeError, msg, input, 1, 2) 93 94 def test_varargs2max(self): 95 msg = (r"get\(\) takes at most 2 arguments \(3 given\)|" 96 r"get expected at most 2 arguments, got 3") 97 self.assertRaisesRegex(TypeError, msg, {}.get, 1, 2, 3) 98 99 def test_varargs1_kw(self): 100 msg = r"__contains__\(\) takes no keyword arguments" 101 self.assertRaisesRegex(TypeError, msg, {}.__contains__, x=2) 102 103 def test_varargs2_kw(self): 104 msg = r"__contains__\(\) takes no keyword arguments" 105 self.assertRaisesRegex(TypeError, msg, {}.__contains__, x=2, y=2) 106 107 def test_varargs3_kw(self): 108 msg = r"bool\(\) takes no keyword arguments" 109 self.assertRaisesRegex(TypeError, msg, bool, x=2) 110 111 def test_varargs4_kw(self): 112 msg = r"^(list[.])?index\(\) takes no keyword arguments$" 113 self.assertRaisesRegex(TypeError, msg, [].index, x=2) 114 115 def test_varargs5_kw(self): 116 msg = r"^hasattr\(\) takes no keyword arguments$" 117 self.assertRaisesRegex(TypeError, msg, hasattr, x=2) 118 119 def test_varargs6_kw(self): 120 msg = r"^getattr\(\) takes no keyword arguments$" 121 self.assertRaisesRegex(TypeError, msg, getattr, x=2) 122 123 def test_varargs7_kw(self): 124 msg = r"^next\(\) takes no keyword arguments$" 125 self.assertRaisesRegex(TypeError, msg, next, x=2) 126 127 def test_varargs8_kw(self): 128 msg = r"^_struct[.]pack\(\) takes no keyword arguments$" 129 self.assertRaisesRegex(TypeError, msg, struct.pack, x=2) 130 131 def test_varargs9_kw(self): 132 msg = r"^_struct[.]pack_into\(\) takes no keyword arguments$" 133 self.assertRaisesRegex(TypeError, msg, struct.pack_into, x=2) 134 135 def test_varargs10_kw(self): 136 msg = r"^deque[.]index\(\) takes no keyword arguments$" 137 self.assertRaisesRegex(TypeError, msg, collections.deque().index, x=2) 138 139 def test_varargs11_kw(self): 140 msg = r"^Struct[.]pack\(\) takes no keyword arguments$" 141 self.assertRaisesRegex(TypeError, msg, struct.Struct.pack, struct.Struct(""), x=2) 142 143 def test_varargs12_kw(self): 144 msg = r"^staticmethod\(\) takes no keyword arguments$" 145 self.assertRaisesRegex(TypeError, msg, staticmethod, func=id) 146 147 def test_varargs13_kw(self): 148 msg = r"^classmethod\(\) takes no keyword arguments$" 149 self.assertRaisesRegex(TypeError, msg, classmethod, func=id) 150 151 def test_varargs14_kw(self): 152 msg = r"^product\(\) takes at most 1 keyword argument \(2 given\)$" 153 self.assertRaisesRegex(TypeError, msg, 154 itertools.product, 0, repeat=1, foo=2) 155 156 def test_varargs15_kw(self): 157 msg = r"^ImportError\(\) takes at most 3 keyword arguments \(4 given\)$" 158 self.assertRaisesRegex(TypeError, msg, 159 ImportError, 0, name=1, path=2, name_from=3, foo=3) 160 161 def test_varargs16_kw(self): 162 msg = r"^min\(\) takes at most 2 keyword arguments \(3 given\)$" 163 self.assertRaisesRegex(TypeError, msg, 164 min, 0, default=1, key=2, foo=3) 165 166 def test_varargs17_kw(self): 167 msg = r"print\(\) got an unexpected keyword argument 'foo'$" 168 self.assertRaisesRegex(TypeError, msg, 169 print, 0, sep=1, end=2, file=3, flush=4, foo=5) 170 171 def test_varargs18_kw(self): 172 # _PyArg_UnpackKeywordsWithVararg() 173 msg = r"invalid keyword argument for print\(\)$" 174 with self.assertRaisesRegex(TypeError, msg): 175 print(0, 1, **{BadStr('foo'): ','}) 176 177 def test_varargs19_kw(self): 178 # _PyArg_UnpackKeywords() 179 msg = r"invalid keyword argument for round\(\)$" 180 with self.assertRaisesRegex(TypeError, msg): 181 round(1.75, **{BadStr('foo'): 1}) 182 183 def test_oldargs0_1(self): 184 msg = r"keys\(\) takes no arguments \(1 given\)" 185 self.assertRaisesRegex(TypeError, msg, {}.keys, 0) 186 187 def test_oldargs0_2(self): 188 msg = r"keys\(\) takes no arguments \(2 given\)" 189 self.assertRaisesRegex(TypeError, msg, {}.keys, 0, 1) 190 191 def test_oldargs0_1_kw(self): 192 msg = r"keys\(\) takes no keyword arguments" 193 self.assertRaisesRegex(TypeError, msg, {}.keys, x=2) 194 195 def test_oldargs0_2_kw(self): 196 msg = r"keys\(\) takes no keyword arguments" 197 self.assertRaisesRegex(TypeError, msg, {}.keys, x=2, y=2) 198 199 def test_oldargs1_0(self): 200 msg = r"count\(\) takes exactly one argument \(0 given\)" 201 self.assertRaisesRegex(TypeError, msg, [].count) 202 203 def test_oldargs1_2(self): 204 msg = r"count\(\) takes exactly one argument \(2 given\)" 205 self.assertRaisesRegex(TypeError, msg, [].count, 1, 2) 206 207 def test_oldargs1_0_kw(self): 208 msg = r"count\(\) takes no keyword arguments" 209 self.assertRaisesRegex(TypeError, msg, [].count, x=2) 210 211 def test_oldargs1_1_kw(self): 212 msg = r"count\(\) takes no keyword arguments" 213 self.assertRaisesRegex(TypeError, msg, [].count, {}, x=2) 214 215 def test_oldargs1_2_kw(self): 216 msg = r"count\(\) takes no keyword arguments" 217 self.assertRaisesRegex(TypeError, msg, [].count, x=2, y=2) 218 219 def test_object_not_callable(self): 220 msg = r"^'object' object is not callable$" 221 self.assertRaisesRegex(TypeError, msg, object()) 222 223 def test_module_not_callable_no_suggestion_0(self): 224 msg = r"^'module' object is not callable$" 225 self.assertRaisesRegex(TypeError, msg, types.ModuleType("mod")) 226 227 def test_module_not_callable_no_suggestion_1(self): 228 msg = r"^'module' object is not callable$" 229 mod = types.ModuleType("mod") 230 mod.mod = 42 231 self.assertRaisesRegex(TypeError, msg, mod) 232 233 def test_module_not_callable_no_suggestion_2(self): 234 msg = r"^'module' object is not callable$" 235 mod = types.ModuleType("mod") 236 del mod.__name__ 237 self.assertRaisesRegex(TypeError, msg, mod) 238 239 def test_module_not_callable_no_suggestion_3(self): 240 msg = r"^'module' object is not callable$" 241 mod = types.ModuleType("mod") 242 mod.__name__ = 42 243 self.assertRaisesRegex(TypeError, msg, mod) 244 245 def test_module_not_callable_suggestion(self): 246 msg = r"^'module' object is not callable\. Did you mean: 'mod\.mod\(\.\.\.\)'\?$" 247 mod = types.ModuleType("mod") 248 mod.mod = lambda: ... 249 self.assertRaisesRegex(TypeError, msg, mod) 250 251 252@unittest.skipIf(_testcapi is None, "requires _testcapi") 253class TestCallingConventions(unittest.TestCase): 254 """Test calling using various C calling conventions (METH_*) from Python 255 256 Subclasses test several kinds of functions (module-level, methods, 257 class methods static methods) using these attributes: 258 obj: the object that contains tested functions (as attributes) 259 expected_self: expected "self" argument to the C function 260 261 The base class tests module-level functions. 262 """ 263 264 def setUp(self): 265 self.obj = self.expected_self = _testcapi 266 267 def test_varargs(self): 268 self.assertEqual( 269 self.obj.meth_varargs(1, 2, 3), 270 (self.expected_self, (1, 2, 3)), 271 ) 272 273 def test_varargs_ext(self): 274 self.assertEqual( 275 self.obj.meth_varargs(*(1, 2, 3)), 276 (self.expected_self, (1, 2, 3)), 277 ) 278 279 def test_varargs_error_kw(self): 280 msg = r"meth_varargs\(\) takes no keyword arguments" 281 self.assertRaisesRegex( 282 TypeError, msg, lambda: self.obj.meth_varargs(k=1), 283 ) 284 285 def test_varargs_keywords(self): 286 self.assertEqual( 287 self.obj.meth_varargs_keywords(1, 2, a=3, b=4), 288 (self.expected_self, (1, 2), {'a': 3, 'b': 4}) 289 ) 290 291 def test_varargs_keywords_ext(self): 292 self.assertEqual( 293 self.obj.meth_varargs_keywords(*[1, 2], **{'a': 3, 'b': 4}), 294 (self.expected_self, (1, 2), {'a': 3, 'b': 4}) 295 ) 296 297 def test_o(self): 298 self.assertEqual(self.obj.meth_o(1), (self.expected_self, 1)) 299 300 def test_o_ext(self): 301 self.assertEqual(self.obj.meth_o(*[1]), (self.expected_self, 1)) 302 303 def test_o_error_no_arg(self): 304 msg = r"meth_o\(\) takes exactly one argument \(0 given\)" 305 self.assertRaisesRegex(TypeError, msg, self.obj.meth_o) 306 307 def test_o_error_two_args(self): 308 msg = r"meth_o\(\) takes exactly one argument \(2 given\)" 309 self.assertRaisesRegex( 310 TypeError, msg, lambda: self.obj.meth_o(1, 2), 311 ) 312 313 def test_o_error_ext(self): 314 msg = r"meth_o\(\) takes exactly one argument \(3 given\)" 315 self.assertRaisesRegex( 316 TypeError, msg, lambda: self.obj.meth_o(*(1, 2, 3)), 317 ) 318 319 def test_o_error_kw(self): 320 msg = r"meth_o\(\) takes no keyword arguments" 321 self.assertRaisesRegex( 322 TypeError, msg, lambda: self.obj.meth_o(k=1), 323 ) 324 325 def test_o_error_arg_kw(self): 326 msg = r"meth_o\(\) takes no keyword arguments" 327 self.assertRaisesRegex( 328 TypeError, msg, lambda: self.obj.meth_o(k=1), 329 ) 330 331 def test_noargs(self): 332 self.assertEqual(self.obj.meth_noargs(), self.expected_self) 333 334 def test_noargs_ext(self): 335 self.assertEqual(self.obj.meth_noargs(*[]), self.expected_self) 336 337 def test_noargs_error_arg(self): 338 msg = r"meth_noargs\(\) takes no arguments \(1 given\)" 339 self.assertRaisesRegex( 340 TypeError, msg, lambda: self.obj.meth_noargs(1), 341 ) 342 343 def test_noargs_error_arg2(self): 344 msg = r"meth_noargs\(\) takes no arguments \(2 given\)" 345 self.assertRaisesRegex( 346 TypeError, msg, lambda: self.obj.meth_noargs(1, 2), 347 ) 348 349 def test_noargs_error_ext(self): 350 msg = r"meth_noargs\(\) takes no arguments \(3 given\)" 351 self.assertRaisesRegex( 352 TypeError, msg, lambda: self.obj.meth_noargs(*(1, 2, 3)), 353 ) 354 355 def test_noargs_error_kw(self): 356 msg = r"meth_noargs\(\) takes no keyword arguments" 357 self.assertRaisesRegex( 358 TypeError, msg, lambda: self.obj.meth_noargs(k=1), 359 ) 360 361 def test_fastcall(self): 362 self.assertEqual( 363 self.obj.meth_fastcall(1, 2, 3), 364 (self.expected_self, (1, 2, 3)), 365 ) 366 367 def test_fastcall_ext(self): 368 self.assertEqual( 369 self.obj.meth_fastcall(*(1, 2, 3)), 370 (self.expected_self, (1, 2, 3)), 371 ) 372 373 def test_fastcall_error_kw(self): 374 msg = r"meth_fastcall\(\) takes no keyword arguments" 375 self.assertRaisesRegex( 376 TypeError, msg, lambda: self.obj.meth_fastcall(k=1), 377 ) 378 379 def test_fastcall_keywords(self): 380 self.assertEqual( 381 self.obj.meth_fastcall_keywords(1, 2, a=3, b=4), 382 (self.expected_self, (1, 2), {'a': 3, 'b': 4}) 383 ) 384 385 def test_fastcall_keywords_ext(self): 386 self.assertEqual( 387 self.obj.meth_fastcall_keywords(*(1, 2), **{'a': 3, 'b': 4}), 388 (self.expected_self, (1, 2), {'a': 3, 'b': 4}) 389 ) 390 391 392class TestCallingConventionsInstance(TestCallingConventions): 393 """Test calling instance methods using various calling conventions""" 394 395 def setUp(self): 396 self.obj = self.expected_self = _testcapi.MethInstance() 397 398 399class TestCallingConventionsClass(TestCallingConventions): 400 """Test calling class methods using various calling conventions""" 401 402 def setUp(self): 403 self.obj = self.expected_self = _testcapi.MethClass 404 405 406class TestCallingConventionsClassInstance(TestCallingConventions): 407 """Test calling class methods on instance""" 408 409 def setUp(self): 410 self.obj = _testcapi.MethClass() 411 self.expected_self = _testcapi.MethClass 412 413 414class TestCallingConventionsStatic(TestCallingConventions): 415 """Test calling static methods using various calling conventions""" 416 417 def setUp(self): 418 self.obj = _testcapi.MethStatic() 419 self.expected_self = None 420 421 422def pyfunc(arg1, arg2): 423 return [arg1, arg2] 424 425 426def pyfunc_noarg(): 427 return "noarg" 428 429 430class PythonClass: 431 def method(self, arg1, arg2): 432 return [arg1, arg2] 433 434 def method_noarg(self): 435 return "noarg" 436 437 @classmethod 438 def class_method(cls): 439 return "classmethod" 440 441 @staticmethod 442 def static_method(): 443 return "staticmethod" 444 445 446PYTHON_INSTANCE = PythonClass() 447 448NULL_OR_EMPTY = object() 449 450 451class FastCallTests(unittest.TestCase): 452 """Test calling using various callables from C 453 """ 454 455 # Test calls with positional arguments 456 CALLS_POSARGS = [ 457 # (func, args: tuple, result) 458 459 # Python function with 2 arguments 460 (pyfunc, (1, 2), [1, 2]), 461 462 # Python function without argument 463 (pyfunc_noarg, (), "noarg"), 464 465 # Python class methods 466 (PythonClass.class_method, (), "classmethod"), 467 (PythonClass.static_method, (), "staticmethod"), 468 469 # Python instance methods 470 (PYTHON_INSTANCE.method, (1, 2), [1, 2]), 471 (PYTHON_INSTANCE.method_noarg, (), "noarg"), 472 (PYTHON_INSTANCE.class_method, (), "classmethod"), 473 (PYTHON_INSTANCE.static_method, (), "staticmethod"), 474 475 # C callables are added later 476 ] 477 478 # Test calls with positional and keyword arguments 479 CALLS_KWARGS = [ 480 # (func, args: tuple, kwargs: dict, result) 481 482 # Python function with 2 arguments 483 (pyfunc, (1,), {'arg2': 2}, [1, 2]), 484 (pyfunc, (), {'arg1': 1, 'arg2': 2}, [1, 2]), 485 486 # Python instance methods 487 (PYTHON_INSTANCE.method, (1,), {'arg2': 2}, [1, 2]), 488 (PYTHON_INSTANCE.method, (), {'arg1': 1, 'arg2': 2}, [1, 2]), 489 490 # C callables are added later 491 ] 492 493 # Add all the calling conventions and variants of C callables 494 if _testcapi: 495 _instance = _testcapi.MethInstance() 496 for obj, expected_self in ( 497 (_testcapi, _testcapi), # module-level function 498 (_instance, _instance), # bound method 499 (_testcapi.MethClass, _testcapi.MethClass), # class method on class 500 (_testcapi.MethClass(), _testcapi.MethClass), # class method on inst. 501 (_testcapi.MethStatic, None), # static method 502 ): 503 CALLS_POSARGS.extend([ 504 (obj.meth_varargs, (1, 2), (expected_self, (1, 2))), 505 (obj.meth_varargs_keywords, 506 (1, 2), (expected_self, (1, 2), NULL_OR_EMPTY)), 507 (obj.meth_fastcall, (1, 2), (expected_self, (1, 2))), 508 (obj.meth_fastcall, (), (expected_self, ())), 509 (obj.meth_fastcall_keywords, 510 (1, 2), (expected_self, (1, 2), NULL_OR_EMPTY)), 511 (obj.meth_fastcall_keywords, 512 (), (expected_self, (), NULL_OR_EMPTY)), 513 (obj.meth_noargs, (), expected_self), 514 (obj.meth_o, (123, ), (expected_self, 123)), 515 ]) 516 517 CALLS_KWARGS.extend([ 518 (obj.meth_varargs_keywords, 519 (1, 2), {'x': 'y'}, (expected_self, (1, 2), {'x': 'y'})), 520 (obj.meth_varargs_keywords, 521 (), {'x': 'y'}, (expected_self, (), {'x': 'y'})), 522 (obj.meth_varargs_keywords, 523 (1, 2), {}, (expected_self, (1, 2), NULL_OR_EMPTY)), 524 (obj.meth_fastcall_keywords, 525 (1, 2), {'x': 'y'}, (expected_self, (1, 2), {'x': 'y'})), 526 (obj.meth_fastcall_keywords, 527 (), {'x': 'y'}, (expected_self, (), {'x': 'y'})), 528 (obj.meth_fastcall_keywords, 529 (1, 2), {}, (expected_self, (1, 2), NULL_OR_EMPTY)), 530 ]) 531 532 def check_result(self, result, expected): 533 if isinstance(expected, tuple) and expected[-1] is NULL_OR_EMPTY: 534 if result[-1] in ({}, None): 535 expected = (*expected[:-1], result[-1]) 536 self.assertEqual(result, expected) 537 538 @unittest.skipIf(_testcapi is None, "requires _testcapi") 539 def test_vectorcall_dict(self): 540 # Test PyObject_VectorcallDict() 541 542 for func, args, expected in self.CALLS_POSARGS: 543 with self.subTest(func=func, args=args): 544 # kwargs=NULL 545 result = _testcapi.pyobject_fastcalldict(func, args, None) 546 self.check_result(result, expected) 547 548 if not args: 549 # args=NULL, nargs=0, kwargs=NULL 550 result = _testcapi.pyobject_fastcalldict(func, None, None) 551 self.check_result(result, expected) 552 553 for func, args, kwargs, expected in self.CALLS_KWARGS: 554 with self.subTest(func=func, args=args, kwargs=kwargs): 555 result = _testcapi.pyobject_fastcalldict(func, args, kwargs) 556 self.check_result(result, expected) 557 558 @unittest.skipIf(_testcapi is None, "requires _testcapi") 559 def test_vectorcall(self): 560 # Test PyObject_Vectorcall() 561 562 for func, args, expected in self.CALLS_POSARGS: 563 with self.subTest(func=func, args=args): 564 # kwnames=NULL 565 result = _testcapi.pyobject_vectorcall(func, args, None) 566 self.check_result(result, expected) 567 568 # kwnames=() 569 result = _testcapi.pyobject_vectorcall(func, args, ()) 570 self.check_result(result, expected) 571 572 if not args: 573 # kwnames=NULL 574 result = _testcapi.pyobject_vectorcall(func, None, None) 575 self.check_result(result, expected) 576 577 # kwnames=() 578 result = _testcapi.pyobject_vectorcall(func, None, ()) 579 self.check_result(result, expected) 580 581 for func, args, kwargs, expected in self.CALLS_KWARGS: 582 with self.subTest(func=func, args=args, kwargs=kwargs): 583 kwnames = tuple(kwargs.keys()) 584 args = args + tuple(kwargs.values()) 585 result = _testcapi.pyobject_vectorcall(func, args, kwnames) 586 self.check_result(result, expected) 587 588 def test_fastcall_clearing_dict(self): 589 # Test bpo-36907: the point of the test is just checking that this 590 # does not crash. 591 class IntWithDict: 592 __slots__ = ["kwargs"] 593 def __init__(self, **kwargs): 594 self.kwargs = kwargs 595 def __index__(self): 596 self.kwargs.clear() 597 gc.collect() 598 return 0 599 x = IntWithDict(optimize=IntWithDict()) 600 # We test the argument handling of "compile" here, the compilation 601 # itself is not relevant. When we pass flags=x below, x.__index__() is 602 # called, which changes the keywords dict. 603 compile("pass", "", "exec", x, **x.kwargs) 604 605 606Py_TPFLAGS_HAVE_VECTORCALL = 1 << 11 607Py_TPFLAGS_METHOD_DESCRIPTOR = 1 << 17 608 609 610def testfunction(self): 611 """some doc""" 612 return self 613 614 615def testfunction_kw(self, *, kw): 616 """some doc""" 617 return self 618 619 620ADAPTIVE_WARMUP_DELAY = 2 621 622 623@unittest.skipIf(_testcapi is None, "requires _testcapi") 624class TestPEP590(unittest.TestCase): 625 626 def test_method_descriptor_flag(self): 627 import functools 628 cached = functools.lru_cache(1)(testfunction) 629 630 self.assertFalse(type(repr).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR) 631 self.assertTrue(type(list.append).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR) 632 self.assertTrue(type(list.__add__).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR) 633 self.assertTrue(type(testfunction).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR) 634 self.assertTrue(type(cached).__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR) 635 636 self.assertTrue(_testcapi.MethodDescriptorBase.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR) 637 self.assertTrue(_testcapi.MethodDescriptorDerived.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR) 638 self.assertFalse(_testcapi.MethodDescriptorNopGet.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR) 639 640 # Mutable heap types should not inherit Py_TPFLAGS_METHOD_DESCRIPTOR 641 class MethodDescriptorHeap(_testcapi.MethodDescriptorBase): 642 pass 643 self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_METHOD_DESCRIPTOR) 644 645 def test_vectorcall_flag(self): 646 self.assertTrue(_testcapi.MethodDescriptorBase.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL) 647 self.assertTrue(_testcapi.MethodDescriptorDerived.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL) 648 self.assertFalse(_testcapi.MethodDescriptorNopGet.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL) 649 self.assertTrue(_testcapi.MethodDescriptor2.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL) 650 651 # Mutable heap types should inherit Py_TPFLAGS_HAVE_VECTORCALL, 652 # but should lose it when __call__ is overridden 653 class MethodDescriptorHeap(_testcapi.MethodDescriptorBase): 654 pass 655 self.assertTrue(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL) 656 MethodDescriptorHeap.__call__ = print 657 self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL) 658 659 # Mutable heap types should not inherit Py_TPFLAGS_HAVE_VECTORCALL if 660 # they define __call__ directly 661 class MethodDescriptorHeap(_testcapi.MethodDescriptorBase): 662 def __call__(self): 663 pass 664 self.assertFalse(MethodDescriptorHeap.__flags__ & Py_TPFLAGS_HAVE_VECTORCALL) 665 666 def test_vectorcall_override(self): 667 # Check that tp_call can correctly override vectorcall. 668 # MethodDescriptorNopGet implements tp_call but it inherits from 669 # MethodDescriptorBase, which implements vectorcall. Since 670 # MethodDescriptorNopGet returns the args tuple when called, we check 671 # additionally that no new tuple is created for this call. 672 args = tuple(range(5)) 673 f = _testcapi.MethodDescriptorNopGet() 674 self.assertIs(f(*args), args) 675 676 def test_vectorcall_override_on_mutable_class(self): 677 """Setting __call__ should disable vectorcall""" 678 TestType = _testcapi.make_vectorcall_class() 679 instance = TestType() 680 self.assertEqual(instance(), "tp_call") 681 instance.set_vectorcall(TestType) 682 self.assertEqual(instance(), "vectorcall") # assume vectorcall is used 683 TestType.__call__ = lambda self: "custom" 684 self.assertEqual(instance(), "custom") 685 686 def test_vectorcall_override_with_subclass(self): 687 """Setting __call__ on a superclass should disable vectorcall""" 688 SuperType = _testcapi.make_vectorcall_class() 689 class DerivedType(SuperType): 690 pass 691 692 instance = DerivedType() 693 694 # Derived types with its own vectorcall should be unaffected 695 UnaffectedType1 = _testcapi.make_vectorcall_class(DerivedType) 696 UnaffectedType2 = _testcapi.make_vectorcall_class(SuperType) 697 698 # Aside: Quickly check that the C helper actually made derived types 699 self.assertTrue(issubclass(UnaffectedType1, DerivedType)) 700 self.assertTrue(issubclass(UnaffectedType2, SuperType)) 701 702 # Initial state: tp_call 703 self.assertEqual(instance(), "tp_call") 704 self.assertEqual(_testcapi.has_vectorcall_flag(SuperType), True) 705 self.assertEqual(_testcapi.has_vectorcall_flag(DerivedType), True) 706 self.assertEqual(_testcapi.has_vectorcall_flag(UnaffectedType1), True) 707 self.assertEqual(_testcapi.has_vectorcall_flag(UnaffectedType2), True) 708 709 # Setting the vectorcall function 710 instance.set_vectorcall(SuperType) 711 712 self.assertEqual(instance(), "vectorcall") 713 self.assertEqual(_testcapi.has_vectorcall_flag(SuperType), True) 714 self.assertEqual(_testcapi.has_vectorcall_flag(DerivedType), True) 715 self.assertEqual(_testcapi.has_vectorcall_flag(UnaffectedType1), True) 716 self.assertEqual(_testcapi.has_vectorcall_flag(UnaffectedType2), True) 717 718 # Setting __call__ should remove vectorcall from all subclasses 719 SuperType.__call__ = lambda self: "custom" 720 721 self.assertEqual(instance(), "custom") 722 self.assertEqual(_testcapi.has_vectorcall_flag(SuperType), False) 723 self.assertEqual(_testcapi.has_vectorcall_flag(DerivedType), False) 724 self.assertEqual(_testcapi.has_vectorcall_flag(UnaffectedType1), True) 725 self.assertEqual(_testcapi.has_vectorcall_flag(UnaffectedType2), True) 726 727 728 def test_vectorcall(self): 729 # Test a bunch of different ways to call objects: 730 # 1. vectorcall using PyVectorcall_Call() 731 # (only for objects that support vectorcall directly) 732 # 2. normal call 733 # 3. vectorcall using PyObject_Vectorcall() 734 # 4. call as bound method 735 # 5. call using functools.partial 736 737 # A list of (function, args, kwargs, result) calls to test 738 calls = [(len, (range(42),), {}, 42), 739 (list.append, ([], 0), {}, None), 740 ([].append, (0,), {}, None), 741 (sum, ([36],), {"start":6}, 42), 742 (testfunction, (42,), {}, 42), 743 (testfunction_kw, (42,), {"kw":None}, 42), 744 (_testcapi.MethodDescriptorBase(), (0,), {}, True), 745 (_testcapi.MethodDescriptorDerived(), (0,), {}, True), 746 (_testcapi.MethodDescriptor2(), (0,), {}, False)] 747 748 from _testcapi import pyobject_vectorcall, pyvectorcall_call 749 from types import MethodType 750 from functools import partial 751 752 def vectorcall(func, args, kwargs): 753 args = *args, *kwargs.values() 754 kwnames = tuple(kwargs) 755 return pyobject_vectorcall(func, args, kwnames) 756 757 for (func, args, kwargs, expected) in calls: 758 with self.subTest(str(func)): 759 if not kwargs: 760 self.assertEqual(expected, pyvectorcall_call(func, args)) 761 self.assertEqual(expected, pyvectorcall_call(func, args, kwargs)) 762 763 # Add derived classes (which do not support vectorcall directly, 764 # but do support all other ways of calling). 765 766 class MethodDescriptorHeap(_testcapi.MethodDescriptorBase): 767 pass 768 769 class MethodDescriptorOverridden(_testcapi.MethodDescriptorBase): 770 def __call__(self, n): 771 return 'new' 772 773 class SuperBase: 774 def __call__(self, *args): 775 return super().__call__(*args) 776 777 class MethodDescriptorSuper(SuperBase, _testcapi.MethodDescriptorBase): 778 def __call__(self, *args): 779 return super().__call__(*args) 780 781 calls += [ 782 (dict.update, ({},), {"key":True}, None), 783 ({}.update, ({},), {"key":True}, None), 784 (MethodDescriptorHeap(), (0,), {}, True), 785 (MethodDescriptorOverridden(), (0,), {}, 'new'), 786 (MethodDescriptorSuper(), (0,), {}, True), 787 ] 788 789 for (func, args, kwargs, expected) in calls: 790 with self.subTest(str(func)): 791 args1 = args[1:] 792 meth = MethodType(func, args[0]) 793 wrapped = partial(func) 794 if not kwargs: 795 self.assertEqual(expected, func(*args)) 796 self.assertEqual(expected, pyobject_vectorcall(func, args, None)) 797 self.assertEqual(expected, meth(*args1)) 798 self.assertEqual(expected, wrapped(*args)) 799 self.assertEqual(expected, func(*args, **kwargs)) 800 self.assertEqual(expected, vectorcall(func, args, kwargs)) 801 self.assertEqual(expected, meth(*args1, **kwargs)) 802 self.assertEqual(expected, wrapped(*args, **kwargs)) 803 804 def test_setvectorcall(self): 805 from _testcapi import function_setvectorcall 806 def f(num): return num + 1 807 assert_equal = self.assertEqual 808 num = 10 809 assert_equal(11, f(num)) 810 function_setvectorcall(f) 811 # make sure specializer is triggered by running > 50 times 812 for _ in range(10 * ADAPTIVE_WARMUP_DELAY): 813 assert_equal("overridden", f(num)) 814 815 def test_setvectorcall_load_attr_specialization_skip(self): 816 from _testcapi import function_setvectorcall 817 818 class X: 819 def __getattribute__(self, attr): 820 return attr 821 822 assert_equal = self.assertEqual 823 x = X() 824 assert_equal("a", x.a) 825 function_setvectorcall(X.__getattribute__) 826 # make sure specialization doesn't trigger 827 # when vectorcall is overridden 828 for _ in range(ADAPTIVE_WARMUP_DELAY): 829 assert_equal("overridden", x.a) 830 831 def test_setvectorcall_load_attr_specialization_deopt(self): 832 from _testcapi import function_setvectorcall 833 834 class X: 835 def __getattribute__(self, attr): 836 return attr 837 838 def get_a(x): 839 return x.a 840 841 assert_equal = self.assertEqual 842 x = X() 843 # trigger LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN specialization 844 for _ in range(ADAPTIVE_WARMUP_DELAY): 845 assert_equal("a", get_a(x)) 846 function_setvectorcall(X.__getattribute__) 847 # make sure specialized LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 848 # gets deopted due to overridden vectorcall 849 for _ in range(ADAPTIVE_WARMUP_DELAY): 850 assert_equal("overridden", get_a(x)) 851 852 @requires_limited_api 853 def test_vectorcall_limited_incoming(self): 854 from _testcapi import pyobject_vectorcall 855 obj = _testlimitedcapi.LimitedVectorCallClass() 856 self.assertEqual(pyobject_vectorcall(obj, (), ()), "vectorcall called") 857 858 @requires_limited_api 859 def test_vectorcall_limited_outgoing(self): 860 from _testlimitedcapi import call_vectorcall 861 862 args_captured = [] 863 kwargs_captured = [] 864 865 def f(*args, **kwargs): 866 args_captured.append(args) 867 kwargs_captured.append(kwargs) 868 return "success" 869 870 self.assertEqual(call_vectorcall(f), "success") 871 self.assertEqual(args_captured, [("foo",)]) 872 self.assertEqual(kwargs_captured, [{"baz": "bar"}]) 873 874 @requires_limited_api 875 def test_vectorcall_limited_outgoing_method(self): 876 from _testlimitedcapi import call_vectorcall_method 877 878 args_captured = [] 879 kwargs_captured = [] 880 881 class TestInstance: 882 def f(self, *args, **kwargs): 883 args_captured.append(args) 884 kwargs_captured.append(kwargs) 885 return "success" 886 887 self.assertEqual(call_vectorcall_method(TestInstance()), "success") 888 self.assertEqual(args_captured, [("foo",)]) 889 self.assertEqual(kwargs_captured, [{"baz": "bar"}]) 890 891class A: 892 def method_two_args(self, x, y): 893 pass 894 895 @staticmethod 896 def static_no_args(): 897 pass 898 899 @staticmethod 900 def positional_only(arg, /): 901 pass 902 903@cpython_only 904class TestErrorMessagesUseQualifiedName(unittest.TestCase): 905 906 @contextlib.contextmanager 907 def check_raises_type_error(self, message): 908 with self.assertRaises(TypeError) as cm: 909 yield 910 self.assertEqual(str(cm.exception), message) 911 912 def test_missing_arguments(self): 913 msg = "A.method_two_args() missing 1 required positional argument: 'y'" 914 with self.check_raises_type_error(msg): 915 A().method_two_args("x") 916 917 def test_too_many_positional(self): 918 msg = "A.static_no_args() takes 0 positional arguments but 1 was given" 919 with self.check_raises_type_error(msg): 920 A.static_no_args("oops it's an arg") 921 922 def test_positional_only_passed_as_keyword(self): 923 msg = "A.positional_only() got some positional-only arguments passed as keyword arguments: 'arg'" 924 with self.check_raises_type_error(msg): 925 A.positional_only(arg="x") 926 927 def test_unexpected_keyword(self): 928 msg = "A.method_two_args() got an unexpected keyword argument 'bad'" 929 with self.check_raises_type_error(msg): 930 A().method_two_args(bad="x") 931 932 def test_multiple_values(self): 933 msg = "A.method_two_args() got multiple values for argument 'x'" 934 with self.check_raises_type_error(msg): 935 A().method_two_args("x", "y", x="oops") 936 937@cpython_only 938class TestErrorMessagesSuggestions(unittest.TestCase): 939 @contextlib.contextmanager 940 def check_suggestion_includes(self, message): 941 with self.assertRaises(TypeError) as cm: 942 yield 943 self.assertIn(f"Did you mean '{message}'?", str(cm.exception)) 944 945 @contextlib.contextmanager 946 def check_suggestion_not_present(self): 947 with self.assertRaises(TypeError) as cm: 948 yield 949 self.assertNotIn("Did you mean", str(cm.exception)) 950 951 def test_unexpected_keyword_suggestion_valid_positions(self): 952 def foo(blech=None, /, aaa=None, *args, late1=None): 953 pass 954 955 cases = [ 956 ("blach", None), 957 ("aa", "aaa"), 958 ("orgs", None), 959 ("late11", "late1"), 960 ] 961 962 for keyword, suggestion in cases: 963 with self.subTest(keyword): 964 ctx = self.check_suggestion_includes(suggestion) if suggestion else self.check_suggestion_not_present() 965 with ctx: 966 foo(**{keyword:None}) 967 968 def test_unexpected_keyword_suggestion_kinds(self): 969 970 def substitution(noise=None, more_noise=None, a = None, blech = None): 971 pass 972 973 def elimination(noise = None, more_noise = None, a = None, blch = None): 974 pass 975 976 def addition(noise = None, more_noise = None, a = None, bluchin = None): 977 pass 978 979 def substitution_over_elimination(blach = None, bluc = None): 980 pass 981 982 def substitution_over_addition(blach = None, bluchi = None): 983 pass 984 985 def elimination_over_addition(bluc = None, blucha = None): 986 pass 987 988 def case_change_over_substitution(BLuch=None, Luch = None, fluch = None): 989 pass 990 991 for func, suggestion in [ 992 (addition, "bluchin"), 993 (substitution, "blech"), 994 (elimination, "blch"), 995 (addition, "bluchin"), 996 (substitution_over_elimination, "blach"), 997 (substitution_over_addition, "blach"), 998 (elimination_over_addition, "bluc"), 999 (case_change_over_substitution, "BLuch"), 1000 ]: 1001 with self.subTest(suggestion): 1002 with self.check_suggestion_includes(suggestion): 1003 func(bluch=None) 1004 1005 def test_unexpected_keyword_suggestion_via_getargs(self): 1006 with self.check_suggestion_includes("maxsplit"): 1007 "foo".split(maxsplt=1) 1008 1009 self.assertRaisesRegex( 1010 TypeError, r"split\(\) got an unexpected keyword argument 'blech'$", 1011 "foo".split, blech=1 1012 ) 1013 with self.check_suggestion_not_present(): 1014 "foo".split(blech=1) 1015 with self.check_suggestion_not_present(): 1016 "foo".split(more_noise=1, maxsplt=1) 1017 1018 # Also test the vgetargskeywords path 1019 with self.check_suggestion_includes("name"): 1020 ImportError(namez="oops") 1021 1022 self.assertRaisesRegex( 1023 TypeError, r"ImportError\(\) got an unexpected keyword argument 'blech'$", 1024 ImportError, blech=1 1025 ) 1026 with self.check_suggestion_not_present(): 1027 ImportError(blech=1) 1028 with self.check_suggestion_not_present(): 1029 ImportError(blech=1, namez="oops") 1030 1031@cpython_only 1032class TestRecursion(unittest.TestCase): 1033 1034 @skip_on_s390x 1035 @unittest.skipIf(is_wasi and Py_DEBUG, "requires deep stack") 1036 @unittest.skipIf(_testcapi is None, "requires _testcapi") 1037 def test_super_deep(self): 1038 1039 def recurse(n): 1040 if n: 1041 recurse(n-1) 1042 1043 def py_recurse(n, m): 1044 if n: 1045 py_recurse(n-1, m) 1046 else: 1047 c_py_recurse(m-1) 1048 1049 def c_recurse(n): 1050 if n: 1051 _testcapi.pyobject_vectorcall(c_recurse, (n-1,), ()) 1052 1053 def c_py_recurse(m): 1054 if m: 1055 _testcapi.pyobject_vectorcall(py_recurse, (1000, m), ()) 1056 1057 with set_recursion_limit(100_000): 1058 recurse(90_000) 1059 with self.assertRaises(RecursionError): 1060 recurse(101_000) 1061 c_recurse(100) 1062 with self.assertRaises(RecursionError): 1063 c_recurse(90_000) 1064 c_py_recurse(90) 1065 with self.assertRaises(RecursionError): 1066 c_py_recurse(100_000) 1067 1068 1069class TestFunctionWithManyArgs(unittest.TestCase): 1070 def test_function_with_many_args(self): 1071 for N in (10, 500, 1000): 1072 with self.subTest(N=N): 1073 args = ",".join([f"a{i}" for i in range(N)]) 1074 src = f"def f({args}) : return a{N//2}" 1075 l = {} 1076 exec(src, {}, l) 1077 self.assertEqual(l['f'](*range(N)), N//2) 1078 1079 1080@unittest.skipIf(_testcapi is None, 'need _testcapi') 1081class TestCAPI(unittest.TestCase): 1082 def test_cfunction_call(self): 1083 def func(*args, **kwargs): 1084 return (args, kwargs) 1085 1086 # PyCFunction_Call() was removed in Python 3.13 API, but was kept in 1087 # the stable ABI. 1088 def PyCFunction_Call(func, *args, **kwargs): 1089 if kwargs: 1090 return _testcapi.pycfunction_call(func, args, kwargs) 1091 else: 1092 return _testcapi.pycfunction_call(func, args) 1093 1094 self.assertEqual(PyCFunction_Call(func), ((), {})) 1095 self.assertEqual(PyCFunction_Call(func, 1, 2, 3), ((1, 2, 3), {})) 1096 self.assertEqual(PyCFunction_Call(func, "arg", num=5), (("arg",), {'num': 5})) 1097 1098 1099if __name__ == "__main__": 1100 unittest.main() 1101