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