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