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