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