1import builtins 2import collections 3import datetime 4import functools 5import importlib 6import inspect 7import io 8import linecache 9import os 10import dis 11from os.path import normcase 12import _pickle 13import pickle 14import shutil 15import sys 16import types 17import textwrap 18import unicodedata 19import unittest 20import unittest.mock 21import warnings 22 23try: 24 from concurrent.futures import ThreadPoolExecutor 25except ImportError: 26 ThreadPoolExecutor = None 27 28from test.support import cpython_only 29from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ 30from test.support.import_helper import DirsOnSysPath 31from test.support.os_helper import TESTFN 32from test.support.script_helper import assert_python_ok, assert_python_failure 33from test import inspect_fodder as mod 34from test import inspect_fodder2 as mod2 35from test import support 36from test import inspect_stock_annotations 37from test import inspect_stringized_annotations 38from test import inspect_stringized_annotations_2 39 40from test.test_import import _ready_to_import 41 42 43# Functions tested in this suite: 44# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode, 45# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers, 46# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource, 47# getclasstree, getargvalues, formatargvalues, 48# currentframe, stack, trace, isdatadescriptor, 49# ismethodwrapper 50 51# NOTE: There are some additional tests relating to interaction with 52# zipimport in the test_zipimport_support test module. 53 54modfile = mod.__file__ 55if modfile.endswith(('c', 'o')): 56 modfile = modfile[:-1] 57 58# Normalize file names: on Windows, the case of file names of compiled 59# modules depends on the path used to start the python executable. 60modfile = normcase(modfile) 61 62def revise(filename, *args): 63 return (normcase(filename),) + args 64 65git = mod.StupidGit() 66 67 68def signatures_with_lexicographic_keyword_only_parameters(): 69 """ 70 Yields a whole bunch of functions with only keyword-only parameters, 71 where those parameters are always in lexicographically sorted order. 72 """ 73 parameters = ['a', 'bar', 'c', 'delta', 'ephraim', 'magical', 'yoyo', 'z'] 74 for i in range(1, 2**len(parameters)): 75 p = [] 76 bit = 1 77 for j in range(len(parameters)): 78 if i & (bit << j): 79 p.append(parameters[j]) 80 fn_text = "def foo(*, " + ", ".join(p) + "): pass" 81 symbols = {} 82 exec(fn_text, symbols, symbols) 83 yield symbols['foo'] 84 85 86def unsorted_keyword_only_parameters_fn(*, throw, out, the, baby, with_, 87 the_, bathwater): 88 pass 89 90unsorted_keyword_only_parameters = 'throw out the baby with_ the_ bathwater'.split() 91 92class IsTestBase(unittest.TestCase): 93 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode, 94 inspect.isframe, inspect.isfunction, inspect.ismethod, 95 inspect.ismodule, inspect.istraceback, 96 inspect.isgenerator, inspect.isgeneratorfunction, 97 inspect.iscoroutine, inspect.iscoroutinefunction, 98 inspect.isasyncgen, inspect.isasyncgenfunction, 99 inspect.ismethodwrapper]) 100 101 def istest(self, predicate, exp): 102 obj = eval(exp) 103 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp)) 104 105 for other in self.predicates - set([predicate]): 106 if (predicate == inspect.isgeneratorfunction or \ 107 predicate == inspect.isasyncgenfunction or \ 108 predicate == inspect.iscoroutinefunction) and \ 109 other == inspect.isfunction: 110 continue 111 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp)) 112 113 def test__all__(self): 114 support.check__all__(self, inspect, not_exported=("modulesbyfile",)) 115 116def generator_function_example(self): 117 for i in range(2): 118 yield i 119 120async def async_generator_function_example(self): 121 async for i in range(2): 122 yield i 123 124async def coroutine_function_example(self): 125 return 'spam' 126 127@types.coroutine 128def gen_coroutine_function_example(self): 129 yield 130 return 'spam' 131 132class TestPredicates(IsTestBase): 133 134 def test_excluding_predicates(self): 135 global tb 136 self.istest(inspect.isbuiltin, 'sys.exit') 137 self.istest(inspect.isbuiltin, '[].append') 138 self.istest(inspect.iscode, 'mod.spam.__code__') 139 try: 140 1/0 141 except Exception as e: 142 tb = e.__traceback__ 143 self.istest(inspect.isframe, 'tb.tb_frame') 144 self.istest(inspect.istraceback, 'tb') 145 if hasattr(types, 'GetSetDescriptorType'): 146 self.istest(inspect.isgetsetdescriptor, 147 'type(tb.tb_frame).f_locals') 148 else: 149 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals)) 150 finally: 151 # Clear traceback and all the frames and local variables hanging to it. 152 tb = None 153 self.istest(inspect.isfunction, 'mod.spam') 154 self.istest(inspect.isfunction, 'mod.StupidGit.abuse') 155 self.istest(inspect.ismethod, 'git.argue') 156 self.istest(inspect.ismethod, 'mod.custom_method') 157 self.istest(inspect.ismodule, 'mod') 158 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory') 159 self.istest(inspect.isgenerator, '(x for x in range(2))') 160 self.istest(inspect.isgeneratorfunction, 'generator_function_example') 161 self.istest(inspect.isasyncgen, 162 'async_generator_function_example(1)') 163 self.istest(inspect.isasyncgenfunction, 164 'async_generator_function_example') 165 166 with warnings.catch_warnings(): 167 warnings.simplefilter("ignore") 168 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)') 169 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example') 170 171 if hasattr(types, 'MemberDescriptorType'): 172 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days') 173 else: 174 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days)) 175 self.istest(inspect.ismethodwrapper, "object().__str__") 176 self.istest(inspect.ismethodwrapper, "object().__eq__") 177 self.istest(inspect.ismethodwrapper, "object().__repr__") 178 self.assertFalse(inspect.ismethodwrapper(type)) 179 self.assertFalse(inspect.ismethodwrapper(int)) 180 self.assertFalse(inspect.ismethodwrapper(type("AnyClass", (), {}))) 181 182 183 184 def test_iscoroutine(self): 185 async_gen_coro = async_generator_function_example(1) 186 gen_coro = gen_coroutine_function_example(1) 187 coro = coroutine_function_example(1) 188 189 self.assertFalse( 190 inspect.iscoroutinefunction(gen_coroutine_function_example)) 191 self.assertFalse( 192 inspect.iscoroutinefunction( 193 functools.partial(functools.partial( 194 gen_coroutine_function_example)))) 195 self.assertFalse(inspect.iscoroutine(gen_coro)) 196 197 self.assertTrue( 198 inspect.isgeneratorfunction(gen_coroutine_function_example)) 199 self.assertTrue( 200 inspect.isgeneratorfunction( 201 functools.partial(functools.partial( 202 gen_coroutine_function_example)))) 203 self.assertTrue(inspect.isgenerator(gen_coro)) 204 205 self.assertFalse( 206 inspect.iscoroutinefunction(unittest.mock.Mock())) 207 self.assertTrue( 208 inspect.iscoroutinefunction(unittest.mock.AsyncMock())) 209 self.assertTrue( 210 inspect.iscoroutinefunction(coroutine_function_example)) 211 self.assertTrue( 212 inspect.iscoroutinefunction( 213 functools.partial(functools.partial( 214 coroutine_function_example)))) 215 self.assertTrue(inspect.iscoroutine(coro)) 216 217 self.assertFalse( 218 inspect.isgeneratorfunction(unittest.mock.Mock())) 219 self.assertFalse( 220 inspect.isgeneratorfunction(unittest.mock.AsyncMock())) 221 self.assertFalse( 222 inspect.isgeneratorfunction(coroutine_function_example)) 223 self.assertFalse( 224 inspect.isgeneratorfunction( 225 functools.partial(functools.partial( 226 coroutine_function_example)))) 227 self.assertFalse(inspect.isgenerator(coro)) 228 229 self.assertFalse( 230 inspect.isasyncgenfunction(unittest.mock.Mock())) 231 self.assertFalse( 232 inspect.isasyncgenfunction(unittest.mock.AsyncMock())) 233 self.assertFalse( 234 inspect.isasyncgenfunction(coroutine_function_example)) 235 self.assertTrue( 236 inspect.isasyncgenfunction(async_generator_function_example)) 237 self.assertTrue( 238 inspect.isasyncgenfunction( 239 functools.partial(functools.partial( 240 async_generator_function_example)))) 241 self.assertTrue(inspect.isasyncgen(async_gen_coro)) 242 243 coro.close(); gen_coro.close(); # silence warnings 244 245 def test_isawaitable(self): 246 def gen(): yield 247 self.assertFalse(inspect.isawaitable(gen())) 248 249 coro = coroutine_function_example(1) 250 gen_coro = gen_coroutine_function_example(1) 251 252 self.assertTrue(inspect.isawaitable(coro)) 253 self.assertTrue(inspect.isawaitable(gen_coro)) 254 255 class Future: 256 def __await__(): 257 pass 258 self.assertTrue(inspect.isawaitable(Future())) 259 self.assertFalse(inspect.isawaitable(Future)) 260 261 class NotFuture: pass 262 not_fut = NotFuture() 263 not_fut.__await__ = lambda: None 264 self.assertFalse(inspect.isawaitable(not_fut)) 265 266 coro.close(); gen_coro.close() # silence warnings 267 268 def test_isroutine(self): 269 # method 270 self.assertTrue(inspect.isroutine(git.argue)) 271 self.assertTrue(inspect.isroutine(mod.custom_method)) 272 self.assertTrue(inspect.isroutine([].count)) 273 # function 274 self.assertTrue(inspect.isroutine(mod.spam)) 275 self.assertTrue(inspect.isroutine(mod.StupidGit.abuse)) 276 # slot-wrapper 277 self.assertTrue(inspect.isroutine(object.__init__)) 278 self.assertTrue(inspect.isroutine(object.__str__)) 279 self.assertTrue(inspect.isroutine(object.__lt__)) 280 self.assertTrue(inspect.isroutine(int.__lt__)) 281 # method-wrapper 282 self.assertTrue(inspect.isroutine(object().__init__)) 283 self.assertTrue(inspect.isroutine(object().__str__)) 284 self.assertTrue(inspect.isroutine(object().__lt__)) 285 self.assertTrue(inspect.isroutine((42).__lt__)) 286 # method-descriptor 287 self.assertTrue(inspect.isroutine(str.join)) 288 self.assertTrue(inspect.isroutine(list.append)) 289 self.assertTrue(inspect.isroutine(''.join)) 290 self.assertTrue(inspect.isroutine([].append)) 291 # object 292 self.assertFalse(inspect.isroutine(object)) 293 self.assertFalse(inspect.isroutine(object())) 294 self.assertFalse(inspect.isroutine(str())) 295 # module 296 self.assertFalse(inspect.isroutine(mod)) 297 # type 298 self.assertFalse(inspect.isroutine(type)) 299 self.assertFalse(inspect.isroutine(int)) 300 self.assertFalse(inspect.isroutine(type('some_class', (), {}))) 301 302 def test_isclass(self): 303 self.istest(inspect.isclass, 'mod.StupidGit') 304 self.assertTrue(inspect.isclass(list)) 305 306 class CustomGetattr(object): 307 def __getattr__(self, attr): 308 return None 309 self.assertFalse(inspect.isclass(CustomGetattr())) 310 311 def test_get_slot_members(self): 312 class C(object): 313 __slots__ = ("a", "b") 314 x = C() 315 x.a = 42 316 members = dict(inspect.getmembers(x)) 317 self.assertIn('a', members) 318 self.assertNotIn('b', members) 319 320 def test_isabstract(self): 321 from abc import ABCMeta, abstractmethod 322 323 class AbstractClassExample(metaclass=ABCMeta): 324 325 @abstractmethod 326 def foo(self): 327 pass 328 329 class ClassExample(AbstractClassExample): 330 def foo(self): 331 pass 332 333 a = ClassExample() 334 335 # Test general behaviour. 336 self.assertTrue(inspect.isabstract(AbstractClassExample)) 337 self.assertFalse(inspect.isabstract(ClassExample)) 338 self.assertFalse(inspect.isabstract(a)) 339 self.assertFalse(inspect.isabstract(int)) 340 self.assertFalse(inspect.isabstract(5)) 341 342 def test_isabstract_during_init_subclass(self): 343 from abc import ABCMeta, abstractmethod 344 isabstract_checks = [] 345 class AbstractChecker(metaclass=ABCMeta): 346 def __init_subclass__(cls): 347 isabstract_checks.append(inspect.isabstract(cls)) 348 class AbstractClassExample(AbstractChecker): 349 @abstractmethod 350 def foo(self): 351 pass 352 class ClassExample(AbstractClassExample): 353 def foo(self): 354 pass 355 self.assertEqual(isabstract_checks, [True, False]) 356 357 isabstract_checks.clear() 358 class AbstractChild(AbstractClassExample): 359 pass 360 class AbstractGrandchild(AbstractChild): 361 pass 362 class ConcreteGrandchild(ClassExample): 363 pass 364 self.assertEqual(isabstract_checks, [True, True, False]) 365 366 367class TestInterpreterStack(IsTestBase): 368 def __init__(self, *args, **kwargs): 369 unittest.TestCase.__init__(self, *args, **kwargs) 370 371 git.abuse(7, 8, 9) 372 373 def test_abuse_done(self): 374 self.istest(inspect.istraceback, 'git.ex[2]') 375 self.istest(inspect.isframe, 'mod.fr') 376 377 def test_stack(self): 378 self.assertTrue(len(mod.st) >= 5) 379 frame1, frame2, frame3, frame4, *_ = mod.st 380 frameinfo = revise(*frame1[1:]) 381 self.assertEqual(frameinfo, 382 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0)) 383 self.assertEqual(frame1.positions, dis.Positions(16, 16, 9, 24)) 384 frameinfo = revise(*frame2[1:]) 385 self.assertEqual(frameinfo, 386 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0)) 387 self.assertEqual(frame2.positions, dis.Positions(9, 9, 4, 22)) 388 frameinfo = revise(*frame3[1:]) 389 self.assertEqual(frameinfo, 390 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0)) 391 self.assertEqual(frame3.positions, dis.Positions(43, 43, 12, 25)) 392 frameinfo = revise(*frame4[1:]) 393 self.assertEqual(frameinfo, 394 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0)) 395 self.assertEqual(frame4.positions, dis.Positions(39, 39, 8, 27)) 396 # Test named tuple fields 397 record = mod.st[0] 398 self.assertIs(record.frame, mod.fr) 399 self.assertEqual(record.lineno, 16) 400 self.assertEqual(record.filename, mod.__file__) 401 self.assertEqual(record.function, 'eggs') 402 self.assertIn('inspect.stack()', record.code_context[0]) 403 self.assertEqual(record.index, 0) 404 405 def test_trace(self): 406 self.assertEqual(len(git.tr), 3) 407 frame1, frame2, frame3, = git.tr 408 self.assertEqual(revise(*frame1[1:]), 409 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0)) 410 self.assertEqual(frame1.positions, dis.Positions(43, 43, 12, 25)) 411 self.assertEqual(revise(*frame2[1:]), 412 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0)) 413 self.assertEqual(frame2.positions, dis.Positions(9, 9, 4, 22)) 414 self.assertEqual(revise(*frame3[1:]), 415 (modfile, 18, 'eggs', [' q = y / 0\n'], 0)) 416 self.assertEqual(frame3.positions, dis.Positions(18, 18, 8, 13)) 417 418 def test_frame(self): 419 args, varargs, varkw, locals = inspect.getargvalues(mod.fr) 420 self.assertEqual(args, ['x', 'y']) 421 self.assertEqual(varargs, None) 422 self.assertEqual(varkw, None) 423 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14}) 424 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals), 425 '(x=11, y=14)') 426 427 def test_previous_frame(self): 428 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back) 429 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f']) 430 self.assertEqual(varargs, 'g') 431 self.assertEqual(varkw, 'h') 432 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals), 433 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})') 434 435class GetSourceBase(unittest.TestCase): 436 # Subclasses must override. 437 fodderModule = None 438 439 def setUp(self): 440 with open(inspect.getsourcefile(self.fodderModule), encoding="utf-8") as fp: 441 self.source = fp.read() 442 443 def sourcerange(self, top, bottom): 444 lines = self.source.split("\n") 445 return "\n".join(lines[top-1:bottom]) + ("\n" if bottom else "") 446 447 def assertSourceEqual(self, obj, top, bottom): 448 self.assertEqual(inspect.getsource(obj), 449 self.sourcerange(top, bottom)) 450 451class SlotUser: 452 'Docstrings for __slots__' 453 __slots__ = {'power': 'measured in kilowatts', 454 'distance': 'measured in kilometers'} 455 456class TestRetrievingSourceCode(GetSourceBase): 457 fodderModule = mod 458 459 def test_getclasses(self): 460 classes = inspect.getmembers(mod, inspect.isclass) 461 self.assertEqual(classes, 462 [('FesteringGob', mod.FesteringGob), 463 ('MalodorousPervert', mod.MalodorousPervert), 464 ('ParrotDroppings', mod.ParrotDroppings), 465 ('StupidGit', mod.StupidGit), 466 ('Tit', mod.MalodorousPervert), 467 ('WhichComments', mod.WhichComments), 468 ]) 469 tree = inspect.getclasstree([cls[1] for cls in classes]) 470 self.assertEqual(tree, 471 [(object, ()), 472 [(mod.ParrotDroppings, (object,)), 473 [(mod.FesteringGob, (mod.MalodorousPervert, 474 mod.ParrotDroppings)) 475 ], 476 (mod.StupidGit, (object,)), 477 [(mod.MalodorousPervert, (mod.StupidGit,)), 478 [(mod.FesteringGob, (mod.MalodorousPervert, 479 mod.ParrotDroppings)) 480 ] 481 ], 482 (mod.WhichComments, (object,),) 483 ] 484 ]) 485 tree = inspect.getclasstree([cls[1] for cls in classes], True) 486 self.assertEqual(tree, 487 [(object, ()), 488 [(mod.ParrotDroppings, (object,)), 489 (mod.StupidGit, (object,)), 490 [(mod.MalodorousPervert, (mod.StupidGit,)), 491 [(mod.FesteringGob, (mod.MalodorousPervert, 492 mod.ParrotDroppings)) 493 ] 494 ], 495 (mod.WhichComments, (object,),) 496 ] 497 ]) 498 499 def test_getfunctions(self): 500 functions = inspect.getmembers(mod, inspect.isfunction) 501 self.assertEqual(functions, [('eggs', mod.eggs), 502 ('lobbest', mod.lobbest), 503 ('spam', mod.spam)]) 504 505 @unittest.skipIf(sys.flags.optimize >= 2, 506 "Docstrings are omitted with -O2 and above") 507 def test_getdoc(self): 508 self.assertEqual(inspect.getdoc(mod), 'A module docstring.') 509 self.assertEqual(inspect.getdoc(mod.StupidGit), 510 'A longer,\n\nindented\n\ndocstring.') 511 self.assertEqual(inspect.getdoc(git.abuse), 512 'Another\n\ndocstring\n\ncontaining\n\ntabs') 513 self.assertEqual(inspect.getdoc(SlotUser.power), 514 'measured in kilowatts') 515 self.assertEqual(inspect.getdoc(SlotUser.distance), 516 'measured in kilometers') 517 518 @unittest.skipIf(sys.flags.optimize >= 2, 519 "Docstrings are omitted with -O2 and above") 520 def test_getdoc_inherited(self): 521 self.assertEqual(inspect.getdoc(mod.FesteringGob), 522 'A longer,\n\nindented\n\ndocstring.') 523 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse), 524 'Another\n\ndocstring\n\ncontaining\n\ntabs') 525 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse), 526 'Another\n\ndocstring\n\ncontaining\n\ntabs') 527 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction), 528 'The automatic gainsaying.') 529 530 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings") 531 def test_finddoc(self): 532 finddoc = inspect._finddoc 533 self.assertEqual(finddoc(int), int.__doc__) 534 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__) 535 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__) 536 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__) 537 self.assertEqual(finddoc(int.real), int.real.__doc__) 538 539 def test_cleandoc(self): 540 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'), 541 'An\nindented\ndocstring.') 542 543 def test_getcomments(self): 544 self.assertEqual(inspect.getcomments(mod), '# line 1\n') 545 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n') 546 self.assertEqual(inspect.getcomments(mod2.cls160), '# line 159\n') 547 # If the object source file is not available, return None. 548 co = compile('x=1', '_non_existing_filename.py', 'exec') 549 self.assertIsNone(inspect.getcomments(co)) 550 # If the object has been defined in C, return None. 551 self.assertIsNone(inspect.getcomments(list)) 552 553 def test_getmodule(self): 554 # Check actual module 555 self.assertEqual(inspect.getmodule(mod), mod) 556 # Check class (uses __module__ attribute) 557 self.assertEqual(inspect.getmodule(mod.StupidGit), mod) 558 # Check a method (no __module__ attribute, falls back to filename) 559 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod) 560 # Do it again (check the caching isn't broken) 561 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod) 562 # Check a builtin 563 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"]) 564 # Check filename override 565 self.assertEqual(inspect.getmodule(None, modfile), mod) 566 567 def test_getmodule_file_not_found(self): 568 # See bpo-45406 569 def _getabsfile(obj, _filename): 570 raise FileNotFoundError('bad file') 571 with unittest.mock.patch('inspect.getabsfile', _getabsfile): 572 f = inspect.currentframe() 573 self.assertIsNone(inspect.getmodule(f)) 574 inspect.getouterframes(f) # smoke test 575 576 def test_getframeinfo_get_first_line(self): 577 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50) 578 self.assertEqual(frame_info.code_context[0], "# line 1\n") 579 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n") 580 581 def test_getsource(self): 582 self.assertSourceEqual(git.abuse, 29, 39) 583 self.assertSourceEqual(mod.StupidGit, 21, 51) 584 self.assertSourceEqual(mod.lobbest, 75, 76) 585 586 def test_getsourcefile(self): 587 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile) 588 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile) 589 fn = "_non_existing_filename_used_for_sourcefile_test.py" 590 co = compile("x=1", fn, "exec") 591 self.assertEqual(inspect.getsourcefile(co), None) 592 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename) 593 try: 594 self.assertEqual(normcase(inspect.getsourcefile(co)), fn) 595 finally: 596 del linecache.cache[co.co_filename] 597 598 def test_getfile(self): 599 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__) 600 601 def test_getfile_builtin_module(self): 602 with self.assertRaises(TypeError) as e: 603 inspect.getfile(sys) 604 self.assertTrue(str(e.exception).startswith('<module')) 605 606 def test_getfile_builtin_class(self): 607 with self.assertRaises(TypeError) as e: 608 inspect.getfile(int) 609 self.assertTrue(str(e.exception).startswith('<class')) 610 611 def test_getfile_builtin_function_or_method(self): 612 with self.assertRaises(TypeError) as e_abs: 613 inspect.getfile(abs) 614 self.assertIn('expected, got', str(e_abs.exception)) 615 with self.assertRaises(TypeError) as e_append: 616 inspect.getfile(list.append) 617 self.assertIn('expected, got', str(e_append.exception)) 618 619 def test_getfile_class_without_module(self): 620 class CM(type): 621 @property 622 def __module__(cls): 623 raise AttributeError 624 class C(metaclass=CM): 625 pass 626 with self.assertRaises(TypeError): 627 inspect.getfile(C) 628 629 def test_getfile_broken_repr(self): 630 class ErrorRepr: 631 def __repr__(self): 632 raise Exception('xyz') 633 er = ErrorRepr() 634 with self.assertRaises(TypeError): 635 inspect.getfile(er) 636 637 def test_getmodule_recursion(self): 638 from types import ModuleType 639 name = '__inspect_dummy' 640 m = sys.modules[name] = ModuleType(name) 641 m.__file__ = "<string>" # hopefully not a real filename... 642 m.__loader__ = "dummy" # pretend the filename is understood by a loader 643 exec("def x(): pass", m.__dict__) 644 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>') 645 del sys.modules[name] 646 inspect.getmodule(compile('a=10','','single')) 647 648 def test_proceed_with_fake_filename(self): 649 '''doctest monkeypatches linecache to enable inspection''' 650 fn, source = '<test>', 'def x(): pass\n' 651 getlines = linecache.getlines 652 def monkey(filename, module_globals=None): 653 if filename == fn: 654 return source.splitlines(keepends=True) 655 else: 656 return getlines(filename, module_globals) 657 linecache.getlines = monkey 658 try: 659 ns = {} 660 exec(compile(source, fn, 'single'), ns) 661 inspect.getsource(ns["x"]) 662 finally: 663 linecache.getlines = getlines 664 665 def test_getsource_on_code_object(self): 666 self.assertSourceEqual(mod.eggs.__code__, 12, 18) 667 668class TestGetsourceInteractive(unittest.TestCase): 669 def test_getclasses_interactive(self): 670 # bpo-44648: simulate a REPL session; 671 # there is no `__file__` in the __main__ module 672 code = "import sys, inspect; \ 673 assert not hasattr(sys.modules['__main__'], '__file__'); \ 674 A = type('A', (), {}); \ 675 inspect.getsource(A)" 676 _, _, stderr = assert_python_failure("-c", code, __isolated=True) 677 self.assertIn(b'OSError: source code not available', stderr) 678 679class TestGettingSourceOfToplevelFrames(GetSourceBase): 680 fodderModule = mod 681 682 def test_range_toplevel_frame(self): 683 self.maxDiff = None 684 self.assertSourceEqual(mod.currentframe, 1, None) 685 686 def test_range_traceback_toplevel_frame(self): 687 self.assertSourceEqual(mod.tb, 1, None) 688 689class TestDecorators(GetSourceBase): 690 fodderModule = mod2 691 692 def test_wrapped_decorator(self): 693 self.assertSourceEqual(mod2.wrapped, 14, 17) 694 695 def test_replacing_decorator(self): 696 self.assertSourceEqual(mod2.gone, 9, 10) 697 698 def test_getsource_unwrap(self): 699 self.assertSourceEqual(mod2.real, 130, 132) 700 701 def test_decorator_with_lambda(self): 702 self.assertSourceEqual(mod2.func114, 113, 115) 703 704class TestOneliners(GetSourceBase): 705 fodderModule = mod2 706 def test_oneline_lambda(self): 707 # Test inspect.getsource with a one-line lambda function. 708 self.assertSourceEqual(mod2.oll, 25, 25) 709 710 def test_threeline_lambda(self): 711 # Test inspect.getsource with a three-line lambda function, 712 # where the second and third lines are _not_ indented. 713 self.assertSourceEqual(mod2.tll, 28, 30) 714 715 def test_twoline_indented_lambda(self): 716 # Test inspect.getsource with a two-line lambda function, 717 # where the second line _is_ indented. 718 self.assertSourceEqual(mod2.tlli, 33, 34) 719 720 def test_onelinefunc(self): 721 # Test inspect.getsource with a regular one-line function. 722 self.assertSourceEqual(mod2.onelinefunc, 37, 37) 723 724 def test_manyargs(self): 725 # Test inspect.getsource with a regular function where 726 # the arguments are on two lines and _not_ indented and 727 # the body on the second line with the last arguments. 728 self.assertSourceEqual(mod2.manyargs, 40, 41) 729 730 def test_twolinefunc(self): 731 # Test inspect.getsource with a regular function where 732 # the body is on two lines, following the argument list and 733 # continued on the next line by a \\. 734 self.assertSourceEqual(mod2.twolinefunc, 44, 45) 735 736 def test_lambda_in_list(self): 737 # Test inspect.getsource with a one-line lambda function 738 # defined in a list, indented. 739 self.assertSourceEqual(mod2.a[1], 49, 49) 740 741 def test_anonymous(self): 742 # Test inspect.getsource with a lambda function defined 743 # as argument to another function. 744 self.assertSourceEqual(mod2.anonymous, 55, 55) 745 746class TestBlockComments(GetSourceBase): 747 fodderModule = mod 748 749 def test_toplevel_class(self): 750 self.assertSourceEqual(mod.WhichComments, 96, 114) 751 752 def test_class_method(self): 753 self.assertSourceEqual(mod.WhichComments.f, 99, 104) 754 755 def test_class_async_method(self): 756 self.assertSourceEqual(mod.WhichComments.asyncf, 109, 112) 757 758class TestBuggyCases(GetSourceBase): 759 fodderModule = mod2 760 761 def test_with_comment(self): 762 self.assertSourceEqual(mod2.with_comment, 58, 59) 763 764 def test_multiline_sig(self): 765 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64) 766 767 def test_nested_class(self): 768 self.assertSourceEqual(mod2.func69().func71, 71, 72) 769 770 def test_one_liner_followed_by_non_name(self): 771 self.assertSourceEqual(mod2.func77, 77, 77) 772 773 def test_one_liner_dedent_non_name(self): 774 self.assertSourceEqual(mod2.cls82.func83, 83, 83) 775 776 def test_with_comment_instead_of_docstring(self): 777 self.assertSourceEqual(mod2.func88, 88, 90) 778 779 def test_method_in_dynamic_class(self): 780 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97) 781 782 # This should not skip for CPython, but might on a repackaged python where 783 # unicodedata is not an external module, or on pypy. 784 @unittest.skipIf(not hasattr(unicodedata, '__file__') or 785 unicodedata.__file__.endswith('.py'), 786 "unicodedata is not an external binary module") 787 def test_findsource_binary(self): 788 self.assertRaises(OSError, inspect.getsource, unicodedata) 789 self.assertRaises(OSError, inspect.findsource, unicodedata) 790 791 def test_findsource_code_in_linecache(self): 792 lines = ["x=1"] 793 co = compile(lines[0], "_dynamically_created_file", "exec") 794 self.assertRaises(OSError, inspect.findsource, co) 795 self.assertRaises(OSError, inspect.getsource, co) 796 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename) 797 try: 798 self.assertEqual(inspect.findsource(co), (lines,0)) 799 self.assertEqual(inspect.getsource(co), lines[0]) 800 finally: 801 del linecache.cache[co.co_filename] 802 803 def test_findsource_without_filename(self): 804 for fname in ['', '<string>']: 805 co = compile('x=1', fname, "exec") 806 self.assertRaises(IOError, inspect.findsource, co) 807 self.assertRaises(IOError, inspect.getsource, co) 808 809 def test_findsource_with_out_of_bounds_lineno(self): 810 mod_len = len(inspect.getsource(mod)) 811 src = '\n' * 2* mod_len + "def f(): pass" 812 co = compile(src, mod.__file__, "exec") 813 g, l = {}, {} 814 eval(co, g, l) 815 func = l['f'] 816 self.assertEqual(func.__code__.co_firstlineno, 1+2*mod_len) 817 with self.assertRaisesRegex(IOError, "lineno is out of bounds"): 818 inspect.findsource(func) 819 820 def test_getsource_on_method(self): 821 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119) 822 823 def test_nested_func(self): 824 self.assertSourceEqual(mod2.cls135.func136, 136, 139) 825 826 def test_class_definition_in_multiline_string_definition(self): 827 self.assertSourceEqual(mod2.cls149, 149, 152) 828 829 def test_class_definition_in_multiline_comment(self): 830 self.assertSourceEqual(mod2.cls160, 160, 163) 831 832 def test_nested_class_definition_indented_string(self): 833 self.assertSourceEqual(mod2.cls173.cls175, 175, 176) 834 835 def test_nested_class_definition(self): 836 self.assertSourceEqual(mod2.cls183, 183, 188) 837 self.assertSourceEqual(mod2.cls183.cls185, 185, 188) 838 839 def test_class_decorator(self): 840 self.assertSourceEqual(mod2.cls196, 194, 201) 841 self.assertSourceEqual(mod2.cls196.cls200, 198, 201) 842 843 def test_class_inside_conditional(self): 844 self.assertSourceEqual(mod2.cls238, 238, 240) 845 self.assertSourceEqual(mod2.cls238.cls239, 239, 240) 846 847 def test_multiple_children_classes(self): 848 self.assertSourceEqual(mod2.cls203, 203, 209) 849 self.assertSourceEqual(mod2.cls203.cls204, 204, 206) 850 self.assertSourceEqual(mod2.cls203.cls204.cls205, 205, 206) 851 self.assertSourceEqual(mod2.cls203.cls207, 207, 209) 852 self.assertSourceEqual(mod2.cls203.cls207.cls205, 208, 209) 853 854 def test_nested_class_definition_inside_function(self): 855 self.assertSourceEqual(mod2.func212(), 213, 214) 856 self.assertSourceEqual(mod2.cls213, 218, 222) 857 self.assertSourceEqual(mod2.cls213().func219(), 220, 221) 858 859 @unittest.skipIf( 860 support.is_emscripten or support.is_wasi, 861 "socket.accept is broken" 862 ) 863 def test_nested_class_definition_inside_async_function(self): 864 import asyncio 865 self.addCleanup(asyncio.set_event_loop_policy, None) 866 self.assertSourceEqual(asyncio.run(mod2.func225()), 226, 227) 867 self.assertSourceEqual(mod2.cls226, 231, 235) 868 self.assertSourceEqual(asyncio.run(mod2.cls226().func232()), 233, 234) 869 870class TestNoEOL(GetSourceBase): 871 def setUp(self): 872 self.tempdir = TESTFN + '_dir' 873 os.mkdir(self.tempdir) 874 with open(os.path.join(self.tempdir, 'inspect_fodder3%spy' % os.extsep), 875 'w', encoding='utf-8') as f: 876 f.write("class X:\n pass # No EOL") 877 with DirsOnSysPath(self.tempdir): 878 import inspect_fodder3 as mod3 879 self.fodderModule = mod3 880 super().setUp() 881 882 def tearDown(self): 883 shutil.rmtree(self.tempdir) 884 885 def test_class(self): 886 self.assertSourceEqual(self.fodderModule.X, 1, 2) 887 888 889class TestComplexDecorator(GetSourceBase): 890 fodderModule = mod2 891 892 def test_parens_in_decorator(self): 893 self.assertSourceEqual(self.fodderModule.complex_decorated, 273, 275) 894 895class _BrokenDataDescriptor(object): 896 """ 897 A broken data descriptor. See bug #1785. 898 """ 899 def __get__(*args): 900 raise AttributeError("broken data descriptor") 901 902 def __set__(*args): 903 raise RuntimeError 904 905 def __getattr__(*args): 906 raise AttributeError("broken data descriptor") 907 908 909class _BrokenMethodDescriptor(object): 910 """ 911 A broken method descriptor. See bug #1785. 912 """ 913 def __get__(*args): 914 raise AttributeError("broken method descriptor") 915 916 def __getattr__(*args): 917 raise AttributeError("broken method descriptor") 918 919 920# Helper for testing classify_class_attrs. 921def attrs_wo_objs(cls): 922 return [t[:3] for t in inspect.classify_class_attrs(cls)] 923 924 925class TestClassesAndFunctions(unittest.TestCase): 926 def test_newstyle_mro(self): 927 # The same w/ new-class MRO. 928 class A(object): pass 929 class B(A): pass 930 class C(A): pass 931 class D(B, C): pass 932 933 expected = (D, B, C, A, object) 934 got = inspect.getmro(D) 935 self.assertEqual(expected, got) 936 937 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None, 938 varkw_e=None, defaults_e=None, 939 posonlyargs_e=[], kwonlyargs_e=[], 940 kwonlydefaults_e=None, 941 ann_e={}): 942 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \ 943 inspect.getfullargspec(routine) 944 self.assertEqual(args, args_e) 945 self.assertEqual(varargs, varargs_e) 946 self.assertEqual(varkw, varkw_e) 947 self.assertEqual(defaults, defaults_e) 948 self.assertEqual(kwonlyargs, kwonlyargs_e) 949 self.assertEqual(kwonlydefaults, kwonlydefaults_e) 950 self.assertEqual(ann, ann_e) 951 952 def test_getfullargspec(self): 953 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1', 954 kwonlyargs_e=['arg2'], 955 kwonlydefaults_e={'arg2':1}) 956 957 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'], 958 ann_e={'arg1' : list}) 959 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [], 960 kwonlyargs_e=['arg']) 961 962 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'], 963 kwonlyargs_e=['e', 'f']) 964 965 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs, 966 ['a', 'b', 'c', 'd'], 967 varargs_e='args', 968 varkw_e='kwargs', 969 kwonlyargs_e=['e', 'f']) 970 971 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'], 972 defaults_e=(1,2,3), 973 kwonlyargs_e=['e', 'f'], 974 kwonlydefaults_e={'e': 4, 'f': 5}) 975 976 def test_argspec_api_ignores_wrapped(self): 977 # Issue 20684: low level introspection API must ignore __wrapped__ 978 @functools.wraps(mod.spam) 979 def ham(x, y): 980 pass 981 # Basic check 982 self.assertFullArgSpecEquals(ham, ['x', 'y']) 983 self.assertFullArgSpecEquals(functools.partial(ham), 984 ['x', 'y']) 985 986 def test_getfullargspec_signature_attr(self): 987 def test(): 988 pass 989 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY) 990 test.__signature__ = inspect.Signature(parameters=(spam_param,)) 991 992 self.assertFullArgSpecEquals(test, ['spam']) 993 994 def test_getfullargspec_signature_annos(self): 995 def test(a:'spam') -> 'ham': pass 996 spec = inspect.getfullargspec(test) 997 self.assertEqual(test.__annotations__, spec.annotations) 998 999 def test(): pass 1000 spec = inspect.getfullargspec(test) 1001 self.assertEqual(test.__annotations__, spec.annotations) 1002 1003 @unittest.skipIf(MISSING_C_DOCSTRINGS, 1004 "Signature information for builtins requires docstrings") 1005 def test_getfullargspec_builtin_methods(self): 1006 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj']) 1007 1008 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj']) 1009 1010 self.assertFullArgSpecEquals( 1011 os.stat, 1012 args_e=['path'], 1013 kwonlyargs_e=['dir_fd', 'follow_symlinks'], 1014 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True}) 1015 1016 @cpython_only 1017 @unittest.skipIf(MISSING_C_DOCSTRINGS, 1018 "Signature information for builtins requires docstrings") 1019 def test_getfullargspec_builtin_func(self): 1020 import _testcapi 1021 builtin = _testcapi.docstring_with_signature_with_defaults 1022 spec = inspect.getfullargspec(builtin) 1023 self.assertEqual(spec.defaults[0], 'avocado') 1024 1025 @cpython_only 1026 @unittest.skipIf(MISSING_C_DOCSTRINGS, 1027 "Signature information for builtins requires docstrings") 1028 def test_getfullargspec_builtin_func_no_signature(self): 1029 import _testcapi 1030 builtin = _testcapi.docstring_no_signature 1031 with self.assertRaises(TypeError): 1032 inspect.getfullargspec(builtin) 1033 1034 def test_getfullargspec_definition_order_preserved_on_kwonly(self): 1035 for fn in signatures_with_lexicographic_keyword_only_parameters(): 1036 signature = inspect.getfullargspec(fn) 1037 l = list(signature.kwonlyargs) 1038 sorted_l = sorted(l) 1039 self.assertTrue(l) 1040 self.assertEqual(l, sorted_l) 1041 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn) 1042 l = list(signature.kwonlyargs) 1043 self.assertEqual(l, unsorted_keyword_only_parameters) 1044 1045 def test_classify_newstyle(self): 1046 class A(object): 1047 1048 def s(): pass 1049 s = staticmethod(s) 1050 1051 def c(cls): pass 1052 c = classmethod(c) 1053 1054 def getp(self): pass 1055 p = property(getp) 1056 1057 def m(self): pass 1058 1059 def m1(self): pass 1060 1061 datablob = '1' 1062 1063 dd = _BrokenDataDescriptor() 1064 md = _BrokenMethodDescriptor() 1065 1066 attrs = attrs_wo_objs(A) 1067 1068 self.assertIn(('__new__', 'static method', object), attrs, 1069 'missing __new__') 1070 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__') 1071 1072 self.assertIn(('s', 'static method', A), attrs, 'missing static method') 1073 self.assertIn(('c', 'class method', A), attrs, 'missing class method') 1074 self.assertIn(('p', 'property', A), attrs, 'missing property') 1075 self.assertIn(('m', 'method', A), attrs, 1076 'missing plain method: %r' % attrs) 1077 self.assertIn(('m1', 'method', A), attrs, 'missing plain method') 1078 self.assertIn(('datablob', 'data', A), attrs, 'missing data') 1079 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor') 1080 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor') 1081 1082 class B(A): 1083 1084 def m(self): pass 1085 1086 attrs = attrs_wo_objs(B) 1087 self.assertIn(('s', 'static method', A), attrs, 'missing static method') 1088 self.assertIn(('c', 'class method', A), attrs, 'missing class method') 1089 self.assertIn(('p', 'property', A), attrs, 'missing property') 1090 self.assertIn(('m', 'method', B), attrs, 'missing plain method') 1091 self.assertIn(('m1', 'method', A), attrs, 'missing plain method') 1092 self.assertIn(('datablob', 'data', A), attrs, 'missing data') 1093 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor') 1094 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor') 1095 1096 1097 class C(A): 1098 1099 def m(self): pass 1100 def c(self): pass 1101 1102 attrs = attrs_wo_objs(C) 1103 self.assertIn(('s', 'static method', A), attrs, 'missing static method') 1104 self.assertIn(('c', 'method', C), attrs, 'missing plain method') 1105 self.assertIn(('p', 'property', A), attrs, 'missing property') 1106 self.assertIn(('m', 'method', C), attrs, 'missing plain method') 1107 self.assertIn(('m1', 'method', A), attrs, 'missing plain method') 1108 self.assertIn(('datablob', 'data', A), attrs, 'missing data') 1109 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor') 1110 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor') 1111 1112 class D(B, C): 1113 1114 def m1(self): pass 1115 1116 attrs = attrs_wo_objs(D) 1117 self.assertIn(('s', 'static method', A), attrs, 'missing static method') 1118 self.assertIn(('c', 'method', C), attrs, 'missing plain method') 1119 self.assertIn(('p', 'property', A), attrs, 'missing property') 1120 self.assertIn(('m', 'method', B), attrs, 'missing plain method') 1121 self.assertIn(('m1', 'method', D), attrs, 'missing plain method') 1122 self.assertIn(('datablob', 'data', A), attrs, 'missing data') 1123 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor') 1124 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor') 1125 1126 def test_classify_builtin_types(self): 1127 # Simple sanity check that all built-in types can have their 1128 # attributes classified. 1129 for name in dir(__builtins__): 1130 builtin = getattr(__builtins__, name) 1131 if isinstance(builtin, type): 1132 inspect.classify_class_attrs(builtin) 1133 1134 attrs = attrs_wo_objs(bool) 1135 self.assertIn(('__new__', 'static method', bool), attrs, 1136 'missing __new__') 1137 self.assertIn(('from_bytes', 'class method', int), attrs, 1138 'missing class method') 1139 self.assertIn(('to_bytes', 'method', int), attrs, 1140 'missing plain method') 1141 self.assertIn(('__add__', 'method', int), attrs, 1142 'missing plain method') 1143 self.assertIn(('__and__', 'method', bool), attrs, 1144 'missing plain method') 1145 1146 def test_classify_DynamicClassAttribute(self): 1147 class Meta(type): 1148 def __getattr__(self, name): 1149 if name == 'ham': 1150 return 'spam' 1151 return super().__getattr__(name) 1152 class VA(metaclass=Meta): 1153 @types.DynamicClassAttribute 1154 def ham(self): 1155 return 'eggs' 1156 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham']) 1157 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA)) 1158 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam') 1159 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA)) 1160 1161 def test_classify_overrides_bool(self): 1162 class NoBool(object): 1163 def __eq__(self, other): 1164 return NoBool() 1165 1166 def __bool__(self): 1167 raise NotImplementedError( 1168 "This object does not specify a boolean value") 1169 1170 class HasNB(object): 1171 dd = NoBool() 1172 1173 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd) 1174 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB)) 1175 1176 def test_classify_metaclass_class_attribute(self): 1177 class Meta(type): 1178 fish = 'slap' 1179 def __dir__(self): 1180 return ['__class__', '__module__', '__name__', 'fish'] 1181 class Class(metaclass=Meta): 1182 pass 1183 should_find = inspect.Attribute('fish', 'data', Meta, 'slap') 1184 self.assertIn(should_find, inspect.classify_class_attrs(Class)) 1185 1186 def test_classify_VirtualAttribute(self): 1187 class Meta(type): 1188 def __dir__(cls): 1189 return ['__class__', '__module__', '__name__', 'BOOM'] 1190 def __getattr__(self, name): 1191 if name =='BOOM': 1192 return 42 1193 return super().__getattr(name) 1194 class Class(metaclass=Meta): 1195 pass 1196 should_find = inspect.Attribute('BOOM', 'data', Meta, 42) 1197 self.assertIn(should_find, inspect.classify_class_attrs(Class)) 1198 1199 def test_classify_VirtualAttribute_multi_classes(self): 1200 class Meta1(type): 1201 def __dir__(cls): 1202 return ['__class__', '__module__', '__name__', 'one'] 1203 def __getattr__(self, name): 1204 if name =='one': 1205 return 1 1206 return super().__getattr__(name) 1207 class Meta2(type): 1208 def __dir__(cls): 1209 return ['__class__', '__module__', '__name__', 'two'] 1210 def __getattr__(self, name): 1211 if name =='two': 1212 return 2 1213 return super().__getattr__(name) 1214 class Meta3(Meta1, Meta2): 1215 def __dir__(cls): 1216 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] + 1217 Meta1.__dir__(cls) + Meta2.__dir__(cls)))) 1218 def __getattr__(self, name): 1219 if name =='three': 1220 return 3 1221 return super().__getattr__(name) 1222 class Class1(metaclass=Meta1): 1223 pass 1224 class Class2(Class1, metaclass=Meta3): 1225 pass 1226 1227 should_find1 = inspect.Attribute('one', 'data', Meta1, 1) 1228 should_find2 = inspect.Attribute('two', 'data', Meta2, 2) 1229 should_find3 = inspect.Attribute('three', 'data', Meta3, 3) 1230 cca = inspect.classify_class_attrs(Class2) 1231 for sf in (should_find1, should_find2, should_find3): 1232 self.assertIn(sf, cca) 1233 1234 def test_classify_class_attrs_with_buggy_dir(self): 1235 class M(type): 1236 def __dir__(cls): 1237 return ['__class__', '__name__', 'missing'] 1238 class C(metaclass=M): 1239 pass 1240 attrs = [a[0] for a in inspect.classify_class_attrs(C)] 1241 self.assertNotIn('missing', attrs) 1242 1243 def test_getmembers_descriptors(self): 1244 class A(object): 1245 dd = _BrokenDataDescriptor() 1246 md = _BrokenMethodDescriptor() 1247 1248 def pred_wrapper(pred): 1249 # A quick'n'dirty way to discard standard attributes of new-style 1250 # classes. 1251 class Empty(object): 1252 pass 1253 def wrapped(x): 1254 if '__name__' in dir(x) and hasattr(Empty, x.__name__): 1255 return False 1256 return pred(x) 1257 return wrapped 1258 1259 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor) 1260 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor) 1261 1262 self.assertEqual(inspect.getmembers(A, ismethoddescriptor), 1263 [('md', A.__dict__['md'])]) 1264 self.assertEqual(inspect.getmembers(A, isdatadescriptor), 1265 [('dd', A.__dict__['dd'])]) 1266 1267 class B(A): 1268 pass 1269 1270 self.assertEqual(inspect.getmembers(B, ismethoddescriptor), 1271 [('md', A.__dict__['md'])]) 1272 self.assertEqual(inspect.getmembers(B, isdatadescriptor), 1273 [('dd', A.__dict__['dd'])]) 1274 1275 def test_getmembers_method(self): 1276 class B: 1277 def f(self): 1278 pass 1279 1280 self.assertIn(('f', B.f), inspect.getmembers(B)) 1281 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod)) 1282 b = B() 1283 self.assertIn(('f', b.f), inspect.getmembers(b)) 1284 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod)) 1285 1286 def test_getmembers_VirtualAttribute(self): 1287 class M(type): 1288 def __getattr__(cls, name): 1289 if name == 'eggs': 1290 return 'scrambled' 1291 return super().__getattr__(name) 1292 class A(metaclass=M): 1293 @types.DynamicClassAttribute 1294 def eggs(self): 1295 return 'spam' 1296 class B: 1297 def __getattr__(self, attribute): 1298 return None 1299 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A)) 1300 self.assertIn(('eggs', 'spam'), inspect.getmembers(A())) 1301 b = B() 1302 self.assertIn(('__getattr__', b.__getattr__), inspect.getmembers(b)) 1303 1304 def test_getmembers_static(self): 1305 class A: 1306 @property 1307 def name(self): 1308 raise NotImplementedError 1309 @types.DynamicClassAttribute 1310 def eggs(self): 1311 raise NotImplementedError 1312 1313 a = A() 1314 instance_members = inspect.getmembers_static(a) 1315 class_members = inspect.getmembers_static(A) 1316 self.assertIn(('name', inspect.getattr_static(a, 'name')), instance_members) 1317 self.assertIn(('eggs', inspect.getattr_static(a, 'eggs')), instance_members) 1318 self.assertIn(('name', inspect.getattr_static(A, 'name')), class_members) 1319 self.assertIn(('eggs', inspect.getattr_static(A, 'eggs')), class_members) 1320 1321 def test_getmembers_with_buggy_dir(self): 1322 class M(type): 1323 def __dir__(cls): 1324 return ['__class__', '__name__', 'missing'] 1325 class C(metaclass=M): 1326 pass 1327 attrs = [a[0] for a in inspect.getmembers(C)] 1328 self.assertNotIn('missing', attrs) 1329 1330 def test_get_annotations_with_stock_annotations(self): 1331 def foo(a:int, b:str): pass 1332 self.assertEqual(inspect.get_annotations(foo), {'a': int, 'b': str}) 1333 1334 foo.__annotations__ = {'a': 'foo', 'b':'str'} 1335 self.assertEqual(inspect.get_annotations(foo), {'a': 'foo', 'b': 'str'}) 1336 1337 self.assertEqual(inspect.get_annotations(foo, eval_str=True, locals=locals()), {'a': foo, 'b': str}) 1338 self.assertEqual(inspect.get_annotations(foo, eval_str=True, globals=locals()), {'a': foo, 'b': str}) 1339 1340 isa = inspect_stock_annotations 1341 self.assertEqual(inspect.get_annotations(isa), {'a': int, 'b': str}) 1342 self.assertEqual(inspect.get_annotations(isa.MyClass), {'a': int, 'b': str}) 1343 self.assertEqual(inspect.get_annotations(isa.function), {'a': int, 'b': str, 'return': isa.MyClass}) 1344 self.assertEqual(inspect.get_annotations(isa.function2), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass}) 1345 self.assertEqual(inspect.get_annotations(isa.function3), {'a': 'int', 'b': 'str', 'c': 'MyClass'}) 1346 self.assertEqual(inspect.get_annotations(inspect), {}) # inspect module has no annotations 1347 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass), {}) 1348 self.assertEqual(inspect.get_annotations(isa.unannotated_function), {}) 1349 1350 self.assertEqual(inspect.get_annotations(isa, eval_str=True), {'a': int, 'b': str}) 1351 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=True), {'a': int, 'b': str}) 1352 self.assertEqual(inspect.get_annotations(isa.function, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass}) 1353 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=True), {'a': int, 'b': str, 'c': isa.MyClass, 'return': isa.MyClass}) 1354 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=True), {'a': int, 'b': str, 'c': isa.MyClass}) 1355 self.assertEqual(inspect.get_annotations(inspect, eval_str=True), {}) 1356 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=True), {}) 1357 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=True), {}) 1358 1359 self.assertEqual(inspect.get_annotations(isa, eval_str=False), {'a': int, 'b': str}) 1360 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=False), {'a': int, 'b': str}) 1361 self.assertEqual(inspect.get_annotations(isa.function, eval_str=False), {'a': int, 'b': str, 'return': isa.MyClass}) 1362 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=False), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass}) 1363 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=False), {'a': 'int', 'b': 'str', 'c': 'MyClass'}) 1364 self.assertEqual(inspect.get_annotations(inspect, eval_str=False), {}) 1365 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=False), {}) 1366 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=False), {}) 1367 1368 def times_three(fn): 1369 @functools.wraps(fn) 1370 def wrapper(a, b): 1371 return fn(a*3, b*3) 1372 return wrapper 1373 1374 wrapped = times_three(isa.function) 1375 self.assertEqual(wrapped(1, 'x'), isa.MyClass(3, 'xxx')) 1376 self.assertIsNot(wrapped.__globals__, isa.function.__globals__) 1377 self.assertEqual(inspect.get_annotations(wrapped), {'a': int, 'b': str, 'return': isa.MyClass}) 1378 self.assertEqual(inspect.get_annotations(wrapped, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass}) 1379 self.assertEqual(inspect.get_annotations(wrapped, eval_str=False), {'a': int, 'b': str, 'return': isa.MyClass}) 1380 1381 def test_get_annotations_with_stringized_annotations(self): 1382 isa = inspect_stringized_annotations 1383 self.assertEqual(inspect.get_annotations(isa), {'a': 'int', 'b': 'str'}) 1384 self.assertEqual(inspect.get_annotations(isa.MyClass), {'a': 'int', 'b': 'str'}) 1385 self.assertEqual(inspect.get_annotations(isa.function), {'a': 'int', 'b': 'str', 'return': 'MyClass'}) 1386 self.assertEqual(inspect.get_annotations(isa.function2), {'a': 'int', 'b': "'str'", 'c': 'MyClass', 'return': 'MyClass'}) 1387 self.assertEqual(inspect.get_annotations(isa.function3), {'a': "'int'", 'b': "'str'", 'c': "'MyClass'"}) 1388 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass), {}) 1389 self.assertEqual(inspect.get_annotations(isa.unannotated_function), {}) 1390 1391 self.assertEqual(inspect.get_annotations(isa, eval_str=True), {'a': int, 'b': str}) 1392 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=True), {'a': int, 'b': str}) 1393 self.assertEqual(inspect.get_annotations(isa.function, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass}) 1394 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=True), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass}) 1395 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=True), {'a': 'int', 'b': 'str', 'c': 'MyClass'}) 1396 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=True), {}) 1397 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=True), {}) 1398 1399 self.assertEqual(inspect.get_annotations(isa, eval_str=False), {'a': 'int', 'b': 'str'}) 1400 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=False), {'a': 'int', 'b': 'str'}) 1401 self.assertEqual(inspect.get_annotations(isa.function, eval_str=False), {'a': 'int', 'b': 'str', 'return': 'MyClass'}) 1402 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=False), {'a': 'int', 'b': "'str'", 'c': 'MyClass', 'return': 'MyClass'}) 1403 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=False), {'a': "'int'", 'b': "'str'", 'c': "'MyClass'"}) 1404 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=False), {}) 1405 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=False), {}) 1406 1407 isa2 = inspect_stringized_annotations_2 1408 self.assertEqual(inspect.get_annotations(isa2), {}) 1409 self.assertEqual(inspect.get_annotations(isa2, eval_str=True), {}) 1410 self.assertEqual(inspect.get_annotations(isa2, eval_str=False), {}) 1411 1412 def times_three(fn): 1413 @functools.wraps(fn) 1414 def wrapper(a, b): 1415 return fn(a*3, b*3) 1416 return wrapper 1417 1418 wrapped = times_three(isa.function) 1419 self.assertEqual(wrapped(1, 'x'), isa.MyClass(3, 'xxx')) 1420 self.assertIsNot(wrapped.__globals__, isa.function.__globals__) 1421 self.assertEqual(inspect.get_annotations(wrapped), {'a': 'int', 'b': 'str', 'return': 'MyClass'}) 1422 self.assertEqual(inspect.get_annotations(wrapped, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass}) 1423 self.assertEqual(inspect.get_annotations(wrapped, eval_str=False), {'a': 'int', 'b': 'str', 'return': 'MyClass'}) 1424 1425 # test that local namespace lookups work 1426 self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations), {'x': 'mytype'}) 1427 self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations, eval_str=True), {'x': int}) 1428 1429 1430class TestFormatAnnotation(unittest.TestCase): 1431 def test_typing_replacement(self): 1432 from test.typinganndata.ann_module9 import ann, ann1 1433 self.assertEqual(inspect.formatannotation(ann), 'Union[List[str], int]') 1434 self.assertEqual(inspect.formatannotation(ann1), 'Union[List[testModule.typing.A], int]') 1435 1436 1437class TestIsDataDescriptor(unittest.TestCase): 1438 1439 def test_custom_descriptors(self): 1440 class NonDataDescriptor: 1441 def __get__(self, value, type=None): pass 1442 class DataDescriptor0: 1443 def __set__(self, name, value): pass 1444 class DataDescriptor1: 1445 def __delete__(self, name): pass 1446 class DataDescriptor2: 1447 __set__ = None 1448 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()), 1449 'class with only __get__ not a data descriptor') 1450 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()), 1451 'class with __set__ is a data descriptor') 1452 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()), 1453 'class with __delete__ is a data descriptor') 1454 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()), 1455 'class with __set__ = None is a data descriptor') 1456 1457 def test_slot(self): 1458 class Slotted: 1459 __slots__ = 'foo', 1460 self.assertTrue(inspect.isdatadescriptor(Slotted.foo), 1461 'a slot is a data descriptor') 1462 1463 def test_property(self): 1464 class Propertied: 1465 @property 1466 def a_property(self): 1467 pass 1468 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property), 1469 'a property is a data descriptor') 1470 1471 def test_functions(self): 1472 class Test(object): 1473 def instance_method(self): pass 1474 @classmethod 1475 def class_method(cls): pass 1476 @staticmethod 1477 def static_method(): pass 1478 def function(): 1479 pass 1480 a_lambda = lambda: None 1481 self.assertFalse(inspect.isdatadescriptor(Test().instance_method), 1482 'a instance method is not a data descriptor') 1483 self.assertFalse(inspect.isdatadescriptor(Test().class_method), 1484 'a class method is not a data descriptor') 1485 self.assertFalse(inspect.isdatadescriptor(Test().static_method), 1486 'a static method is not a data descriptor') 1487 self.assertFalse(inspect.isdatadescriptor(function), 1488 'a function is not a data descriptor') 1489 self.assertFalse(inspect.isdatadescriptor(a_lambda), 1490 'a lambda is not a data descriptor') 1491 1492 1493_global_ref = object() 1494class TestGetClosureVars(unittest.TestCase): 1495 1496 def test_name_resolution(self): 1497 # Basic test of the 4 different resolution mechanisms 1498 def f(nonlocal_ref): 1499 def g(local_ref): 1500 print(local_ref, nonlocal_ref, _global_ref, unbound_ref) 1501 return g 1502 _arg = object() 1503 nonlocal_vars = {"nonlocal_ref": _arg} 1504 global_vars = {"_global_ref": _global_ref} 1505 builtin_vars = {"print": print} 1506 unbound_names = {"unbound_ref"} 1507 expected = inspect.ClosureVars(nonlocal_vars, global_vars, 1508 builtin_vars, unbound_names) 1509 self.assertEqual(inspect.getclosurevars(f(_arg)), expected) 1510 1511 def test_generator_closure(self): 1512 def f(nonlocal_ref): 1513 def g(local_ref): 1514 print(local_ref, nonlocal_ref, _global_ref, unbound_ref) 1515 yield 1516 return g 1517 _arg = object() 1518 nonlocal_vars = {"nonlocal_ref": _arg} 1519 global_vars = {"_global_ref": _global_ref} 1520 builtin_vars = {"print": print} 1521 unbound_names = {"unbound_ref"} 1522 expected = inspect.ClosureVars(nonlocal_vars, global_vars, 1523 builtin_vars, unbound_names) 1524 self.assertEqual(inspect.getclosurevars(f(_arg)), expected) 1525 1526 def test_method_closure(self): 1527 class C: 1528 def f(self, nonlocal_ref): 1529 def g(local_ref): 1530 print(local_ref, nonlocal_ref, _global_ref, unbound_ref) 1531 return g 1532 _arg = object() 1533 nonlocal_vars = {"nonlocal_ref": _arg} 1534 global_vars = {"_global_ref": _global_ref} 1535 builtin_vars = {"print": print} 1536 unbound_names = {"unbound_ref"} 1537 expected = inspect.ClosureVars(nonlocal_vars, global_vars, 1538 builtin_vars, unbound_names) 1539 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected) 1540 1541 def test_nonlocal_vars(self): 1542 # More complex tests of nonlocal resolution 1543 def _nonlocal_vars(f): 1544 return inspect.getclosurevars(f).nonlocals 1545 1546 def make_adder(x): 1547 def add(y): 1548 return x + y 1549 return add 1550 1551 def curry(func, arg1): 1552 return lambda arg2: func(arg1, arg2) 1553 1554 def less_than(a, b): 1555 return a < b 1556 1557 # The infamous Y combinator. 1558 def Y(le): 1559 def g(f): 1560 return le(lambda x: f(f)(x)) 1561 Y.g_ref = g 1562 return g(g) 1563 1564 def check_y_combinator(func): 1565 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref}) 1566 1567 inc = make_adder(1) 1568 add_two = make_adder(2) 1569 greater_than_five = curry(less_than, 5) 1570 1571 self.assertEqual(_nonlocal_vars(inc), {'x': 1}) 1572 self.assertEqual(_nonlocal_vars(add_two), {'x': 2}) 1573 self.assertEqual(_nonlocal_vars(greater_than_five), 1574 {'arg1': 5, 'func': less_than}) 1575 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)), 1576 {'x': 3}) 1577 Y(check_y_combinator) 1578 1579 def test_getclosurevars_empty(self): 1580 def foo(): pass 1581 _empty = inspect.ClosureVars({}, {}, {}, set()) 1582 self.assertEqual(inspect.getclosurevars(lambda: True), _empty) 1583 self.assertEqual(inspect.getclosurevars(foo), _empty) 1584 1585 def test_getclosurevars_error(self): 1586 class T: pass 1587 self.assertRaises(TypeError, inspect.getclosurevars, 1) 1588 self.assertRaises(TypeError, inspect.getclosurevars, list) 1589 self.assertRaises(TypeError, inspect.getclosurevars, {}) 1590 1591 def _private_globals(self): 1592 code = """def f(): print(path)""" 1593 ns = {} 1594 exec(code, ns) 1595 return ns["f"], ns 1596 1597 def test_builtins_fallback(self): 1598 f, ns = self._private_globals() 1599 ns.pop("__builtins__", None) 1600 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"}) 1601 self.assertEqual(inspect.getclosurevars(f), expected) 1602 1603 def test_builtins_as_dict(self): 1604 f, ns = self._private_globals() 1605 ns["__builtins__"] = {"path":1} 1606 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"}) 1607 self.assertEqual(inspect.getclosurevars(f), expected) 1608 1609 def test_builtins_as_module(self): 1610 f, ns = self._private_globals() 1611 ns["__builtins__"] = os 1612 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"}) 1613 self.assertEqual(inspect.getclosurevars(f), expected) 1614 1615 1616class TestGetcallargsFunctions(unittest.TestCase): 1617 1618 def assertEqualCallArgs(self, func, call_params_string, locs=None): 1619 locs = dict(locs or {}, func=func) 1620 r1 = eval('func(%s)' % call_params_string, None, locs) 1621 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None, 1622 locs) 1623 self.assertEqual(r1, r2) 1624 1625 def assertEqualException(self, func, call_param_string, locs=None): 1626 locs = dict(locs or {}, func=func) 1627 try: 1628 eval('func(%s)' % call_param_string, None, locs) 1629 except Exception as e: 1630 ex1 = e 1631 else: 1632 self.fail('Exception not raised') 1633 try: 1634 eval('inspect.getcallargs(func, %s)' % call_param_string, None, 1635 locs) 1636 except Exception as e: 1637 ex2 = e 1638 else: 1639 self.fail('Exception not raised') 1640 self.assertIs(type(ex1), type(ex2)) 1641 self.assertEqual(str(ex1), str(ex2)) 1642 del ex1, ex2 1643 1644 def makeCallable(self, signature): 1645 """Create a function that returns its locals()""" 1646 code = "lambda %s: locals()" 1647 return eval(code % signature) 1648 1649 def test_plain(self): 1650 f = self.makeCallable('a, b=1') 1651 self.assertEqualCallArgs(f, '2') 1652 self.assertEqualCallArgs(f, '2, 3') 1653 self.assertEqualCallArgs(f, 'a=2') 1654 self.assertEqualCallArgs(f, 'b=3, a=2') 1655 self.assertEqualCallArgs(f, '2, b=3') 1656 # expand *iterable / **mapping 1657 self.assertEqualCallArgs(f, '*(2,)') 1658 self.assertEqualCallArgs(f, '*[2]') 1659 self.assertEqualCallArgs(f, '*(2, 3)') 1660 self.assertEqualCallArgs(f, '*[2, 3]') 1661 self.assertEqualCallArgs(f, '**{"a":2}') 1662 self.assertEqualCallArgs(f, 'b=3, **{"a":2}') 1663 self.assertEqualCallArgs(f, '2, **{"b":3}') 1664 self.assertEqualCallArgs(f, '**{"b":3, "a":2}') 1665 # expand UserList / UserDict 1666 self.assertEqualCallArgs(f, '*collections.UserList([2])') 1667 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])') 1668 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)') 1669 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)') 1670 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)') 1671 1672 def test_varargs(self): 1673 f = self.makeCallable('a, b=1, *c') 1674 self.assertEqualCallArgs(f, '2') 1675 self.assertEqualCallArgs(f, '2, 3') 1676 self.assertEqualCallArgs(f, '2, 3, 4') 1677 self.assertEqualCallArgs(f, '*(2,3,4)') 1678 self.assertEqualCallArgs(f, '2, *[3,4]') 1679 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])') 1680 1681 def test_varkw(self): 1682 f = self.makeCallable('a, b=1, **c') 1683 self.assertEqualCallArgs(f, 'a=2') 1684 self.assertEqualCallArgs(f, '2, b=3, c=4') 1685 self.assertEqualCallArgs(f, 'b=3, a=2, c=4') 1686 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}') 1687 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}') 1688 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}') 1689 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)') 1690 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)') 1691 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)') 1692 1693 def test_varkw_only(self): 1694 # issue11256: 1695 f = self.makeCallable('**c') 1696 self.assertEqualCallArgs(f, '') 1697 self.assertEqualCallArgs(f, 'a=1') 1698 self.assertEqualCallArgs(f, 'a=1, b=2') 1699 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}') 1700 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)') 1701 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)') 1702 1703 def test_keyword_only(self): 1704 f = self.makeCallable('a=3, *, c, d=2') 1705 self.assertEqualCallArgs(f, 'c=3') 1706 self.assertEqualCallArgs(f, 'c=3, a=3') 1707 self.assertEqualCallArgs(f, 'a=2, c=4') 1708 self.assertEqualCallArgs(f, '4, c=4') 1709 self.assertEqualException(f, '') 1710 self.assertEqualException(f, '3') 1711 self.assertEqualException(f, 'a=3') 1712 self.assertEqualException(f, 'd=4') 1713 1714 f = self.makeCallable('*, c, d=2') 1715 self.assertEqualCallArgs(f, 'c=3') 1716 self.assertEqualCallArgs(f, 'c=3, d=4') 1717 self.assertEqualCallArgs(f, 'd=4, c=3') 1718 1719 def test_multiple_features(self): 1720 f = self.makeCallable('a, b=2, *f, **g') 1721 self.assertEqualCallArgs(f, '2, 3, 7') 1722 self.assertEqualCallArgs(f, '2, 3, x=8') 1723 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]') 1724 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9') 1725 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9') 1726 self.assertEqualCallArgs(f, 'x=8, *collections.UserList(' 1727 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}') 1728 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, ' 1729 '(4,[5,6])]), **collections.UserDict(' 1730 'y=9, z=10)') 1731 1732 f = self.makeCallable('a, b=2, *f, x, y=99, **g') 1733 self.assertEqualCallArgs(f, '2, 3, x=8') 1734 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]') 1735 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10') 1736 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10') 1737 self.assertEqualCallArgs(f, 'x=8, *collections.UserList(' 1738 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}') 1739 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, ' 1740 '(4,[5,6])]), q=0, **collections.UserDict(' 1741 'y=9, z=10)') 1742 1743 def test_errors(self): 1744 f0 = self.makeCallable('') 1745 f1 = self.makeCallable('a, b') 1746 f2 = self.makeCallable('a, b=1') 1747 # f0 takes no arguments 1748 self.assertEqualException(f0, '1') 1749 self.assertEqualException(f0, 'x=1') 1750 self.assertEqualException(f0, '1,x=1') 1751 # f1 takes exactly 2 arguments 1752 self.assertEqualException(f1, '') 1753 self.assertEqualException(f1, '1') 1754 self.assertEqualException(f1, 'a=2') 1755 self.assertEqualException(f1, 'b=3') 1756 # f2 takes at least 1 argument 1757 self.assertEqualException(f2, '') 1758 self.assertEqualException(f2, 'b=3') 1759 for f in f1, f2: 1760 # f1/f2 takes exactly/at most 2 arguments 1761 self.assertEqualException(f, '2, 3, 4') 1762 self.assertEqualException(f, '1, 2, 3, a=1') 1763 self.assertEqualException(f, '2, 3, 4, c=5') 1764 self.assertEqualException(f, '2, 3, 4, a=1, c=5') 1765 # f got an unexpected keyword argument 1766 self.assertEqualException(f, 'c=2') 1767 self.assertEqualException(f, '2, c=3') 1768 self.assertEqualException(f, '2, 3, c=4') 1769 self.assertEqualException(f, '2, c=4, b=3') 1770 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}') 1771 # f got multiple values for keyword argument 1772 self.assertEqualException(f, '1, a=2') 1773 self.assertEqualException(f, '1, **{"a":2}') 1774 self.assertEqualException(f, '1, 2, b=3') 1775 self.assertEqualException(f, '1, c=3, a=2') 1776 # issue11256: 1777 f3 = self.makeCallable('**c') 1778 self.assertEqualException(f3, '1, 2') 1779 self.assertEqualException(f3, '1, 2, a=1, b=2') 1780 f4 = self.makeCallable('*, a, b=0') 1781 self.assertEqualException(f4, '1, 2') 1782 self.assertEqualException(f4, '1, 2, a=1, b=2') 1783 self.assertEqualException(f4, 'a=1, a=3') 1784 self.assertEqualException(f4, 'a=1, c=3') 1785 self.assertEqualException(f4, 'a=1, a=3, b=4') 1786 self.assertEqualException(f4, 'a=1, b=2, a=3, b=4') 1787 self.assertEqualException(f4, 'a=1, a=2, a=3, b=4') 1788 1789 # issue #20816: getcallargs() fails to iterate over non-existent 1790 # kwonlydefaults and raises a wrong TypeError 1791 def f5(*, a): pass 1792 with self.assertRaisesRegex(TypeError, 1793 'missing 1 required keyword-only'): 1794 inspect.getcallargs(f5) 1795 1796 1797 # issue20817: 1798 def f6(a, b, c): 1799 pass 1800 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"): 1801 inspect.getcallargs(f6) 1802 1803 # bpo-33197 1804 with self.assertRaisesRegex(ValueError, 1805 'variadic keyword parameters cannot' 1806 ' have default values'): 1807 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD, 1808 default=42) 1809 with self.assertRaisesRegex(ValueError, 1810 "value 5 is not a valid Parameter.kind"): 1811 inspect.Parameter("bar", kind=5, default=42) 1812 1813 with self.assertRaisesRegex(TypeError, 1814 'name must be a str, not a int'): 1815 inspect.Parameter(123, kind=4) 1816 1817class TestGetcallargsMethods(TestGetcallargsFunctions): 1818 1819 def setUp(self): 1820 class Foo(object): 1821 pass 1822 self.cls = Foo 1823 self.inst = Foo() 1824 1825 def makeCallable(self, signature): 1826 assert 'self' not in signature 1827 mk = super(TestGetcallargsMethods, self).makeCallable 1828 self.cls.method = mk('self, ' + signature) 1829 return self.inst.method 1830 1831class TestGetcallargsUnboundMethods(TestGetcallargsMethods): 1832 1833 def makeCallable(self, signature): 1834 super(TestGetcallargsUnboundMethods, self).makeCallable(signature) 1835 return self.cls.method 1836 1837 def assertEqualCallArgs(self, func, call_params_string, locs=None): 1838 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs( 1839 *self._getAssertEqualParams(func, call_params_string, locs)) 1840 1841 def assertEqualException(self, func, call_params_string, locs=None): 1842 return super(TestGetcallargsUnboundMethods, self).assertEqualException( 1843 *self._getAssertEqualParams(func, call_params_string, locs)) 1844 1845 def _getAssertEqualParams(self, func, call_params_string, locs=None): 1846 assert 'inst' not in call_params_string 1847 locs = dict(locs or {}, inst=self.inst) 1848 return (func, 'inst,' + call_params_string, locs) 1849 1850 1851class TestGetattrStatic(unittest.TestCase): 1852 1853 def test_basic(self): 1854 class Thing(object): 1855 x = object() 1856 1857 thing = Thing() 1858 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x) 1859 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x) 1860 with self.assertRaises(AttributeError): 1861 inspect.getattr_static(thing, 'y') 1862 1863 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3) 1864 1865 def test_inherited(self): 1866 class Thing(object): 1867 x = object() 1868 class OtherThing(Thing): 1869 pass 1870 1871 something = OtherThing() 1872 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x) 1873 1874 def test_instance_attr(self): 1875 class Thing(object): 1876 x = 2 1877 def __init__(self, x): 1878 self.x = x 1879 thing = Thing(3) 1880 self.assertEqual(inspect.getattr_static(thing, 'x'), 3) 1881 del thing.x 1882 self.assertEqual(inspect.getattr_static(thing, 'x'), 2) 1883 1884 def test_property(self): 1885 class Thing(object): 1886 @property 1887 def x(self): 1888 raise AttributeError("I'm pretending not to exist") 1889 thing = Thing() 1890 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x) 1891 1892 def test_descriptor_raises_AttributeError(self): 1893 class descriptor(object): 1894 def __get__(*_): 1895 raise AttributeError("I'm pretending not to exist") 1896 desc = descriptor() 1897 class Thing(object): 1898 x = desc 1899 thing = Thing() 1900 self.assertEqual(inspect.getattr_static(thing, 'x'), desc) 1901 1902 def test_classAttribute(self): 1903 class Thing(object): 1904 x = object() 1905 1906 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x) 1907 1908 def test_classVirtualAttribute(self): 1909 class Thing(object): 1910 @types.DynamicClassAttribute 1911 def x(self): 1912 return self._x 1913 _x = object() 1914 1915 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x']) 1916 1917 def test_inherited_classattribute(self): 1918 class Thing(object): 1919 x = object() 1920 class OtherThing(Thing): 1921 pass 1922 1923 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x) 1924 1925 def test_slots(self): 1926 class Thing(object): 1927 y = 'bar' 1928 __slots__ = ['x'] 1929 def __init__(self): 1930 self.x = 'foo' 1931 thing = Thing() 1932 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x) 1933 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar') 1934 1935 del thing.x 1936 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x) 1937 1938 def test_metaclass(self): 1939 class meta(type): 1940 attr = 'foo' 1941 class Thing(object, metaclass=meta): 1942 pass 1943 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo') 1944 1945 class sub(meta): 1946 pass 1947 class OtherThing(object, metaclass=sub): 1948 x = 3 1949 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo') 1950 1951 class OtherOtherThing(OtherThing): 1952 pass 1953 # this test is odd, but it was added as it exposed a bug 1954 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3) 1955 1956 def test_no_dict_no_slots(self): 1957 self.assertEqual(inspect.getattr_static(1, 'foo', None), None) 1958 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None) 1959 1960 def test_no_dict_no_slots_instance_member(self): 1961 # returns descriptor 1962 with open(__file__, encoding='utf-8') as handle: 1963 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name) 1964 1965 def test_inherited_slots(self): 1966 # returns descriptor 1967 class Thing(object): 1968 __slots__ = ['x'] 1969 def __init__(self): 1970 self.x = 'foo' 1971 1972 class OtherThing(Thing): 1973 pass 1974 # it would be nice if this worked... 1975 # we get the descriptor instead of the instance attribute 1976 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x) 1977 1978 def test_descriptor(self): 1979 class descriptor(object): 1980 def __get__(self, instance, owner): 1981 return 3 1982 class Foo(object): 1983 d = descriptor() 1984 1985 foo = Foo() 1986 1987 # for a non data descriptor we return the instance attribute 1988 foo.__dict__['d'] = 1 1989 self.assertEqual(inspect.getattr_static(foo, 'd'), 1) 1990 1991 # if the descriptor is a data-descriptor we should return the 1992 # descriptor 1993 descriptor.__set__ = lambda s, i, v: None 1994 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d']) 1995 1996 del descriptor.__set__ 1997 descriptor.__delete__ = lambda s, i, o: None 1998 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d']) 1999 2000 def test_metaclass_with_descriptor(self): 2001 class descriptor(object): 2002 def __get__(self, instance, owner): 2003 return 3 2004 class meta(type): 2005 d = descriptor() 2006 class Thing(object, metaclass=meta): 2007 pass 2008 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d']) 2009 2010 2011 def test_class_as_property(self): 2012 class Base(object): 2013 foo = 3 2014 2015 class Something(Base): 2016 executed = False 2017 @property 2018 def __class__(self): 2019 self.executed = True 2020 return object 2021 2022 instance = Something() 2023 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3) 2024 self.assertFalse(instance.executed) 2025 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3) 2026 2027 def test_mro_as_property(self): 2028 class Meta(type): 2029 @property 2030 def __mro__(self): 2031 return (object,) 2032 2033 class Base(object): 2034 foo = 3 2035 2036 class Something(Base, metaclass=Meta): 2037 pass 2038 2039 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3) 2040 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3) 2041 2042 def test_dict_as_property(self): 2043 test = self 2044 test.called = False 2045 2046 class Foo(dict): 2047 a = 3 2048 @property 2049 def __dict__(self): 2050 test.called = True 2051 return {} 2052 2053 foo = Foo() 2054 foo.a = 4 2055 self.assertEqual(inspect.getattr_static(foo, 'a'), 3) 2056 self.assertFalse(test.called) 2057 2058 def test_custom_object_dict(self): 2059 test = self 2060 test.called = False 2061 2062 class Custom(dict): 2063 def get(self, key, default=None): 2064 test.called = True 2065 super().get(key, default) 2066 2067 class Foo(object): 2068 a = 3 2069 foo = Foo() 2070 foo.__dict__ = Custom() 2071 self.assertEqual(inspect.getattr_static(foo, 'a'), 3) 2072 self.assertFalse(test.called) 2073 2074 def test_metaclass_dict_as_property(self): 2075 class Meta(type): 2076 @property 2077 def __dict__(self): 2078 self.executed = True 2079 2080 class Thing(metaclass=Meta): 2081 executed = False 2082 2083 def __init__(self): 2084 self.spam = 42 2085 2086 instance = Thing() 2087 self.assertEqual(inspect.getattr_static(instance, "spam"), 42) 2088 self.assertFalse(Thing.executed) 2089 2090 def test_module(self): 2091 sentinel = object() 2092 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel), 2093 sentinel) 2094 2095 def test_metaclass_with_metaclass_with_dict_as_property(self): 2096 class MetaMeta(type): 2097 @property 2098 def __dict__(self): 2099 self.executed = True 2100 return dict(spam=42) 2101 2102 class Meta(type, metaclass=MetaMeta): 2103 executed = False 2104 2105 class Thing(metaclass=Meta): 2106 pass 2107 2108 with self.assertRaises(AttributeError): 2109 inspect.getattr_static(Thing, "spam") 2110 self.assertFalse(Thing.executed) 2111 2112 def test_custom___getattr__(self): 2113 test = self 2114 test.called = False 2115 2116 class Foo: 2117 def __getattr__(self, attr): 2118 test.called = True 2119 return {} 2120 2121 with self.assertRaises(AttributeError): 2122 inspect.getattr_static(Foo(), 'whatever') 2123 2124 self.assertFalse(test.called) 2125 2126 def test_custom___getattribute__(self): 2127 test = self 2128 test.called = False 2129 2130 class Foo: 2131 def __getattribute__(self, attr): 2132 test.called = True 2133 return {} 2134 2135 with self.assertRaises(AttributeError): 2136 inspect.getattr_static(Foo(), 'really_could_be_anything') 2137 2138 self.assertFalse(test.called) 2139 2140 2141class TestGetGeneratorState(unittest.TestCase): 2142 2143 def setUp(self): 2144 def number_generator(): 2145 for number in range(5): 2146 yield number 2147 self.generator = number_generator() 2148 2149 def _generatorstate(self): 2150 return inspect.getgeneratorstate(self.generator) 2151 2152 def test_created(self): 2153 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED) 2154 2155 def test_suspended(self): 2156 next(self.generator) 2157 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED) 2158 2159 def test_closed_after_exhaustion(self): 2160 for i in self.generator: 2161 pass 2162 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED) 2163 2164 def test_closed_after_immediate_exception(self): 2165 with self.assertRaises(RuntimeError): 2166 self.generator.throw(RuntimeError) 2167 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED) 2168 2169 def test_running(self): 2170 # As mentioned on issue #10220, checking for the RUNNING state only 2171 # makes sense inside the generator itself. 2172 # The following generator checks for this by using the closure's 2173 # reference to self and the generator state checking helper method 2174 def running_check_generator(): 2175 for number in range(5): 2176 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING) 2177 yield number 2178 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING) 2179 self.generator = running_check_generator() 2180 # Running up to the first yield 2181 next(self.generator) 2182 # Running after the first yield 2183 next(self.generator) 2184 2185 def test_easy_debugging(self): 2186 # repr() and str() of a generator state should contain the state name 2187 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split() 2188 for name in names: 2189 state = getattr(inspect, name) 2190 self.assertIn(name, repr(state)) 2191 self.assertIn(name, str(state)) 2192 2193 def test_getgeneratorlocals(self): 2194 def each(lst, a=None): 2195 b=(1, 2, 3) 2196 for v in lst: 2197 if v == 3: 2198 c = 12 2199 yield v 2200 2201 numbers = each([1, 2, 3]) 2202 self.assertEqual(inspect.getgeneratorlocals(numbers), 2203 {'a': None, 'lst': [1, 2, 3]}) 2204 next(numbers) 2205 self.assertEqual(inspect.getgeneratorlocals(numbers), 2206 {'a': None, 'lst': [1, 2, 3], 'v': 1, 2207 'b': (1, 2, 3)}) 2208 next(numbers) 2209 self.assertEqual(inspect.getgeneratorlocals(numbers), 2210 {'a': None, 'lst': [1, 2, 3], 'v': 2, 2211 'b': (1, 2, 3)}) 2212 next(numbers) 2213 self.assertEqual(inspect.getgeneratorlocals(numbers), 2214 {'a': None, 'lst': [1, 2, 3], 'v': 3, 2215 'b': (1, 2, 3), 'c': 12}) 2216 try: 2217 next(numbers) 2218 except StopIteration: 2219 pass 2220 self.assertEqual(inspect.getgeneratorlocals(numbers), {}) 2221 2222 def test_getgeneratorlocals_empty(self): 2223 def yield_one(): 2224 yield 1 2225 one = yield_one() 2226 self.assertEqual(inspect.getgeneratorlocals(one), {}) 2227 try: 2228 next(one) 2229 except StopIteration: 2230 pass 2231 self.assertEqual(inspect.getgeneratorlocals(one), {}) 2232 2233 def test_getgeneratorlocals_error(self): 2234 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1) 2235 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True) 2236 self.assertRaises(TypeError, inspect.getgeneratorlocals, set) 2237 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3)) 2238 2239 2240class TestGetCoroutineState(unittest.TestCase): 2241 2242 def setUp(self): 2243 @types.coroutine 2244 def number_coroutine(): 2245 for number in range(5): 2246 yield number 2247 async def coroutine(): 2248 await number_coroutine() 2249 self.coroutine = coroutine() 2250 2251 def tearDown(self): 2252 self.coroutine.close() 2253 2254 def _coroutinestate(self): 2255 return inspect.getcoroutinestate(self.coroutine) 2256 2257 def test_created(self): 2258 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED) 2259 2260 def test_suspended(self): 2261 self.coroutine.send(None) 2262 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED) 2263 2264 def test_closed_after_exhaustion(self): 2265 while True: 2266 try: 2267 self.coroutine.send(None) 2268 except StopIteration: 2269 break 2270 2271 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED) 2272 2273 def test_closed_after_immediate_exception(self): 2274 with self.assertRaises(RuntimeError): 2275 self.coroutine.throw(RuntimeError) 2276 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED) 2277 2278 def test_easy_debugging(self): 2279 # repr() and str() of a coroutine state should contain the state name 2280 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split() 2281 for name in names: 2282 state = getattr(inspect, name) 2283 self.assertIn(name, repr(state)) 2284 self.assertIn(name, str(state)) 2285 2286 def test_getcoroutinelocals(self): 2287 @types.coroutine 2288 def gencoro(): 2289 yield 2290 2291 gencoro = gencoro() 2292 async def func(a=None): 2293 b = 'spam' 2294 await gencoro 2295 2296 coro = func() 2297 self.assertEqual(inspect.getcoroutinelocals(coro), 2298 {'a': None, 'gencoro': gencoro}) 2299 coro.send(None) 2300 self.assertEqual(inspect.getcoroutinelocals(coro), 2301 {'a': None, 'gencoro': gencoro, 'b': 'spam'}) 2302 2303 2304class MySignature(inspect.Signature): 2305 # Top-level to make it picklable; 2306 # used in test_signature_object_pickle 2307 pass 2308 2309class MyParameter(inspect.Parameter): 2310 # Top-level to make it picklable; 2311 # used in test_signature_object_pickle 2312 pass 2313 2314 2315 2316class TestSignatureObject(unittest.TestCase): 2317 @staticmethod 2318 def signature(func, **kw): 2319 sig = inspect.signature(func, **kw) 2320 return (tuple((param.name, 2321 (... if param.default is param.empty else param.default), 2322 (... if param.annotation is param.empty 2323 else param.annotation), 2324 str(param.kind).lower()) 2325 for param in sig.parameters.values()), 2326 (... if sig.return_annotation is sig.empty 2327 else sig.return_annotation)) 2328 2329 def test_signature_object(self): 2330 S = inspect.Signature 2331 P = inspect.Parameter 2332 2333 self.assertEqual(str(S()), '()') 2334 self.assertEqual(repr(S().parameters), 'mappingproxy(OrderedDict())') 2335 2336 def test(po, /, pk, pkd=100, *args, ko, kod=10, **kwargs): 2337 pass 2338 2339 sig = inspect.signature(test) 2340 self.assertTrue(repr(sig).startswith('<Signature')) 2341 self.assertTrue('(po, /, pk' in repr(sig)) 2342 2343 # We need two functions, because it is impossible to represent 2344 # all param kinds in a single one. 2345 def test2(pod=42, /): 2346 pass 2347 2348 sig2 = inspect.signature(test2) 2349 self.assertTrue(repr(sig2).startswith('<Signature')) 2350 self.assertTrue('(pod=42, /)' in repr(sig2)) 2351 2352 po = sig.parameters['po'] 2353 pod = sig2.parameters['pod'] 2354 pk = sig.parameters['pk'] 2355 pkd = sig.parameters['pkd'] 2356 args = sig.parameters['args'] 2357 ko = sig.parameters['ko'] 2358 kod = sig.parameters['kod'] 2359 kwargs = sig.parameters['kwargs'] 2360 2361 S((po, pk, args, ko, kwargs)) 2362 S((po, pk, ko, kod)) 2363 S((po, pod, ko)) 2364 S((po, pod, kod)) 2365 S((pod, ko, kod)) 2366 S((pod, kod)) 2367 S((pod, args, kod, kwargs)) 2368 # keyword-only parameters without default values 2369 # can follow keyword-only parameters with default values: 2370 S((kod, ko)) 2371 S((kod, ko, kwargs)) 2372 S((args, kod, ko)) 2373 2374 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 2375 S((pk, po, args, ko, kwargs)) 2376 2377 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 2378 S((po, args, pk, ko, kwargs)) 2379 2380 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 2381 S((args, po, pk, ko, kwargs)) 2382 2383 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 2384 S((po, pk, args, kwargs, ko)) 2385 2386 kwargs2 = kwargs.replace(name='args') 2387 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'): 2388 S((po, pk, args, kwargs2, ko)) 2389 2390 with self.assertRaisesRegex(ValueError, 'follows default argument'): 2391 S((pod, po)) 2392 2393 with self.assertRaisesRegex(ValueError, 'follows default argument'): 2394 S((pod, pk)) 2395 2396 with self.assertRaisesRegex(ValueError, 'follows default argument'): 2397 S((po, pod, pk)) 2398 2399 with self.assertRaisesRegex(ValueError, 'follows default argument'): 2400 S((po, pkd, pk)) 2401 2402 with self.assertRaisesRegex(ValueError, 'follows default argument'): 2403 S((pkd, pk)) 2404 2405 def test_signature_object_pickle(self): 2406 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass 2407 foo_partial = functools.partial(foo, a=1) 2408 2409 sig = inspect.signature(foo_partial) 2410 2411 for ver in range(pickle.HIGHEST_PROTOCOL + 1): 2412 with self.subTest(pickle_ver=ver, subclass=False): 2413 sig_pickled = pickle.loads(pickle.dumps(sig, ver)) 2414 self.assertEqual(sig, sig_pickled) 2415 2416 # Test that basic sub-classing works 2417 sig = inspect.signature(foo) 2418 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY) 2419 myparams = collections.OrderedDict(sig.parameters, a=myparam) 2420 mysig = MySignature().replace(parameters=myparams.values(), 2421 return_annotation=sig.return_annotation) 2422 self.assertTrue(isinstance(mysig, MySignature)) 2423 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter)) 2424 2425 for ver in range(pickle.HIGHEST_PROTOCOL + 1): 2426 with self.subTest(pickle_ver=ver, subclass=True): 2427 sig_pickled = pickle.loads(pickle.dumps(mysig, ver)) 2428 self.assertEqual(mysig, sig_pickled) 2429 self.assertTrue(isinstance(sig_pickled, MySignature)) 2430 self.assertTrue(isinstance(sig_pickled.parameters['z'], 2431 MyParameter)) 2432 2433 def test_signature_immutability(self): 2434 def test(a): 2435 pass 2436 sig = inspect.signature(test) 2437 2438 with self.assertRaises(AttributeError): 2439 sig.foo = 'bar' 2440 2441 with self.assertRaises(TypeError): 2442 sig.parameters['a'] = None 2443 2444 def test_signature_on_noarg(self): 2445 def test(): 2446 pass 2447 self.assertEqual(self.signature(test), ((), ...)) 2448 2449 def test_signature_on_wargs(self): 2450 def test(a, b:'foo') -> 123: 2451 pass 2452 self.assertEqual(self.signature(test), 2453 ((('a', ..., ..., "positional_or_keyword"), 2454 ('b', ..., 'foo', "positional_or_keyword")), 2455 123)) 2456 2457 def test_signature_on_wkwonly(self): 2458 def test(*, a:float, b:str) -> int: 2459 pass 2460 self.assertEqual(self.signature(test), 2461 ((('a', ..., float, "keyword_only"), 2462 ('b', ..., str, "keyword_only")), 2463 int)) 2464 2465 def test_signature_on_complex_args(self): 2466 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int): 2467 pass 2468 self.assertEqual(self.signature(test), 2469 ((('a', ..., ..., "positional_or_keyword"), 2470 ('b', 10, 'foo', "positional_or_keyword"), 2471 ('args', ..., 'bar', "var_positional"), 2472 ('spam', ..., 'baz', "keyword_only"), 2473 ('ham', 123, ..., "keyword_only"), 2474 ('kwargs', ..., int, "var_keyword")), 2475 ...)) 2476 2477 def test_signature_without_self(self): 2478 def test_args_only(*args): # NOQA 2479 pass 2480 2481 def test_args_kwargs_only(*args, **kwargs): # NOQA 2482 pass 2483 2484 class A: 2485 @classmethod 2486 def test_classmethod(*args): # NOQA 2487 pass 2488 2489 @staticmethod 2490 def test_staticmethod(*args): # NOQA 2491 pass 2492 2493 f1 = functools.partialmethod((test_classmethod), 1) 2494 f2 = functools.partialmethod((test_args_only), 1) 2495 f3 = functools.partialmethod((test_staticmethod), 1) 2496 f4 = functools.partialmethod((test_args_kwargs_only),1) 2497 2498 self.assertEqual(self.signature(test_args_only), 2499 ((('args', ..., ..., 'var_positional'),), ...)) 2500 self.assertEqual(self.signature(test_args_kwargs_only), 2501 ((('args', ..., ..., 'var_positional'), 2502 ('kwargs', ..., ..., 'var_keyword')), ...)) 2503 self.assertEqual(self.signature(A.f1), 2504 ((('args', ..., ..., 'var_positional'),), ...)) 2505 self.assertEqual(self.signature(A.f2), 2506 ((('args', ..., ..., 'var_positional'),), ...)) 2507 self.assertEqual(self.signature(A.f3), 2508 ((('args', ..., ..., 'var_positional'),), ...)) 2509 self.assertEqual(self.signature(A.f4), 2510 ((('args', ..., ..., 'var_positional'), 2511 ('kwargs', ..., ..., 'var_keyword')), ...)) 2512 @cpython_only 2513 @unittest.skipIf(MISSING_C_DOCSTRINGS, 2514 "Signature information for builtins requires docstrings") 2515 def test_signature_on_builtins(self): 2516 import _testcapi 2517 2518 def test_unbound_method(o): 2519 """Use this to test unbound methods (things that should have a self)""" 2520 signature = inspect.signature(o) 2521 self.assertTrue(isinstance(signature, inspect.Signature)) 2522 self.assertEqual(list(signature.parameters.values())[0].name, 'self') 2523 return signature 2524 2525 def test_callable(o): 2526 """Use this to test bound methods or normal callables (things that don't expect self)""" 2527 signature = inspect.signature(o) 2528 self.assertTrue(isinstance(signature, inspect.Signature)) 2529 if signature.parameters: 2530 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self') 2531 return signature 2532 2533 signature = test_callable(_testcapi.docstring_with_signature_with_defaults) 2534 def p(name): return signature.parameters[name].default 2535 self.assertEqual(p('s'), 'avocado') 2536 self.assertEqual(p('b'), b'bytes') 2537 self.assertEqual(p('d'), 3.14) 2538 self.assertEqual(p('i'), 35) 2539 self.assertEqual(p('n'), None) 2540 self.assertEqual(p('t'), True) 2541 self.assertEqual(p('f'), False) 2542 self.assertEqual(p('local'), 3) 2543 self.assertEqual(p('sys'), sys.maxsize) 2544 self.assertEqual(p('exp'), sys.maxsize - 1) 2545 2546 test_callable(object) 2547 2548 # normal method 2549 # (PyMethodDescr_Type, "method_descriptor") 2550 test_unbound_method(_pickle.Pickler.dump) 2551 d = _pickle.Pickler(io.StringIO()) 2552 test_callable(d.dump) 2553 2554 # static method 2555 test_callable(bytes.maketrans) 2556 test_callable(b'abc'.maketrans) 2557 2558 # class method 2559 test_callable(dict.fromkeys) 2560 test_callable({}.fromkeys) 2561 2562 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor") 2563 test_unbound_method(type.__call__) 2564 test_unbound_method(int.__add__) 2565 test_callable((3).__add__) 2566 2567 # _PyMethodWrapper_Type 2568 # support for 'method-wrapper' 2569 test_callable(min.__call__) 2570 2571 # This doesn't work now. 2572 # (We don't have a valid signature for "type" in 3.4) 2573 with self.assertRaisesRegex(ValueError, "no signature found"): 2574 class ThisWorksNow: 2575 __call__ = type 2576 test_callable(ThisWorksNow()) 2577 2578 # Regression test for issue #20786 2579 test_unbound_method(dict.__delitem__) 2580 test_unbound_method(property.__delete__) 2581 2582 # Regression test for issue #20586 2583 test_callable(_testcapi.docstring_with_signature_but_no_doc) 2584 2585 @cpython_only 2586 @unittest.skipIf(MISSING_C_DOCSTRINGS, 2587 "Signature information for builtins requires docstrings") 2588 def test_signature_on_decorated_builtins(self): 2589 import _testcapi 2590 func = _testcapi.docstring_with_signature_with_defaults 2591 2592 def decorator(func): 2593 @functools.wraps(func) 2594 def wrapper(*args, **kwargs) -> int: 2595 return func(*args, **kwargs) 2596 return wrapper 2597 2598 decorated_func = decorator(func) 2599 2600 self.assertEqual(inspect.signature(func), 2601 inspect.signature(decorated_func)) 2602 2603 def wrapper_like(*args, **kwargs) -> int: pass 2604 self.assertEqual(inspect.signature(decorated_func, 2605 follow_wrapped=False), 2606 inspect.signature(wrapper_like)) 2607 2608 @cpython_only 2609 def test_signature_on_builtins_no_signature(self): 2610 import _testcapi 2611 with self.assertRaisesRegex(ValueError, 2612 'no signature found for builtin'): 2613 inspect.signature(_testcapi.docstring_no_signature) 2614 2615 with self.assertRaisesRegex(ValueError, 2616 'no signature found for builtin'): 2617 inspect.signature(str) 2618 2619 def test_signature_on_non_function(self): 2620 with self.assertRaisesRegex(TypeError, 'is not a callable object'): 2621 inspect.signature(42) 2622 2623 def test_signature_from_functionlike_object(self): 2624 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs): 2625 pass 2626 2627 class funclike: 2628 # Has to be callable, and have correct 2629 # __code__, __annotations__, __defaults__, __name__, 2630 # and __kwdefaults__ attributes 2631 2632 def __init__(self, func): 2633 self.__name__ = func.__name__ 2634 self.__code__ = func.__code__ 2635 self.__annotations__ = func.__annotations__ 2636 self.__defaults__ = func.__defaults__ 2637 self.__kwdefaults__ = func.__kwdefaults__ 2638 self.func = func 2639 2640 def __call__(self, *args, **kwargs): 2641 return self.func(*args, **kwargs) 2642 2643 sig_func = inspect.Signature.from_callable(func) 2644 2645 sig_funclike = inspect.Signature.from_callable(funclike(func)) 2646 self.assertEqual(sig_funclike, sig_func) 2647 2648 sig_funclike = inspect.signature(funclike(func)) 2649 self.assertEqual(sig_funclike, sig_func) 2650 2651 # If object is not a duck type of function, then 2652 # signature will try to get a signature for its '__call__' 2653 # method 2654 fl = funclike(func) 2655 del fl.__defaults__ 2656 self.assertEqual(self.signature(fl), 2657 ((('args', ..., ..., "var_positional"), 2658 ('kwargs', ..., ..., "var_keyword")), 2659 ...)) 2660 2661 # Test with cython-like builtins: 2662 _orig_isdesc = inspect.ismethoddescriptor 2663 def _isdesc(obj): 2664 if hasattr(obj, '_builtinmock'): 2665 return True 2666 return _orig_isdesc(obj) 2667 2668 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc): 2669 builtin_func = funclike(func) 2670 # Make sure that our mock setup is working 2671 self.assertFalse(inspect.ismethoddescriptor(builtin_func)) 2672 builtin_func._builtinmock = True 2673 self.assertTrue(inspect.ismethoddescriptor(builtin_func)) 2674 self.assertEqual(inspect.signature(builtin_func), sig_func) 2675 2676 def test_signature_functionlike_class(self): 2677 # We only want to duck type function-like objects, 2678 # not classes. 2679 2680 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs): 2681 pass 2682 2683 class funclike: 2684 def __init__(self, marker): 2685 pass 2686 2687 __name__ = func.__name__ 2688 __code__ = func.__code__ 2689 __annotations__ = func.__annotations__ 2690 __defaults__ = func.__defaults__ 2691 __kwdefaults__ = func.__kwdefaults__ 2692 2693 self.assertEqual(str(inspect.signature(funclike)), '(marker)') 2694 2695 def test_signature_on_method(self): 2696 class Test: 2697 def __init__(*args): 2698 pass 2699 def m1(self, arg1, arg2=1) -> int: 2700 pass 2701 def m2(*args): 2702 pass 2703 def __call__(*, a): 2704 pass 2705 2706 self.assertEqual(self.signature(Test().m1), 2707 ((('arg1', ..., ..., "positional_or_keyword"), 2708 ('arg2', 1, ..., "positional_or_keyword")), 2709 int)) 2710 2711 self.assertEqual(self.signature(Test().m2), 2712 ((('args', ..., ..., "var_positional"),), 2713 ...)) 2714 2715 self.assertEqual(self.signature(Test), 2716 ((('args', ..., ..., "var_positional"),), 2717 ...)) 2718 2719 with self.assertRaisesRegex(ValueError, 'invalid method signature'): 2720 self.signature(Test()) 2721 2722 def test_signature_wrapped_bound_method(self): 2723 # Issue 24298 2724 class Test: 2725 def m1(self, arg1, arg2=1) -> int: 2726 pass 2727 @functools.wraps(Test().m1) 2728 def m1d(*args, **kwargs): 2729 pass 2730 self.assertEqual(self.signature(m1d), 2731 ((('arg1', ..., ..., "positional_or_keyword"), 2732 ('arg2', 1, ..., "positional_or_keyword")), 2733 int)) 2734 2735 def test_signature_on_classmethod(self): 2736 class Test: 2737 @classmethod 2738 def foo(cls, arg1, *, arg2=1): 2739 pass 2740 2741 meth = Test().foo 2742 self.assertEqual(self.signature(meth), 2743 ((('arg1', ..., ..., "positional_or_keyword"), 2744 ('arg2', 1, ..., "keyword_only")), 2745 ...)) 2746 2747 meth = Test.foo 2748 self.assertEqual(self.signature(meth), 2749 ((('arg1', ..., ..., "positional_or_keyword"), 2750 ('arg2', 1, ..., "keyword_only")), 2751 ...)) 2752 2753 def test_signature_on_staticmethod(self): 2754 class Test: 2755 @staticmethod 2756 def foo(cls, *, arg): 2757 pass 2758 2759 meth = Test().foo 2760 self.assertEqual(self.signature(meth), 2761 ((('cls', ..., ..., "positional_or_keyword"), 2762 ('arg', ..., ..., "keyword_only")), 2763 ...)) 2764 2765 meth = Test.foo 2766 self.assertEqual(self.signature(meth), 2767 ((('cls', ..., ..., "positional_or_keyword"), 2768 ('arg', ..., ..., "keyword_only")), 2769 ...)) 2770 2771 def test_signature_on_partial(self): 2772 from functools import partial 2773 2774 def test(): 2775 pass 2776 2777 self.assertEqual(self.signature(partial(test)), ((), ...)) 2778 2779 with self.assertRaisesRegex(ValueError, "has incorrect arguments"): 2780 inspect.signature(partial(test, 1)) 2781 2782 with self.assertRaisesRegex(ValueError, "has incorrect arguments"): 2783 inspect.signature(partial(test, a=1)) 2784 2785 def test(a, b, *, c, d): 2786 pass 2787 2788 self.assertEqual(self.signature(partial(test)), 2789 ((('a', ..., ..., "positional_or_keyword"), 2790 ('b', ..., ..., "positional_or_keyword"), 2791 ('c', ..., ..., "keyword_only"), 2792 ('d', ..., ..., "keyword_only")), 2793 ...)) 2794 2795 self.assertEqual(self.signature(partial(test, 1)), 2796 ((('b', ..., ..., "positional_or_keyword"), 2797 ('c', ..., ..., "keyword_only"), 2798 ('d', ..., ..., "keyword_only")), 2799 ...)) 2800 2801 self.assertEqual(self.signature(partial(test, 1, c=2)), 2802 ((('b', ..., ..., "positional_or_keyword"), 2803 ('c', 2, ..., "keyword_only"), 2804 ('d', ..., ..., "keyword_only")), 2805 ...)) 2806 2807 self.assertEqual(self.signature(partial(test, b=1, c=2)), 2808 ((('a', ..., ..., "positional_or_keyword"), 2809 ('b', 1, ..., "keyword_only"), 2810 ('c', 2, ..., "keyword_only"), 2811 ('d', ..., ..., "keyword_only")), 2812 ...)) 2813 2814 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)), 2815 ((('b', 1, ..., "keyword_only"), 2816 ('c', 2, ..., "keyword_only"), 2817 ('d', ..., ..., "keyword_only")), 2818 ...)) 2819 2820 self.assertEqual(self.signature(partial(test, a=1)), 2821 ((('a', 1, ..., "keyword_only"), 2822 ('b', ..., ..., "keyword_only"), 2823 ('c', ..., ..., "keyword_only"), 2824 ('d', ..., ..., "keyword_only")), 2825 ...)) 2826 2827 def test(a, *args, b, **kwargs): 2828 pass 2829 2830 self.assertEqual(self.signature(partial(test, 1)), 2831 ((('args', ..., ..., "var_positional"), 2832 ('b', ..., ..., "keyword_only"), 2833 ('kwargs', ..., ..., "var_keyword")), 2834 ...)) 2835 2836 self.assertEqual(self.signature(partial(test, a=1)), 2837 ((('a', 1, ..., "keyword_only"), 2838 ('b', ..., ..., "keyword_only"), 2839 ('kwargs', ..., ..., "var_keyword")), 2840 ...)) 2841 2842 self.assertEqual(self.signature(partial(test, 1, 2, 3)), 2843 ((('args', ..., ..., "var_positional"), 2844 ('b', ..., ..., "keyword_only"), 2845 ('kwargs', ..., ..., "var_keyword")), 2846 ...)) 2847 2848 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)), 2849 ((('args', ..., ..., "var_positional"), 2850 ('b', ..., ..., "keyword_only"), 2851 ('kwargs', ..., ..., "var_keyword")), 2852 ...)) 2853 2854 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)), 2855 ((('args', ..., ..., "var_positional"), 2856 ('b', 0, ..., "keyword_only"), 2857 ('kwargs', ..., ..., "var_keyword")), 2858 ...)) 2859 2860 self.assertEqual(self.signature(partial(test, b=0)), 2861 ((('a', ..., ..., "positional_or_keyword"), 2862 ('args', ..., ..., "var_positional"), 2863 ('b', 0, ..., "keyword_only"), 2864 ('kwargs', ..., ..., "var_keyword")), 2865 ...)) 2866 2867 self.assertEqual(self.signature(partial(test, b=0, test=1)), 2868 ((('a', ..., ..., "positional_or_keyword"), 2869 ('args', ..., ..., "var_positional"), 2870 ('b', 0, ..., "keyword_only"), 2871 ('kwargs', ..., ..., "var_keyword")), 2872 ...)) 2873 2874 def test(a, b, c:int) -> 42: 2875 pass 2876 2877 sig = test.__signature__ = inspect.signature(test) 2878 2879 self.assertEqual(self.signature(partial(partial(test, 1))), 2880 ((('b', ..., ..., "positional_or_keyword"), 2881 ('c', ..., int, "positional_or_keyword")), 2882 42)) 2883 2884 self.assertEqual(self.signature(partial(partial(test, 1), 2)), 2885 ((('c', ..., int, "positional_or_keyword"),), 2886 42)) 2887 2888 def foo(a): 2889 return a 2890 _foo = partial(partial(foo, a=10), a=20) 2891 self.assertEqual(self.signature(_foo), 2892 ((('a', 20, ..., "keyword_only"),), 2893 ...)) 2894 # check that we don't have any side-effects in signature(), 2895 # and the partial object is still functioning 2896 self.assertEqual(_foo(), 20) 2897 2898 def foo(a, b, c): 2899 return a, b, c 2900 _foo = partial(partial(foo, 1, b=20), b=30) 2901 2902 self.assertEqual(self.signature(_foo), 2903 ((('b', 30, ..., "keyword_only"), 2904 ('c', ..., ..., "keyword_only")), 2905 ...)) 2906 self.assertEqual(_foo(c=10), (1, 30, 10)) 2907 2908 def foo(a, b, c, *, d): 2909 return a, b, c, d 2910 _foo = partial(partial(foo, d=20, c=20), b=10, d=30) 2911 self.assertEqual(self.signature(_foo), 2912 ((('a', ..., ..., "positional_or_keyword"), 2913 ('b', 10, ..., "keyword_only"), 2914 ('c', 20, ..., "keyword_only"), 2915 ('d', 30, ..., "keyword_only"), 2916 ), 2917 ...)) 2918 ba = inspect.signature(_foo).bind(a=200, b=11) 2919 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30)) 2920 2921 def foo(a=1, b=2, c=3): 2922 return a, b, c 2923 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13) 2924 2925 ba = inspect.signature(_foo).bind(a=11) 2926 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13)) 2927 2928 ba = inspect.signature(_foo).bind(11, 12) 2929 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13)) 2930 2931 ba = inspect.signature(_foo).bind(11, b=12) 2932 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13)) 2933 2934 ba = inspect.signature(_foo).bind(b=12) 2935 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13)) 2936 2937 _foo = partial(_foo, b=10, c=20) 2938 ba = inspect.signature(_foo).bind(12) 2939 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20)) 2940 2941 2942 def foo(a, b, /, c, d, **kwargs): 2943 pass 2944 sig = inspect.signature(foo) 2945 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)') 2946 2947 self.assertEqual(self.signature(partial(foo, 1)), 2948 ((('b', ..., ..., 'positional_only'), 2949 ('c', ..., ..., 'positional_or_keyword'), 2950 ('d', ..., ..., 'positional_or_keyword'), 2951 ('kwargs', ..., ..., 'var_keyword')), 2952 ...)) 2953 2954 self.assertEqual(self.signature(partial(foo, 1, 2)), 2955 ((('c', ..., ..., 'positional_or_keyword'), 2956 ('d', ..., ..., 'positional_or_keyword'), 2957 ('kwargs', ..., ..., 'var_keyword')), 2958 ...)) 2959 2960 self.assertEqual(self.signature(partial(foo, 1, 2, 3)), 2961 ((('d', ..., ..., 'positional_or_keyword'), 2962 ('kwargs', ..., ..., 'var_keyword')), 2963 ...)) 2964 2965 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)), 2966 ((('c', 3, ..., 'keyword_only'), 2967 ('d', ..., ..., 'keyword_only'), 2968 ('kwargs', ..., ..., 'var_keyword')), 2969 ...)) 2970 2971 self.assertEqual(self.signature(partial(foo, 1, c=3)), 2972 ((('b', ..., ..., 'positional_only'), 2973 ('c', 3, ..., 'keyword_only'), 2974 ('d', ..., ..., 'keyword_only'), 2975 ('kwargs', ..., ..., 'var_keyword')), 2976 ...)) 2977 2978 def test_signature_on_partialmethod(self): 2979 from functools import partialmethod 2980 2981 class Spam: 2982 def test(): 2983 pass 2984 ham = partialmethod(test) 2985 2986 with self.assertRaisesRegex(ValueError, "has incorrect arguments"): 2987 inspect.signature(Spam.ham) 2988 2989 class Spam: 2990 def test(it, a, *, c) -> 'spam': 2991 pass 2992 ham = partialmethod(test, c=1) 2993 2994 self.assertEqual(self.signature(Spam.ham, eval_str=False), 2995 ((('it', ..., ..., 'positional_or_keyword'), 2996 ('a', ..., ..., 'positional_or_keyword'), 2997 ('c', 1, ..., 'keyword_only')), 2998 'spam')) 2999 3000 self.assertEqual(self.signature(Spam().ham, eval_str=False), 3001 ((('a', ..., ..., 'positional_or_keyword'), 3002 ('c', 1, ..., 'keyword_only')), 3003 'spam')) 3004 3005 class Spam: 3006 def test(self: 'anno', x): 3007 pass 3008 3009 g = partialmethod(test, 1) 3010 3011 self.assertEqual(self.signature(Spam.g, eval_str=False), 3012 ((('self', ..., 'anno', 'positional_or_keyword'),), 3013 ...)) 3014 3015 def test_signature_on_fake_partialmethod(self): 3016 def foo(a): pass 3017 foo._partialmethod = 'spam' 3018 self.assertEqual(str(inspect.signature(foo)), '(a)') 3019 3020 def test_signature_on_decorated(self): 3021 def decorator(func): 3022 @functools.wraps(func) 3023 def wrapper(*args, **kwargs) -> int: 3024 return func(*args, **kwargs) 3025 return wrapper 3026 3027 class Foo: 3028 @decorator 3029 def bar(self, a, b): 3030 pass 3031 3032 bar = decorator(Foo().bar) 3033 3034 self.assertEqual(self.signature(Foo.bar), 3035 ((('self', ..., ..., "positional_or_keyword"), 3036 ('a', ..., ..., "positional_or_keyword"), 3037 ('b', ..., ..., "positional_or_keyword")), 3038 ...)) 3039 3040 self.assertEqual(self.signature(Foo().bar), 3041 ((('a', ..., ..., "positional_or_keyword"), 3042 ('b', ..., ..., "positional_or_keyword")), 3043 ...)) 3044 3045 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False), 3046 ((('args', ..., ..., "var_positional"), 3047 ('kwargs', ..., ..., "var_keyword")), 3048 ...)) # functools.wraps will copy __annotations__ 3049 # from "func" to "wrapper", hence no 3050 # return_annotation 3051 3052 self.assertEqual(self.signature(bar), 3053 ((('a', ..., ..., "positional_or_keyword"), 3054 ('b', ..., ..., "positional_or_keyword")), 3055 ...)) 3056 3057 # Test that we handle method wrappers correctly 3058 def decorator(func): 3059 @functools.wraps(func) 3060 def wrapper(*args, **kwargs) -> int: 3061 return func(42, *args, **kwargs) 3062 sig = inspect.signature(func) 3063 new_params = tuple(sig.parameters.values())[1:] 3064 wrapper.__signature__ = sig.replace(parameters=new_params) 3065 return wrapper 3066 3067 class Foo: 3068 @decorator 3069 def __call__(self, a, b): 3070 pass 3071 3072 self.assertEqual(self.signature(Foo.__call__), 3073 ((('a', ..., ..., "positional_or_keyword"), 3074 ('b', ..., ..., "positional_or_keyword")), 3075 ...)) 3076 3077 self.assertEqual(self.signature(Foo().__call__), 3078 ((('b', ..., ..., "positional_or_keyword"),), 3079 ...)) 3080 3081 # Test we handle __signature__ partway down the wrapper stack 3082 def wrapped_foo_call(): 3083 pass 3084 wrapped_foo_call.__wrapped__ = Foo.__call__ 3085 3086 self.assertEqual(self.signature(wrapped_foo_call), 3087 ((('a', ..., ..., "positional_or_keyword"), 3088 ('b', ..., ..., "positional_or_keyword")), 3089 ...)) 3090 3091 3092 def test_signature_on_class(self): 3093 class C: 3094 def __init__(self, a): 3095 pass 3096 3097 self.assertEqual(self.signature(C), 3098 ((('a', ..., ..., "positional_or_keyword"),), 3099 ...)) 3100 3101 class CM(type): 3102 def __call__(cls, a): 3103 pass 3104 class C(metaclass=CM): 3105 def __init__(self, b): 3106 pass 3107 3108 self.assertEqual(self.signature(C), 3109 ((('a', ..., ..., "positional_or_keyword"),), 3110 ...)) 3111 3112 class CM(type): 3113 def __new__(mcls, name, bases, dct, *, foo=1): 3114 return super().__new__(mcls, name, bases, dct) 3115 class C(metaclass=CM): 3116 def __init__(self, b): 3117 pass 3118 3119 self.assertEqual(self.signature(C), 3120 ((('b', ..., ..., "positional_or_keyword"),), 3121 ...)) 3122 3123 self.assertEqual(self.signature(CM), 3124 ((('name', ..., ..., "positional_or_keyword"), 3125 ('bases', ..., ..., "positional_or_keyword"), 3126 ('dct', ..., ..., "positional_or_keyword"), 3127 ('foo', 1, ..., "keyword_only")), 3128 ...)) 3129 3130 class CMM(type): 3131 def __new__(mcls, name, bases, dct, *, foo=1): 3132 return super().__new__(mcls, name, bases, dct) 3133 def __call__(cls, nm, bs, dt): 3134 return type(nm, bs, dt) 3135 class CM(type, metaclass=CMM): 3136 def __new__(mcls, name, bases, dct, *, bar=2): 3137 return super().__new__(mcls, name, bases, dct) 3138 class C(metaclass=CM): 3139 def __init__(self, b): 3140 pass 3141 3142 self.assertEqual(self.signature(CMM), 3143 ((('name', ..., ..., "positional_or_keyword"), 3144 ('bases', ..., ..., "positional_or_keyword"), 3145 ('dct', ..., ..., "positional_or_keyword"), 3146 ('foo', 1, ..., "keyword_only")), 3147 ...)) 3148 3149 self.assertEqual(self.signature(CM), 3150 ((('nm', ..., ..., "positional_or_keyword"), 3151 ('bs', ..., ..., "positional_or_keyword"), 3152 ('dt', ..., ..., "positional_or_keyword")), 3153 ...)) 3154 3155 self.assertEqual(self.signature(C), 3156 ((('b', ..., ..., "positional_or_keyword"),), 3157 ...)) 3158 3159 class CM(type): 3160 def __init__(cls, name, bases, dct, *, bar=2): 3161 return super().__init__(name, bases, dct) 3162 class C(metaclass=CM): 3163 def __init__(self, b): 3164 pass 3165 3166 self.assertEqual(self.signature(CM), 3167 ((('name', ..., ..., "positional_or_keyword"), 3168 ('bases', ..., ..., "positional_or_keyword"), 3169 ('dct', ..., ..., "positional_or_keyword"), 3170 ('bar', 2, ..., "keyword_only")), 3171 ...)) 3172 3173 def test_signature_on_subclass(self): 3174 class A: 3175 def __new__(cls, a=1, *args, **kwargs): 3176 return object.__new__(cls) 3177 class B(A): 3178 def __init__(self, b): 3179 pass 3180 class C(A): 3181 def __new__(cls, a=1, b=2, *args, **kwargs): 3182 return object.__new__(cls) 3183 class D(A): 3184 pass 3185 3186 self.assertEqual(self.signature(B), 3187 ((('b', ..., ..., "positional_or_keyword"),), 3188 ...)) 3189 self.assertEqual(self.signature(C), 3190 ((('a', 1, ..., 'positional_or_keyword'), 3191 ('b', 2, ..., 'positional_or_keyword'), 3192 ('args', ..., ..., 'var_positional'), 3193 ('kwargs', ..., ..., 'var_keyword')), 3194 ...)) 3195 self.assertEqual(self.signature(D), 3196 ((('a', 1, ..., 'positional_or_keyword'), 3197 ('args', ..., ..., 'var_positional'), 3198 ('kwargs', ..., ..., 'var_keyword')), 3199 ...)) 3200 3201 def test_signature_on_generic_subclass(self): 3202 from typing import Generic, TypeVar 3203 3204 T = TypeVar('T') 3205 3206 class A(Generic[T]): 3207 def __init__(self, *, a: int) -> None: 3208 pass 3209 3210 self.assertEqual(self.signature(A), 3211 ((('a', ..., int, 'keyword_only'),), 3212 None)) 3213 3214 @unittest.skipIf(MISSING_C_DOCSTRINGS, 3215 "Signature information for builtins requires docstrings") 3216 def test_signature_on_class_without_init(self): 3217 # Test classes without user-defined __init__ or __new__ 3218 class C: pass 3219 self.assertEqual(str(inspect.signature(C)), '()') 3220 class D(C): pass 3221 self.assertEqual(str(inspect.signature(D)), '()') 3222 3223 # Test meta-classes without user-defined __init__ or __new__ 3224 class C(type): pass 3225 class D(C): pass 3226 with self.assertRaisesRegex(ValueError, "callable.*is not supported"): 3227 self.assertEqual(inspect.signature(C), None) 3228 with self.assertRaisesRegex(ValueError, "callable.*is not supported"): 3229 self.assertEqual(inspect.signature(D), None) 3230 3231 @unittest.skipIf(MISSING_C_DOCSTRINGS, 3232 "Signature information for builtins requires docstrings") 3233 def test_signature_on_builtin_class(self): 3234 expected = ('(file, protocol=None, fix_imports=True, ' 3235 'buffer_callback=None)') 3236 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected) 3237 3238 class P(_pickle.Pickler): pass 3239 class EmptyTrait: pass 3240 class P2(EmptyTrait, P): pass 3241 self.assertEqual(str(inspect.signature(P)), expected) 3242 self.assertEqual(str(inspect.signature(P2)), expected) 3243 3244 class P3(P2): 3245 def __init__(self, spam): 3246 pass 3247 self.assertEqual(str(inspect.signature(P3)), '(spam)') 3248 3249 class MetaP(type): 3250 def __call__(cls, foo, bar): 3251 pass 3252 class P4(P2, metaclass=MetaP): 3253 pass 3254 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)') 3255 3256 def test_signature_on_callable_objects(self): 3257 class Foo: 3258 def __call__(self, a): 3259 pass 3260 3261 self.assertEqual(self.signature(Foo()), 3262 ((('a', ..., ..., "positional_or_keyword"),), 3263 ...)) 3264 3265 class Spam: 3266 pass 3267 with self.assertRaisesRegex(TypeError, "is not a callable object"): 3268 inspect.signature(Spam()) 3269 3270 class Bar(Spam, Foo): 3271 pass 3272 3273 self.assertEqual(self.signature(Bar()), 3274 ((('a', ..., ..., "positional_or_keyword"),), 3275 ...)) 3276 3277 class Wrapped: 3278 pass 3279 Wrapped.__wrapped__ = lambda a: None 3280 self.assertEqual(self.signature(Wrapped), 3281 ((('a', ..., ..., "positional_or_keyword"),), 3282 ...)) 3283 # wrapper loop: 3284 Wrapped.__wrapped__ = Wrapped 3285 with self.assertRaisesRegex(ValueError, 'wrapper loop'): 3286 self.signature(Wrapped) 3287 3288 def test_signature_on_lambdas(self): 3289 self.assertEqual(self.signature((lambda a=10: a)), 3290 ((('a', 10, ..., "positional_or_keyword"),), 3291 ...)) 3292 3293 def test_signature_on_mocks(self): 3294 # https://github.com/python/cpython/issues/96127 3295 for mock in ( 3296 unittest.mock.Mock(), 3297 unittest.mock.AsyncMock(), 3298 unittest.mock.MagicMock(), 3299 ): 3300 with self.subTest(mock=mock): 3301 self.assertEqual(str(inspect.signature(mock)), '(*args, **kwargs)') 3302 3303 def test_signature_on_noncallable_mocks(self): 3304 for mock in ( 3305 unittest.mock.NonCallableMock(), 3306 unittest.mock.NonCallableMagicMock(), 3307 ): 3308 with self.subTest(mock=mock): 3309 with self.assertRaises(TypeError): 3310 inspect.signature(mock) 3311 3312 def test_signature_equality(self): 3313 def foo(a, *, b:int) -> float: pass 3314 self.assertFalse(inspect.signature(foo) == 42) 3315 self.assertTrue(inspect.signature(foo) != 42) 3316 self.assertTrue(inspect.signature(foo) == ALWAYS_EQ) 3317 self.assertFalse(inspect.signature(foo) != ALWAYS_EQ) 3318 3319 def bar(a, *, b:int) -> float: pass 3320 self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) 3321 self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) 3322 self.assertEqual( 3323 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 3324 3325 def bar(a, *, b:int) -> int: pass 3326 self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) 3327 self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) 3328 self.assertNotEqual( 3329 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 3330 3331 def bar(a, *, b:int): pass 3332 self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) 3333 self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) 3334 self.assertNotEqual( 3335 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 3336 3337 def bar(a, *, b:int=42) -> float: pass 3338 self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) 3339 self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) 3340 self.assertNotEqual( 3341 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 3342 3343 def bar(a, *, c) -> float: pass 3344 self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) 3345 self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) 3346 self.assertNotEqual( 3347 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 3348 3349 def bar(a, b:int) -> float: pass 3350 self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) 3351 self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) 3352 self.assertNotEqual( 3353 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 3354 def spam(b:int, a) -> float: pass 3355 self.assertFalse(inspect.signature(spam) == inspect.signature(bar)) 3356 self.assertTrue(inspect.signature(spam) != inspect.signature(bar)) 3357 self.assertNotEqual( 3358 hash(inspect.signature(spam)), hash(inspect.signature(bar))) 3359 3360 def foo(*, a, b, c): pass 3361 def bar(*, c, b, a): pass 3362 self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) 3363 self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) 3364 self.assertEqual( 3365 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 3366 3367 def foo(*, a=1, b, c): pass 3368 def bar(*, c, b, a=1): pass 3369 self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) 3370 self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) 3371 self.assertEqual( 3372 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 3373 3374 def foo(pos, *, a=1, b, c): pass 3375 def bar(pos, *, c, b, a=1): pass 3376 self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) 3377 self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) 3378 self.assertEqual( 3379 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 3380 3381 def foo(pos, *, a, b, c): pass 3382 def bar(pos, *, c, b, a=1): pass 3383 self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) 3384 self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) 3385 self.assertNotEqual( 3386 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 3387 3388 def foo(pos, *args, a=42, b, c, **kwargs:int): pass 3389 def bar(pos, *args, c, b, a=42, **kwargs:int): pass 3390 self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) 3391 self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) 3392 self.assertEqual( 3393 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 3394 3395 def test_signature_hashable(self): 3396 S = inspect.Signature 3397 P = inspect.Parameter 3398 3399 def foo(a): pass 3400 foo_sig = inspect.signature(foo) 3401 3402 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)]) 3403 3404 self.assertEqual(hash(foo_sig), hash(manual_sig)) 3405 self.assertNotEqual(hash(foo_sig), 3406 hash(manual_sig.replace(return_annotation='spam'))) 3407 3408 def bar(a) -> 1: pass 3409 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar))) 3410 3411 def foo(a={}): pass 3412 with self.assertRaisesRegex(TypeError, 'unhashable type'): 3413 hash(inspect.signature(foo)) 3414 3415 def foo(a) -> {}: pass 3416 with self.assertRaisesRegex(TypeError, 'unhashable type'): 3417 hash(inspect.signature(foo)) 3418 3419 def test_signature_str(self): 3420 def foo(a:int=1, *, b, c=None, **kwargs) -> 42: 3421 pass 3422 self.assertEqual(str(inspect.signature(foo)), 3423 '(a: int = 1, *, b, c=None, **kwargs) -> 42') 3424 3425 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42: 3426 pass 3427 self.assertEqual(str(inspect.signature(foo)), 3428 '(a: int = 1, *args, b, c=None, **kwargs) -> 42') 3429 3430 def foo(): 3431 pass 3432 self.assertEqual(str(inspect.signature(foo)), '()') 3433 3434 def foo(a: list[str]) -> tuple[str, float]: 3435 pass 3436 self.assertEqual(str(inspect.signature(foo)), 3437 '(a: list[str]) -> tuple[str, float]') 3438 3439 from typing import Tuple 3440 def foo(a: list[str]) -> Tuple[str, float]: 3441 pass 3442 self.assertEqual(str(inspect.signature(foo)), 3443 '(a: list[str]) -> Tuple[str, float]') 3444 3445 def test_signature_str_positional_only(self): 3446 P = inspect.Parameter 3447 S = inspect.Signature 3448 3449 def test(a_po, /, *, b, **kwargs): 3450 return a_po, kwargs 3451 3452 self.assertEqual(str(inspect.signature(test)), 3453 '(a_po, /, *, b, **kwargs)') 3454 3455 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])), 3456 '(foo, /)') 3457 3458 self.assertEqual(str(S(parameters=[ 3459 P('foo', P.POSITIONAL_ONLY), 3460 P('bar', P.VAR_KEYWORD)])), 3461 '(foo, /, **bar)') 3462 3463 self.assertEqual(str(S(parameters=[ 3464 P('foo', P.POSITIONAL_ONLY), 3465 P('bar', P.VAR_POSITIONAL)])), 3466 '(foo, /, *bar)') 3467 3468 def test_signature_replace_anno(self): 3469 def test() -> 42: 3470 pass 3471 3472 sig = inspect.signature(test) 3473 sig = sig.replace(return_annotation=None) 3474 self.assertIs(sig.return_annotation, None) 3475 sig = sig.replace(return_annotation=sig.empty) 3476 self.assertIs(sig.return_annotation, sig.empty) 3477 sig = sig.replace(return_annotation=42) 3478 self.assertEqual(sig.return_annotation, 42) 3479 self.assertEqual(sig, inspect.signature(test)) 3480 3481 def test_signature_replaced(self): 3482 def test(): 3483 pass 3484 3485 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY) 3486 sig = test.__signature__ = inspect.Signature(parameters=(spam_param,)) 3487 self.assertEqual(sig, inspect.signature(test)) 3488 3489 def test_signature_on_mangled_parameters(self): 3490 class Spam: 3491 def foo(self, __p1:1=2, *, __p2:2=3): 3492 pass 3493 class Ham(Spam): 3494 pass 3495 3496 self.assertEqual(self.signature(Spam.foo), 3497 ((('self', ..., ..., "positional_or_keyword"), 3498 ('_Spam__p1', 2, 1, "positional_or_keyword"), 3499 ('_Spam__p2', 3, 2, "keyword_only")), 3500 ...)) 3501 3502 self.assertEqual(self.signature(Spam.foo), 3503 self.signature(Ham.foo)) 3504 3505 def test_signature_from_callable_python_obj(self): 3506 class MySignature(inspect.Signature): pass 3507 def foo(a, *, b:1): pass 3508 foo_sig = MySignature.from_callable(foo) 3509 self.assertIsInstance(foo_sig, MySignature) 3510 3511 def test_signature_from_callable_class(self): 3512 # A regression test for a class inheriting its signature from `object`. 3513 class MySignature(inspect.Signature): pass 3514 class foo: pass 3515 foo_sig = MySignature.from_callable(foo) 3516 self.assertIsInstance(foo_sig, MySignature) 3517 3518 @unittest.skipIf(MISSING_C_DOCSTRINGS, 3519 "Signature information for builtins requires docstrings") 3520 def test_signature_from_callable_builtin_obj(self): 3521 class MySignature(inspect.Signature): pass 3522 sig = MySignature.from_callable(_pickle.Pickler) 3523 self.assertIsInstance(sig, MySignature) 3524 3525 def test_signature_definition_order_preserved_on_kwonly(self): 3526 for fn in signatures_with_lexicographic_keyword_only_parameters(): 3527 signature = inspect.signature(fn) 3528 l = list(signature.parameters) 3529 sorted_l = sorted(l) 3530 self.assertTrue(l) 3531 self.assertEqual(l, sorted_l) 3532 signature = inspect.signature(unsorted_keyword_only_parameters_fn) 3533 l = list(signature.parameters) 3534 self.assertEqual(l, unsorted_keyword_only_parameters) 3535 3536 def test_signater_parameters_is_ordered(self): 3537 p1 = inspect.signature(lambda x, y: None).parameters 3538 p2 = inspect.signature(lambda y, x: None).parameters 3539 self.assertNotEqual(p1, p2) 3540 3541 def test_signature_annotations_with_local_namespaces(self): 3542 class Foo: ... 3543 def func(foo: Foo) -> int: pass 3544 def func2(foo: Foo, bar: 'Bar') -> int: pass 3545 3546 for signature_func in (inspect.signature, inspect.Signature.from_callable): 3547 with self.subTest(signature_func = signature_func): 3548 sig1 = signature_func(func) 3549 self.assertEqual(sig1.return_annotation, int) 3550 self.assertEqual(sig1.parameters['foo'].annotation, Foo) 3551 3552 sig2 = signature_func(func, locals=locals()) 3553 self.assertEqual(sig2.return_annotation, int) 3554 self.assertEqual(sig2.parameters['foo'].annotation, Foo) 3555 3556 sig3 = signature_func(func2, globals={'Bar': int}, locals=locals()) 3557 self.assertEqual(sig3.return_annotation, int) 3558 self.assertEqual(sig3.parameters['foo'].annotation, Foo) 3559 self.assertEqual(sig3.parameters['bar'].annotation, 'Bar') 3560 3561 def test_signature_eval_str(self): 3562 isa = inspect_stringized_annotations 3563 sig = inspect.Signature 3564 par = inspect.Parameter 3565 PORK = inspect.Parameter.POSITIONAL_OR_KEYWORD 3566 for signature_func in (inspect.signature, inspect.Signature.from_callable): 3567 with self.subTest(signature_func = signature_func): 3568 self.assertEqual( 3569 signature_func(isa.MyClass), 3570 sig( 3571 parameters=( 3572 par('a', PORK), 3573 par('b', PORK), 3574 ))) 3575 self.assertEqual( 3576 signature_func(isa.function), 3577 sig( 3578 return_annotation='MyClass', 3579 parameters=( 3580 par('a', PORK, annotation='int'), 3581 par('b', PORK, annotation='str'), 3582 ))) 3583 self.assertEqual( 3584 signature_func(isa.function2), 3585 sig( 3586 return_annotation='MyClass', 3587 parameters=( 3588 par('a', PORK, annotation='int'), 3589 par('b', PORK, annotation="'str'"), 3590 par('c', PORK, annotation="MyClass"), 3591 ))) 3592 self.assertEqual( 3593 signature_func(isa.function3), 3594 sig( 3595 parameters=( 3596 par('a', PORK, annotation="'int'"), 3597 par('b', PORK, annotation="'str'"), 3598 par('c', PORK, annotation="'MyClass'"), 3599 ))) 3600 3601 self.assertEqual(signature_func(isa.UnannotatedClass), sig()) 3602 self.assertEqual(signature_func(isa.unannotated_function), 3603 sig( 3604 parameters=( 3605 par('a', PORK), 3606 par('b', PORK), 3607 par('c', PORK), 3608 ))) 3609 3610 self.assertEqual( 3611 signature_func(isa.MyClass, eval_str=True), 3612 sig( 3613 parameters=( 3614 par('a', PORK), 3615 par('b', PORK), 3616 ))) 3617 self.assertEqual( 3618 signature_func(isa.function, eval_str=True), 3619 sig( 3620 return_annotation=isa.MyClass, 3621 parameters=( 3622 par('a', PORK, annotation=int), 3623 par('b', PORK, annotation=str), 3624 ))) 3625 self.assertEqual( 3626 signature_func(isa.function2, eval_str=True), 3627 sig( 3628 return_annotation=isa.MyClass, 3629 parameters=( 3630 par('a', PORK, annotation=int), 3631 par('b', PORK, annotation='str'), 3632 par('c', PORK, annotation=isa.MyClass), 3633 ))) 3634 self.assertEqual( 3635 signature_func(isa.function3, eval_str=True), 3636 sig( 3637 parameters=( 3638 par('a', PORK, annotation='int'), 3639 par('b', PORK, annotation='str'), 3640 par('c', PORK, annotation='MyClass'), 3641 ))) 3642 3643 globalns = {'int': float, 'str': complex} 3644 localns = {'str': tuple, 'MyClass': dict} 3645 with self.assertRaises(NameError): 3646 signature_func(isa.function, eval_str=True, globals=globalns) 3647 3648 self.assertEqual( 3649 signature_func(isa.function, eval_str=True, locals=localns), 3650 sig( 3651 return_annotation=dict, 3652 parameters=( 3653 par('a', PORK, annotation=int), 3654 par('b', PORK, annotation=tuple), 3655 ))) 3656 3657 self.assertEqual( 3658 signature_func(isa.function, eval_str=True, globals=globalns, locals=localns), 3659 sig( 3660 return_annotation=dict, 3661 parameters=( 3662 par('a', PORK, annotation=float), 3663 par('b', PORK, annotation=tuple), 3664 ))) 3665 3666 def test_signature_none_annotation(self): 3667 class funclike: 3668 # Has to be callable, and have correct 3669 # __code__, __annotations__, __defaults__, __name__, 3670 # and __kwdefaults__ attributes 3671 3672 def __init__(self, func): 3673 self.__name__ = func.__name__ 3674 self.__code__ = func.__code__ 3675 self.__annotations__ = func.__annotations__ 3676 self.__defaults__ = func.__defaults__ 3677 self.__kwdefaults__ = func.__kwdefaults__ 3678 self.func = func 3679 3680 def __call__(self, *args, **kwargs): 3681 return self.func(*args, **kwargs) 3682 3683 def foo(): pass 3684 foo = funclike(foo) 3685 foo.__annotations__ = None 3686 for signature_func in (inspect.signature, inspect.Signature.from_callable): 3687 with self.subTest(signature_func = signature_func): 3688 self.assertEqual(signature_func(foo), inspect.Signature()) 3689 self.assertEqual(inspect.get_annotations(foo), {}) 3690 3691 def test_signature_on_derived_classes(self): 3692 # gh-105080: Make sure that signatures are consistent on derived classes 3693 3694 class B: 3695 def __new__(self, *args, **kwargs): 3696 return super().__new__(self) 3697 def __init__(self, value): 3698 self.value = value 3699 3700 class D1(B): 3701 def __init__(self, value): 3702 super().__init__(value) 3703 3704 class D2(D1): 3705 pass 3706 3707 self.assertEqual(inspect.signature(D2), inspect.signature(D1)) 3708 3709 3710class TestParameterObject(unittest.TestCase): 3711 def test_signature_parameter_kinds(self): 3712 P = inspect.Parameter 3713 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \ 3714 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD) 3715 3716 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY') 3717 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY)) 3718 3719 def test_signature_parameter_object(self): 3720 p = inspect.Parameter('foo', default=10, 3721 kind=inspect.Parameter.POSITIONAL_ONLY) 3722 self.assertEqual(p.name, 'foo') 3723 self.assertEqual(p.default, 10) 3724 self.assertIs(p.annotation, p.empty) 3725 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY) 3726 3727 with self.assertRaisesRegex(ValueError, "value '123' is " 3728 "not a valid Parameter.kind"): 3729 inspect.Parameter('foo', default=10, kind='123') 3730 3731 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'): 3732 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD) 3733 3734 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'): 3735 inspect.Parameter('from', kind=inspect.Parameter.VAR_KEYWORD) 3736 3737 with self.assertRaisesRegex(TypeError, 'name must be a str'): 3738 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD) 3739 3740 with self.assertRaisesRegex(ValueError, 3741 'is not a valid parameter name'): 3742 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD) 3743 3744 with self.assertRaisesRegex(ValueError, 3745 'is not a valid parameter name'): 3746 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD) 3747 3748 with self.assertRaisesRegex(ValueError, 'cannot have default values'): 3749 inspect.Parameter('a', default=42, 3750 kind=inspect.Parameter.VAR_KEYWORD) 3751 3752 with self.assertRaisesRegex(ValueError, 'cannot have default values'): 3753 inspect.Parameter('a', default=42, 3754 kind=inspect.Parameter.VAR_POSITIONAL) 3755 3756 p = inspect.Parameter('a', default=42, 3757 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD) 3758 with self.assertRaisesRegex(ValueError, 'cannot have default values'): 3759 p.replace(kind=inspect.Parameter.VAR_POSITIONAL) 3760 3761 self.assertTrue(repr(p).startswith('<Parameter')) 3762 self.assertTrue('"a=42"' in repr(p)) 3763 3764 def test_signature_parameter_hashable(self): 3765 P = inspect.Parameter 3766 foo = P('foo', kind=P.POSITIONAL_ONLY) 3767 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY))) 3768 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY, 3769 default=42))) 3770 self.assertNotEqual(hash(foo), 3771 hash(foo.replace(kind=P.VAR_POSITIONAL))) 3772 3773 def test_signature_parameter_equality(self): 3774 P = inspect.Parameter 3775 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY) 3776 3777 self.assertTrue(p == p) 3778 self.assertFalse(p != p) 3779 self.assertFalse(p == 42) 3780 self.assertTrue(p != 42) 3781 self.assertTrue(p == ALWAYS_EQ) 3782 self.assertFalse(p != ALWAYS_EQ) 3783 3784 self.assertTrue(p == P('foo', default=42, 3785 kind=inspect.Parameter.KEYWORD_ONLY)) 3786 self.assertFalse(p != P('foo', default=42, 3787 kind=inspect.Parameter.KEYWORD_ONLY)) 3788 3789 def test_signature_parameter_replace(self): 3790 p = inspect.Parameter('foo', default=42, 3791 kind=inspect.Parameter.KEYWORD_ONLY) 3792 3793 self.assertIsNot(p, p.replace()) 3794 self.assertEqual(p, p.replace()) 3795 3796 p2 = p.replace(annotation=1) 3797 self.assertEqual(p2.annotation, 1) 3798 p2 = p2.replace(annotation=p2.empty) 3799 self.assertEqual(p, p2) 3800 3801 p2 = p2.replace(name='bar') 3802 self.assertEqual(p2.name, 'bar') 3803 self.assertNotEqual(p2, p) 3804 3805 with self.assertRaisesRegex(ValueError, 3806 'name is a required attribute'): 3807 p2 = p2.replace(name=p2.empty) 3808 3809 p2 = p2.replace(name='foo', default=None) 3810 self.assertIs(p2.default, None) 3811 self.assertNotEqual(p2, p) 3812 3813 p2 = p2.replace(name='foo', default=p2.empty) 3814 self.assertIs(p2.default, p2.empty) 3815 3816 3817 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD) 3818 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD) 3819 self.assertNotEqual(p2, p) 3820 3821 with self.assertRaisesRegex(ValueError, 3822 "value <class 'inspect._empty'> " 3823 "is not a valid Parameter.kind"): 3824 p2 = p2.replace(kind=p2.empty) 3825 3826 p2 = p2.replace(kind=p2.KEYWORD_ONLY) 3827 self.assertEqual(p2, p) 3828 3829 def test_signature_parameter_positional_only(self): 3830 with self.assertRaisesRegex(TypeError, 'name must be a str'): 3831 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY) 3832 3833 @cpython_only 3834 def test_signature_parameter_implicit(self): 3835 with self.assertRaisesRegex(ValueError, 3836 'implicit arguments must be passed as ' 3837 'positional or keyword arguments, ' 3838 'not positional-only'): 3839 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY) 3840 3841 param = inspect.Parameter( 3842 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD) 3843 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY) 3844 self.assertEqual(param.name, 'implicit0') 3845 3846 def test_signature_parameter_immutability(self): 3847 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY) 3848 3849 with self.assertRaises(AttributeError): 3850 p.foo = 'bar' 3851 3852 with self.assertRaises(AttributeError): 3853 p.kind = 123 3854 3855 3856class TestSignatureBind(unittest.TestCase): 3857 @staticmethod 3858 def call(func, *args, **kwargs): 3859 sig = inspect.signature(func) 3860 ba = sig.bind(*args, **kwargs) 3861 return func(*ba.args, **ba.kwargs) 3862 3863 def test_signature_bind_empty(self): 3864 def test(): 3865 return 42 3866 3867 self.assertEqual(self.call(test), 42) 3868 with self.assertRaisesRegex(TypeError, 'too many positional arguments'): 3869 self.call(test, 1) 3870 with self.assertRaisesRegex(TypeError, 'too many positional arguments'): 3871 self.call(test, 1, spam=10) 3872 with self.assertRaisesRegex( 3873 TypeError, "got an unexpected keyword argument 'spam'"): 3874 3875 self.call(test, spam=1) 3876 3877 def test_signature_bind_var(self): 3878 def test(*args, **kwargs): 3879 return args, kwargs 3880 3881 self.assertEqual(self.call(test), ((), {})) 3882 self.assertEqual(self.call(test, 1), ((1,), {})) 3883 self.assertEqual(self.call(test, 1, 2), ((1, 2), {})) 3884 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'})) 3885 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'})) 3886 self.assertEqual(self.call(test, args=10), ((), {'args': 10})) 3887 self.assertEqual(self.call(test, 1, 2, foo='bar'), 3888 ((1, 2), {'foo': 'bar'})) 3889 3890 def test_signature_bind_just_args(self): 3891 def test(a, b, c): 3892 return a, b, c 3893 3894 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3)) 3895 3896 with self.assertRaisesRegex(TypeError, 'too many positional arguments'): 3897 self.call(test, 1, 2, 3, 4) 3898 3899 with self.assertRaisesRegex(TypeError, 3900 "missing a required argument: 'b'"): 3901 self.call(test, 1) 3902 3903 with self.assertRaisesRegex(TypeError, 3904 "missing a required argument: 'a'"): 3905 self.call(test) 3906 3907 def test(a, b, c=10): 3908 return a, b, c 3909 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3)) 3910 self.assertEqual(self.call(test, 1, 2), (1, 2, 10)) 3911 3912 def test(a=1, b=2, c=3): 3913 return a, b, c 3914 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13)) 3915 self.assertEqual(self.call(test, a=10), (10, 2, 3)) 3916 self.assertEqual(self.call(test, b=10), (1, 10, 3)) 3917 3918 def test_signature_bind_varargs_order(self): 3919 def test(*args): 3920 return args 3921 3922 self.assertEqual(self.call(test), ()) 3923 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3)) 3924 3925 def test_signature_bind_args_and_varargs(self): 3926 def test(a, b, c=3, *args): 3927 return a, b, c, args 3928 3929 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5))) 3930 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ())) 3931 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ())) 3932 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ())) 3933 3934 with self.assertRaisesRegex(TypeError, 3935 "multiple values for argument 'c'"): 3936 self.call(test, 1, 2, 3, c=4) 3937 3938 def test_signature_bind_just_kwargs(self): 3939 def test(**kwargs): 3940 return kwargs 3941 3942 self.assertEqual(self.call(test), {}) 3943 self.assertEqual(self.call(test, foo='bar', spam='ham'), 3944 {'foo': 'bar', 'spam': 'ham'}) 3945 3946 def test_signature_bind_args_and_kwargs(self): 3947 def test(a, b, c=3, **kwargs): 3948 return a, b, c, kwargs 3949 3950 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {})) 3951 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'), 3952 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'})) 3953 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'), 3954 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'})) 3955 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'), 3956 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'})) 3957 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'), 3958 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'})) 3959 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'), 3960 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'})) 3961 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'), 3962 (1, 2, 4, {'foo': 'bar'})) 3963 self.assertEqual(self.call(test, c=5, a=4, b=3), 3964 (4, 3, 5, {})) 3965 3966 def test_signature_bind_kwonly(self): 3967 def test(*, foo): 3968 return foo 3969 with self.assertRaisesRegex(TypeError, 3970 'too many positional arguments'): 3971 self.call(test, 1) 3972 self.assertEqual(self.call(test, foo=1), 1) 3973 3974 def test(a, *, foo=1, bar): 3975 return foo 3976 with self.assertRaisesRegex(TypeError, 3977 "missing a required argument: 'bar'"): 3978 self.call(test, 1) 3979 3980 def test(foo, *, bar): 3981 return foo, bar 3982 self.assertEqual(self.call(test, 1, bar=2), (1, 2)) 3983 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2)) 3984 3985 with self.assertRaisesRegex( 3986 TypeError, "got an unexpected keyword argument 'spam'"): 3987 3988 self.call(test, bar=2, foo=1, spam=10) 3989 3990 with self.assertRaisesRegex(TypeError, 3991 'too many positional arguments'): 3992 self.call(test, 1, 2) 3993 3994 with self.assertRaisesRegex(TypeError, 3995 'too many positional arguments'): 3996 self.call(test, 1, 2, bar=2) 3997 3998 with self.assertRaisesRegex( 3999 TypeError, "got an unexpected keyword argument 'spam'"): 4000 4001 self.call(test, 1, bar=2, spam='ham') 4002 4003 with self.assertRaisesRegex(TypeError, 4004 "missing a required argument: 'bar'"): 4005 self.call(test, 1) 4006 4007 def test(foo, *, bar, **bin): 4008 return foo, bar, bin 4009 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {})) 4010 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {})) 4011 self.assertEqual(self.call(test, 1, bar=2, spam='ham'), 4012 (1, 2, {'spam': 'ham'})) 4013 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2), 4014 (1, 2, {'spam': 'ham'})) 4015 with self.assertRaisesRegex(TypeError, 4016 "missing a required argument: 'foo'"): 4017 self.call(test, spam='ham', bar=2) 4018 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10), 4019 (1, 2, {'bin': 1, 'spam': 10})) 4020 4021 def test_signature_bind_arguments(self): 4022 def test(a, *args, b, z=100, **kwargs): 4023 pass 4024 sig = inspect.signature(test) 4025 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60) 4026 # we won't have 'z' argument in the bound arguments object, as we didn't 4027 # pass it to the 'bind' 4028 self.assertEqual(tuple(ba.arguments.items()), 4029 (('a', 10), ('args', (20,)), ('b', 30), 4030 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60}))) 4031 self.assertEqual(ba.kwargs, 4032 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60}) 4033 self.assertEqual(ba.args, (10, 20)) 4034 4035 def test_signature_bind_positional_only(self): 4036 def test(a_po, b_po, c_po=3, /, foo=42, *, bar=50, **kwargs): 4037 return a_po, b_po, c_po, foo, bar, kwargs 4038 4039 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6), 4040 (1, 2, 4, 5, 6, {})) 4041 4042 self.assertEqual(self.call(test, 1, 2), 4043 (1, 2, 3, 42, 50, {})) 4044 4045 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5), 4046 (1, 2, 3, 4, 5, {})) 4047 4048 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"): 4049 self.call(test, 1, 2, foo=4, bar=5, c_po=10) 4050 4051 with self.assertRaisesRegex(TypeError, "parameter is positional only"): 4052 self.call(test, 1, 2, c_po=4) 4053 4054 with self.assertRaisesRegex(TypeError, "parameter is positional only"): 4055 self.call(test, a_po=1, b_po=2) 4056 4057 def test_signature_bind_with_self_arg(self): 4058 # Issue #17071: one of the parameters is named "self 4059 def test(a, self, b): 4060 pass 4061 sig = inspect.signature(test) 4062 ba = sig.bind(1, 2, 3) 4063 self.assertEqual(ba.args, (1, 2, 3)) 4064 ba = sig.bind(1, self=2, b=3) 4065 self.assertEqual(ba.args, (1, 2, 3)) 4066 4067 def test_signature_bind_vararg_name(self): 4068 def test(a, *args): 4069 return a, args 4070 sig = inspect.signature(test) 4071 4072 with self.assertRaisesRegex( 4073 TypeError, "got an unexpected keyword argument 'args'"): 4074 4075 sig.bind(a=0, args=1) 4076 4077 def test(*args, **kwargs): 4078 return args, kwargs 4079 self.assertEqual(self.call(test, args=1), ((), {'args': 1})) 4080 4081 sig = inspect.signature(test) 4082 ba = sig.bind(args=1) 4083 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}}) 4084 4085 @cpython_only 4086 def test_signature_bind_implicit_arg(self): 4087 # Issue #19611: getcallargs should work with set comprehensions 4088 def make_set(): 4089 return {z * z for z in range(5)} 4090 setcomp_code = make_set.__code__.co_consts[1] 4091 setcomp_func = types.FunctionType(setcomp_code, {}) 4092 4093 iterator = iter(range(5)) 4094 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16}) 4095 4096 def test_signature_bind_posonly_kwargs(self): 4097 def foo(bar, /, **kwargs): 4098 return bar, kwargs.get(bar) 4099 4100 sig = inspect.signature(foo) 4101 result = sig.bind("pos-only", bar="keyword") 4102 4103 self.assertEqual(result.kwargs, {"bar": "keyword"}) 4104 self.assertIn(("bar", "pos-only"), result.arguments.items()) 4105 4106 4107class TestBoundArguments(unittest.TestCase): 4108 def test_signature_bound_arguments_unhashable(self): 4109 def foo(a): pass 4110 ba = inspect.signature(foo).bind(1) 4111 4112 with self.assertRaisesRegex(TypeError, 'unhashable type'): 4113 hash(ba) 4114 4115 def test_signature_bound_arguments_equality(self): 4116 def foo(a): pass 4117 ba = inspect.signature(foo).bind(1) 4118 self.assertTrue(ba == ba) 4119 self.assertFalse(ba != ba) 4120 self.assertTrue(ba == ALWAYS_EQ) 4121 self.assertFalse(ba != ALWAYS_EQ) 4122 4123 ba2 = inspect.signature(foo).bind(1) 4124 self.assertTrue(ba == ba2) 4125 self.assertFalse(ba != ba2) 4126 4127 ba3 = inspect.signature(foo).bind(2) 4128 self.assertFalse(ba == ba3) 4129 self.assertTrue(ba != ba3) 4130 ba3.arguments['a'] = 1 4131 self.assertTrue(ba == ba3) 4132 self.assertFalse(ba != ba3) 4133 4134 def bar(b): pass 4135 ba4 = inspect.signature(bar).bind(1) 4136 self.assertFalse(ba == ba4) 4137 self.assertTrue(ba != ba4) 4138 4139 def foo(*, a, b): pass 4140 sig = inspect.signature(foo) 4141 ba1 = sig.bind(a=1, b=2) 4142 ba2 = sig.bind(b=2, a=1) 4143 self.assertTrue(ba1 == ba2) 4144 self.assertFalse(ba1 != ba2) 4145 4146 def test_signature_bound_arguments_pickle(self): 4147 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass 4148 sig = inspect.signature(foo) 4149 ba = sig.bind(20, 30, z={}) 4150 4151 for ver in range(pickle.HIGHEST_PROTOCOL + 1): 4152 with self.subTest(pickle_ver=ver): 4153 ba_pickled = pickle.loads(pickle.dumps(ba, ver)) 4154 self.assertEqual(ba, ba_pickled) 4155 4156 def test_signature_bound_arguments_repr(self): 4157 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass 4158 sig = inspect.signature(foo) 4159 ba = sig.bind(20, 30, z={}) 4160 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>') 4161 4162 def test_signature_bound_arguments_apply_defaults(self): 4163 def foo(a, b=1, *args, c:1={}, **kw): pass 4164 sig = inspect.signature(foo) 4165 4166 ba = sig.bind(20) 4167 ba.apply_defaults() 4168 self.assertEqual( 4169 list(ba.arguments.items()), 4170 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})]) 4171 4172 # Make sure that we preserve the order: 4173 # i.e. 'c' should be *before* 'kw'. 4174 ba = sig.bind(10, 20, 30, d=1) 4175 ba.apply_defaults() 4176 self.assertEqual( 4177 list(ba.arguments.items()), 4178 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})]) 4179 4180 # Make sure that BoundArguments produced by bind_partial() 4181 # are supported. 4182 def foo(a, b): pass 4183 sig = inspect.signature(foo) 4184 ba = sig.bind_partial(20) 4185 ba.apply_defaults() 4186 self.assertEqual( 4187 list(ba.arguments.items()), 4188 [('a', 20)]) 4189 4190 # Test no args 4191 def foo(): pass 4192 sig = inspect.signature(foo) 4193 ba = sig.bind() 4194 ba.apply_defaults() 4195 self.assertEqual(list(ba.arguments.items()), []) 4196 4197 # Make sure a no-args binding still acquires proper defaults. 4198 def foo(a='spam'): pass 4199 sig = inspect.signature(foo) 4200 ba = sig.bind() 4201 ba.apply_defaults() 4202 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')]) 4203 4204 def test_signature_bound_arguments_arguments_type(self): 4205 def foo(a): pass 4206 ba = inspect.signature(foo).bind(1) 4207 self.assertIs(type(ba.arguments), dict) 4208 4209class TestSignaturePrivateHelpers(unittest.TestCase): 4210 def _strip_non_python_syntax(self, input, 4211 clean_signature, self_parameter, last_positional_only): 4212 computed_clean_signature, \ 4213 computed_self_parameter, \ 4214 computed_last_positional_only = \ 4215 inspect._signature_strip_non_python_syntax(input) 4216 self.assertEqual(computed_clean_signature, clean_signature) 4217 self.assertEqual(computed_self_parameter, self_parameter) 4218 self.assertEqual(computed_last_positional_only, last_positional_only) 4219 4220 def test_signature_strip_non_python_syntax(self): 4221 self._strip_non_python_syntax( 4222 "($module, /, path, mode, *, dir_fd=None, " + 4223 "effective_ids=False,\n follow_symlinks=True)", 4224 "(module, path, mode, *, dir_fd=None, " + 4225 "effective_ids=False, follow_symlinks=True)", 4226 0, 4227 0) 4228 4229 self._strip_non_python_syntax( 4230 "($module, word, salt, /)", 4231 "(module, word, salt)", 4232 0, 4233 2) 4234 4235 self._strip_non_python_syntax( 4236 "(x, y=None, z=None, /)", 4237 "(x, y=None, z=None)", 4238 None, 4239 2) 4240 4241 self._strip_non_python_syntax( 4242 "(x, y=None, z=None)", 4243 "(x, y=None, z=None)", 4244 None, 4245 None) 4246 4247 self._strip_non_python_syntax( 4248 "(x,\n y=None,\n z = None )", 4249 "(x, y=None, z=None)", 4250 None, 4251 None) 4252 4253 self._strip_non_python_syntax( 4254 "", 4255 "", 4256 None, 4257 None) 4258 4259 self._strip_non_python_syntax( 4260 None, 4261 None, 4262 None, 4263 None) 4264 4265class TestSignatureDefinitions(unittest.TestCase): 4266 # This test case provides a home for checking that particular APIs 4267 # have signatures available for introspection 4268 4269 @cpython_only 4270 @unittest.skipIf(MISSING_C_DOCSTRINGS, 4271 "Signature information for builtins requires docstrings") 4272 def test_builtins_have_signatures(self): 4273 # This checks all builtin callables in CPython have signatures 4274 # A few have signatures Signature can't yet handle, so we skip those 4275 # since they will have to wait until PEP 457 adds the required 4276 # introspection support to the inspect module 4277 # Some others also haven't been converted yet for various other 4278 # reasons, so we also skip those for the time being, but design 4279 # the test to fail in order to indicate when it needs to be 4280 # updated. 4281 no_signature = set() 4282 # These need PEP 457 groups 4283 needs_groups = {"range", "slice", "dir", "getattr", 4284 "next", "iter", "vars"} 4285 no_signature |= needs_groups 4286 # These have unrepresentable parameter default values of NULL 4287 needs_null = {"anext"} 4288 no_signature |= needs_null 4289 # These need PEP 457 groups or a signature change to accept None 4290 needs_semantic_update = {"round"} 4291 no_signature |= needs_semantic_update 4292 # These need *args support in Argument Clinic 4293 needs_varargs = {"breakpoint", "min", "max", "print", 4294 "__build_class__"} 4295 no_signature |= needs_varargs 4296 # These simply weren't covered in the initial AC conversion 4297 # for builtin callables 4298 not_converted_yet = {"open", "__import__"} 4299 no_signature |= not_converted_yet 4300 # These builtin types are expected to provide introspection info 4301 types_with_signatures = set() 4302 # Check the signatures we expect to be there 4303 ns = vars(builtins) 4304 for name, obj in sorted(ns.items()): 4305 if not callable(obj): 4306 continue 4307 # The builtin types haven't been converted to AC yet 4308 if isinstance(obj, type) and (name not in types_with_signatures): 4309 # Note that this also skips all the exception types 4310 no_signature.add(name) 4311 if (name in no_signature): 4312 # Not yet converted 4313 continue 4314 with self.subTest(builtin=name): 4315 self.assertIsNotNone(inspect.signature(obj)) 4316 # Check callables that haven't been converted don't claim a signature 4317 # This ensures this test will start failing as more signatures are 4318 # added, so the affected items can be moved into the scope of the 4319 # regression test above 4320 for name in no_signature: 4321 with self.subTest(builtin=name): 4322 self.assertIsNone(obj.__text_signature__) 4323 4324 def test_python_function_override_signature(self): 4325 def func(*args, **kwargs): 4326 pass 4327 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)' 4328 sig = inspect.signature(func) 4329 self.assertIsNotNone(sig) 4330 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)') 4331 4332 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)' 4333 sig = inspect.signature(func) 4334 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)') 4335 4336 func.__text_signature__ = '(self, a=1+2, b=4-3, c=1 | 3 | 16)' 4337 sig = inspect.signature(func) 4338 self.assertEqual(str(sig), '(self, a=3, b=1, c=19)') 4339 4340 func.__text_signature__ = '(self, a=1,\nb=2,\n\n\n c=3)' 4341 sig = inspect.signature(func) 4342 self.assertEqual(str(sig), '(self, a=1, b=2, c=3)') 4343 4344 func.__text_signature__ = '(self, x=does_not_exist)' 4345 with self.assertRaises(ValueError): 4346 inspect.signature(func) 4347 func.__text_signature__ = '(self, x=sys, y=inspect)' 4348 with self.assertRaises(ValueError): 4349 inspect.signature(func) 4350 func.__text_signature__ = '(self, 123)' 4351 with self.assertRaises(ValueError): 4352 inspect.signature(func) 4353 4354 def test_base_class_have_text_signature(self): 4355 # see issue 43118 4356 from test.ann_module7 import BufferedReader 4357 class MyBufferedReader(BufferedReader): 4358 """buffer reader class.""" 4359 4360 text_signature = BufferedReader.__text_signature__ 4361 self.assertEqual(text_signature, '(raw, buffer_size=DEFAULT_BUFFER_SIZE)') 4362 sig = inspect.signature(MyBufferedReader) 4363 self.assertEqual(str(sig), '(raw, buffer_size=8192)') 4364 4365 4366class NTimesUnwrappable: 4367 def __init__(self, n): 4368 self.n = n 4369 self._next = None 4370 4371 @property 4372 def __wrapped__(self): 4373 if self.n <= 0: 4374 raise Exception("Unwrapped too many times") 4375 if self._next is None: 4376 self._next = NTimesUnwrappable(self.n - 1) 4377 return self._next 4378 4379class TestUnwrap(unittest.TestCase): 4380 4381 def test_unwrap_one(self): 4382 def func(a, b): 4383 return a + b 4384 wrapper = functools.lru_cache(maxsize=20)(func) 4385 self.assertIs(inspect.unwrap(wrapper), func) 4386 4387 def test_unwrap_several(self): 4388 def func(a, b): 4389 return a + b 4390 wrapper = func 4391 for __ in range(10): 4392 @functools.wraps(wrapper) 4393 def wrapper(): 4394 pass 4395 self.assertIsNot(wrapper.__wrapped__, func) 4396 self.assertIs(inspect.unwrap(wrapper), func) 4397 4398 def test_stop(self): 4399 def func1(a, b): 4400 return a + b 4401 @functools.wraps(func1) 4402 def func2(): 4403 pass 4404 @functools.wraps(func2) 4405 def wrapper(): 4406 pass 4407 func2.stop_here = 1 4408 unwrapped = inspect.unwrap(wrapper, 4409 stop=(lambda f: hasattr(f, "stop_here"))) 4410 self.assertIs(unwrapped, func2) 4411 4412 def test_cycle(self): 4413 def func1(): pass 4414 func1.__wrapped__ = func1 4415 with self.assertRaisesRegex(ValueError, 'wrapper loop'): 4416 inspect.unwrap(func1) 4417 4418 def func2(): pass 4419 func2.__wrapped__ = func1 4420 func1.__wrapped__ = func2 4421 with self.assertRaisesRegex(ValueError, 'wrapper loop'): 4422 inspect.unwrap(func1) 4423 with self.assertRaisesRegex(ValueError, 'wrapper loop'): 4424 inspect.unwrap(func2) 4425 4426 def test_unhashable(self): 4427 def func(): pass 4428 func.__wrapped__ = None 4429 class C: 4430 __hash__ = None 4431 __wrapped__ = func 4432 self.assertIsNone(inspect.unwrap(C())) 4433 4434 def test_recursion_limit(self): 4435 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1) 4436 with self.assertRaisesRegex(ValueError, 'wrapper loop'): 4437 inspect.unwrap(obj) 4438 4439class TestMain(unittest.TestCase): 4440 def test_only_source(self): 4441 module = importlib.import_module('unittest') 4442 rc, out, err = assert_python_ok('-m', 'inspect', 4443 'unittest') 4444 lines = out.decode().splitlines() 4445 # ignore the final newline 4446 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines()) 4447 self.assertEqual(err, b'') 4448 4449 def test_custom_getattr(self): 4450 def foo(): 4451 pass 4452 foo.__signature__ = 42 4453 with self.assertRaises(TypeError): 4454 inspect.signature(foo) 4455 4456 @unittest.skipIf(ThreadPoolExecutor is None, 4457 'threads required to test __qualname__ for source files') 4458 def test_qualname_source(self): 4459 rc, out, err = assert_python_ok('-m', 'inspect', 4460 'concurrent.futures:ThreadPoolExecutor') 4461 lines = out.decode().splitlines() 4462 # ignore the final newline 4463 self.assertEqual(lines[:-1], 4464 inspect.getsource(ThreadPoolExecutor).splitlines()) 4465 self.assertEqual(err, b'') 4466 4467 def test_builtins(self): 4468 _, out, err = assert_python_failure('-m', 'inspect', 4469 'sys') 4470 lines = err.decode().splitlines() 4471 self.assertEqual(lines, ["Can't get info for builtin modules."]) 4472 4473 def test_details(self): 4474 module = importlib.import_module('unittest') 4475 args = support.optim_args_from_interpreter_flags() 4476 rc, out, err = assert_python_ok(*args, '-m', 'inspect', 4477 'unittest', '--details') 4478 output = out.decode() 4479 # Just a quick sanity check on the output 4480 self.assertIn(module.__name__, output) 4481 self.assertIn(module.__file__, output) 4482 self.assertIn(module.__cached__, output) 4483 self.assertEqual(err, b'') 4484 4485 4486class TestReload(unittest.TestCase): 4487 4488 src_before = textwrap.dedent("""\ 4489def foo(): 4490 print("Bla") 4491 """) 4492 4493 src_after = textwrap.dedent("""\ 4494def foo(): 4495 print("Oh no!") 4496 """) 4497 4498 def assertInspectEqual(self, path, source): 4499 inspected_src = inspect.getsource(source) 4500 with open(path, encoding='utf-8') as src: 4501 self.assertEqual( 4502 src.read().splitlines(True), 4503 inspected_src.splitlines(True) 4504 ) 4505 4506 def test_getsource_reload(self): 4507 # see issue 1218234 4508 with _ready_to_import('reload_bug', self.src_before) as (name, path): 4509 module = importlib.import_module(name) 4510 self.assertInspectEqual(path, module) 4511 with open(path, 'w', encoding='utf-8') as src: 4512 src.write(self.src_after) 4513 self.assertInspectEqual(path, module) 4514 4515 4516if __name__ == "__main__": 4517 unittest.main() 4518