1import asyncio 2import builtins 3import collections 4import copy 5import datetime 6import functools 7import gc 8import importlib 9import inspect 10import io 11import linecache 12import os 13import dis 14from os.path import normcase 15import _pickle 16import pickle 17import shutil 18import stat 19import sys 20import subprocess 21import time 22import types 23import tempfile 24import textwrap 25from typing import Unpack 26import unicodedata 27import unittest 28import unittest.mock 29import warnings 30import weakref 31 32 33try: 34 from concurrent.futures import ThreadPoolExecutor 35except ImportError: 36 ThreadPoolExecutor = None 37 38from test.support import cpython_only, import_helper, suppress_immortalization 39from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ 40from test.support.import_helper import DirsOnSysPath, ready_to_import 41from test.support.os_helper import TESTFN, temp_cwd 42from test.support.script_helper import assert_python_ok, assert_python_failure, kill_python 43from test.support import has_subprocess_support, SuppressCrashReport 44from test import support 45 46from test.test_inspect import inspect_fodder as mod 47from test.test_inspect import inspect_fodder2 as mod2 48from test.test_inspect import inspect_stock_annotations 49from test.test_inspect import inspect_stringized_annotations 50from test.test_inspect import inspect_stringized_annotations_2 51from test.test_inspect import inspect_stringized_annotations_pep695 52 53 54# Functions tested in this suite: 55# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode, 56# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers, 57# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource, 58# getclasstree, getargvalues, formatargvalues, currentframe, 59# stack, trace, ismethoddescriptor, isdatadescriptor, ismethodwrapper 60 61# NOTE: There are some additional tests relating to interaction with 62# zipimport in the test_zipimport_support test module. 63 64modfile = mod.__file__ 65if modfile.endswith(('c', 'o')): 66 modfile = modfile[:-1] 67 68# Normalize file names: on Windows, the case of file names of compiled 69# modules depends on the path used to start the python executable. 70modfile = normcase(modfile) 71 72def revise(filename, *args): 73 return (normcase(filename),) + args 74 75git = mod.StupidGit() 76 77 78def tearDownModule(): 79 if support.has_socket_support: 80 asyncio.set_event_loop_policy(None) 81 82 83def signatures_with_lexicographic_keyword_only_parameters(): 84 """ 85 Yields a whole bunch of functions with only keyword-only parameters, 86 where those parameters are always in lexicographically sorted order. 87 """ 88 parameters = ['a', 'bar', 'c', 'delta', 'ephraim', 'magical', 'yoyo', 'z'] 89 for i in range(1, 2**len(parameters)): 90 p = [] 91 bit = 1 92 for j in range(len(parameters)): 93 if i & (bit << j): 94 p.append(parameters[j]) 95 fn_text = "def foo(*, " + ", ".join(p) + "): pass" 96 symbols = {} 97 exec(fn_text, symbols, symbols) 98 yield symbols['foo'] 99 100 101def unsorted_keyword_only_parameters_fn(*, throw, out, the, baby, with_, 102 the_, bathwater): 103 pass 104 105unsorted_keyword_only_parameters = 'throw out the baby with_ the_ bathwater'.split() 106 107class IsTestBase(unittest.TestCase): 108 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode, 109 inspect.isframe, inspect.isfunction, inspect.ismethod, 110 inspect.ismodule, inspect.istraceback, 111 inspect.isgenerator, inspect.isgeneratorfunction, 112 inspect.iscoroutine, inspect.iscoroutinefunction, 113 inspect.isasyncgen, inspect.isasyncgenfunction, 114 inspect.ismethodwrapper]) 115 116 def istest(self, predicate, exp): 117 obj = eval(exp) 118 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp)) 119 120 for other in self.predicates - set([predicate]): 121 if (predicate == inspect.isgeneratorfunction or \ 122 predicate == inspect.isasyncgenfunction or \ 123 predicate == inspect.iscoroutinefunction) and \ 124 other == inspect.isfunction: 125 continue 126 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp)) 127 128 def test__all__(self): 129 support.check__all__(self, inspect, not_exported=("modulesbyfile",)) 130 131def generator_function_example(self): 132 for i in range(2): 133 yield i 134 135async def async_generator_function_example(self): 136 async for i in range(2): 137 yield i 138 139async def coroutine_function_example(self): 140 return 'spam' 141 142@types.coroutine 143def gen_coroutine_function_example(self): 144 yield 145 return 'spam' 146 147def meth_noargs(): pass 148def meth_o(object, /): pass 149def meth_self_noargs(self, /): pass 150def meth_self_o(self, object, /): pass 151def meth_type_noargs(type, /): pass 152def meth_type_o(type, object, /): pass 153 154 155class TestPredicates(IsTestBase): 156 157 def test_excluding_predicates(self): 158 global tb 159 self.istest(inspect.isbuiltin, 'sys.exit') 160 self.istest(inspect.isbuiltin, '[].append') 161 self.istest(inspect.iscode, 'mod.spam.__code__') 162 try: 163 1/0 164 except Exception as e: 165 tb = e.__traceback__ 166 self.istest(inspect.isframe, 'tb.tb_frame') 167 self.istest(inspect.istraceback, 'tb') 168 if hasattr(types, 'GetSetDescriptorType'): 169 self.istest(inspect.isgetsetdescriptor, 170 'type(tb.tb_frame).f_locals') 171 else: 172 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals)) 173 finally: 174 # Clear traceback and all the frames and local variables hanging to it. 175 tb = None 176 self.istest(inspect.isfunction, 'mod.spam') 177 self.istest(inspect.isfunction, 'mod.StupidGit.abuse') 178 self.istest(inspect.ismethod, 'git.argue') 179 self.istest(inspect.ismethod, 'mod.custom_method') 180 self.istest(inspect.ismodule, 'mod') 181 self.istest(inspect.ismethoddescriptor, 'int.__add__') 182 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory') 183 self.istest(inspect.isgenerator, '(x for x in range(2))') 184 self.istest(inspect.isgeneratorfunction, 'generator_function_example') 185 self.istest(inspect.isasyncgen, 186 'async_generator_function_example(1)') 187 self.istest(inspect.isasyncgenfunction, 188 'async_generator_function_example') 189 190 with warnings.catch_warnings(): 191 warnings.simplefilter("ignore") 192 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)') 193 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example') 194 195 if hasattr(types, 'MemberDescriptorType'): 196 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days') 197 else: 198 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days)) 199 self.istest(inspect.ismethodwrapper, "object().__str__") 200 self.istest(inspect.ismethodwrapper, "object().__eq__") 201 self.istest(inspect.ismethodwrapper, "object().__repr__") 202 self.assertFalse(inspect.ismethodwrapper(type)) 203 self.assertFalse(inspect.ismethodwrapper(int)) 204 self.assertFalse(inspect.ismethodwrapper(type("AnyClass", (), {}))) 205 206 207 208 def test_iscoroutine(self): 209 async_gen_coro = async_generator_function_example(1) 210 gen_coro = gen_coroutine_function_example(1) 211 coro = coroutine_function_example(1) 212 213 class PMClass: 214 async_generator_partialmethod_example = functools.partialmethod( 215 async_generator_function_example) 216 coroutine_partialmethod_example = functools.partialmethod( 217 coroutine_function_example) 218 gen_coroutine_partialmethod_example = functools.partialmethod( 219 gen_coroutine_function_example) 220 221 # partialmethods on the class, bound to an instance 222 pm_instance = PMClass() 223 async_gen_coro_pmi = pm_instance.async_generator_partialmethod_example 224 gen_coro_pmi = pm_instance.gen_coroutine_partialmethod_example 225 coro_pmi = pm_instance.coroutine_partialmethod_example 226 227 # partialmethods on the class, unbound but accessed via the class 228 async_gen_coro_pmc = PMClass.async_generator_partialmethod_example 229 gen_coro_pmc = PMClass.gen_coroutine_partialmethod_example 230 coro_pmc = PMClass.coroutine_partialmethod_example 231 232 self.assertFalse( 233 inspect.iscoroutinefunction(gen_coroutine_function_example)) 234 self.assertFalse( 235 inspect.iscoroutinefunction( 236 functools.partial(functools.partial( 237 gen_coroutine_function_example)))) 238 self.assertFalse(inspect.iscoroutinefunction(gen_coro_pmi)) 239 self.assertFalse(inspect.iscoroutinefunction(gen_coro_pmc)) 240 self.assertFalse(inspect.iscoroutinefunction(inspect)) 241 self.assertFalse(inspect.iscoroutine(gen_coro)) 242 243 self.assertTrue( 244 inspect.isgeneratorfunction(gen_coroutine_function_example)) 245 self.assertTrue( 246 inspect.isgeneratorfunction( 247 functools.partial(functools.partial( 248 gen_coroutine_function_example)))) 249 self.assertTrue(inspect.isgeneratorfunction(gen_coro_pmi)) 250 self.assertTrue(inspect.isgeneratorfunction(gen_coro_pmc)) 251 self.assertTrue(inspect.isgenerator(gen_coro)) 252 253 async def _fn3(): 254 pass 255 256 @inspect.markcoroutinefunction 257 def fn3(): 258 return _fn3() 259 260 self.assertTrue(inspect.iscoroutinefunction(fn3)) 261 self.assertTrue( 262 inspect.iscoroutinefunction( 263 inspect.markcoroutinefunction(lambda: _fn3()) 264 ) 265 ) 266 267 class Cl: 268 async def __call__(self): 269 pass 270 271 self.assertFalse(inspect.iscoroutinefunction(Cl)) 272 # instances with async def __call__ are NOT recognised. 273 self.assertFalse(inspect.iscoroutinefunction(Cl())) 274 # unless explicitly marked. 275 self.assertTrue(inspect.iscoroutinefunction( 276 inspect.markcoroutinefunction(Cl()) 277 )) 278 279 class Cl2: 280 @inspect.markcoroutinefunction 281 def __call__(self): 282 pass 283 284 self.assertFalse(inspect.iscoroutinefunction(Cl2)) 285 # instances with marked __call__ are NOT recognised. 286 self.assertFalse(inspect.iscoroutinefunction(Cl2())) 287 # unless explicitly marked. 288 self.assertTrue(inspect.iscoroutinefunction( 289 inspect.markcoroutinefunction(Cl2()) 290 )) 291 292 class Cl3: 293 @inspect.markcoroutinefunction 294 @classmethod 295 def do_something_classy(cls): 296 pass 297 298 @inspect.markcoroutinefunction 299 @staticmethod 300 def do_something_static(): 301 pass 302 303 self.assertTrue(inspect.iscoroutinefunction(Cl3.do_something_classy)) 304 self.assertTrue(inspect.iscoroutinefunction(Cl3.do_something_static)) 305 306 self.assertFalse( 307 inspect.iscoroutinefunction(unittest.mock.Mock())) 308 self.assertTrue( 309 inspect.iscoroutinefunction(unittest.mock.AsyncMock())) 310 self.assertTrue( 311 inspect.iscoroutinefunction(coroutine_function_example)) 312 self.assertTrue( 313 inspect.iscoroutinefunction( 314 functools.partial(functools.partial( 315 coroutine_function_example)))) 316 self.assertTrue(inspect.iscoroutinefunction(coro_pmi)) 317 self.assertTrue(inspect.iscoroutinefunction(coro_pmc)) 318 self.assertTrue(inspect.iscoroutine(coro)) 319 320 self.assertFalse( 321 inspect.isgeneratorfunction(unittest.mock.Mock())) 322 self.assertFalse( 323 inspect.isgeneratorfunction(unittest.mock.AsyncMock())) 324 self.assertFalse( 325 inspect.isgeneratorfunction(coroutine_function_example)) 326 self.assertFalse( 327 inspect.isgeneratorfunction( 328 functools.partial(functools.partial( 329 coroutine_function_example)))) 330 self.assertFalse(inspect.isgeneratorfunction(coro_pmi)) 331 self.assertFalse(inspect.isgeneratorfunction(coro_pmc)) 332 self.assertFalse(inspect.isgenerator(coro)) 333 334 self.assertFalse( 335 inspect.isasyncgenfunction(unittest.mock.Mock())) 336 self.assertFalse( 337 inspect.isasyncgenfunction(unittest.mock.AsyncMock())) 338 self.assertFalse( 339 inspect.isasyncgenfunction(coroutine_function_example)) 340 self.assertTrue( 341 inspect.isasyncgenfunction(async_generator_function_example)) 342 self.assertTrue( 343 inspect.isasyncgenfunction( 344 functools.partial(functools.partial( 345 async_generator_function_example)))) 346 self.assertTrue(inspect.isasyncgenfunction(async_gen_coro_pmi)) 347 self.assertTrue(inspect.isasyncgenfunction(async_gen_coro_pmc)) 348 self.assertTrue(inspect.isasyncgen(async_gen_coro)) 349 350 coro.close(); gen_coro.close(); # silence warnings 351 352 def test_isawaitable(self): 353 def gen(): yield 354 self.assertFalse(inspect.isawaitable(gen())) 355 356 coro = coroutine_function_example(1) 357 gen_coro = gen_coroutine_function_example(1) 358 359 self.assertTrue(inspect.isawaitable(coro)) 360 self.assertTrue(inspect.isawaitable(gen_coro)) 361 362 class Future: 363 def __await__(): 364 pass 365 self.assertTrue(inspect.isawaitable(Future())) 366 self.assertFalse(inspect.isawaitable(Future)) 367 368 class NotFuture: pass 369 not_fut = NotFuture() 370 not_fut.__await__ = lambda: None 371 self.assertFalse(inspect.isawaitable(not_fut)) 372 373 coro.close(); gen_coro.close() # silence warnings 374 375 def test_isroutine(self): 376 # method 377 self.assertTrue(inspect.isroutine(git.argue)) 378 self.assertTrue(inspect.isroutine(mod.custom_method)) 379 self.assertTrue(inspect.isroutine([].count)) 380 # function 381 self.assertTrue(inspect.isroutine(mod.spam)) 382 self.assertTrue(inspect.isroutine(mod.StupidGit.abuse)) 383 # slot-wrapper 384 self.assertTrue(inspect.isroutine(object.__init__)) 385 self.assertTrue(inspect.isroutine(object.__str__)) 386 self.assertTrue(inspect.isroutine(object.__lt__)) 387 self.assertTrue(inspect.isroutine(int.__lt__)) 388 # method-wrapper 389 self.assertTrue(inspect.isroutine(object().__init__)) 390 self.assertTrue(inspect.isroutine(object().__str__)) 391 self.assertTrue(inspect.isroutine(object().__lt__)) 392 self.assertTrue(inspect.isroutine((42).__lt__)) 393 # method-descriptor 394 self.assertTrue(inspect.isroutine(str.join)) 395 self.assertTrue(inspect.isroutine(list.append)) 396 self.assertTrue(inspect.isroutine(''.join)) 397 self.assertTrue(inspect.isroutine([].append)) 398 # object 399 self.assertFalse(inspect.isroutine(object)) 400 self.assertFalse(inspect.isroutine(object())) 401 self.assertFalse(inspect.isroutine(str())) 402 # module 403 self.assertFalse(inspect.isroutine(mod)) 404 # type 405 self.assertFalse(inspect.isroutine(type)) 406 self.assertFalse(inspect.isroutine(int)) 407 self.assertFalse(inspect.isroutine(type('some_class', (), {}))) 408 # partial 409 self.assertFalse(inspect.isroutine(functools.partial(mod.spam))) 410 411 def test_isclass(self): 412 self.istest(inspect.isclass, 'mod.StupidGit') 413 self.assertTrue(inspect.isclass(list)) 414 415 class CustomGetattr(object): 416 def __getattr__(self, attr): 417 return None 418 self.assertFalse(inspect.isclass(CustomGetattr())) 419 420 def test_get_slot_members(self): 421 class C(object): 422 __slots__ = ("a", "b") 423 x = C() 424 x.a = 42 425 members = dict(inspect.getmembers(x)) 426 self.assertIn('a', members) 427 self.assertNotIn('b', members) 428 429 def test_isabstract(self): 430 from abc import ABCMeta, abstractmethod 431 432 class AbstractClassExample(metaclass=ABCMeta): 433 434 @abstractmethod 435 def foo(self): 436 pass 437 438 class ClassExample(AbstractClassExample): 439 def foo(self): 440 pass 441 442 a = ClassExample() 443 444 # Test general behaviour. 445 self.assertTrue(inspect.isabstract(AbstractClassExample)) 446 self.assertFalse(inspect.isabstract(ClassExample)) 447 self.assertFalse(inspect.isabstract(a)) 448 self.assertFalse(inspect.isabstract(int)) 449 self.assertFalse(inspect.isabstract(5)) 450 451 def test_isabstract_during_init_subclass(self): 452 from abc import ABCMeta, abstractmethod 453 isabstract_checks = [] 454 class AbstractChecker(metaclass=ABCMeta): 455 def __init_subclass__(cls): 456 isabstract_checks.append(inspect.isabstract(cls)) 457 class AbstractClassExample(AbstractChecker): 458 @abstractmethod 459 def foo(self): 460 pass 461 class ClassExample(AbstractClassExample): 462 def foo(self): 463 pass 464 self.assertEqual(isabstract_checks, [True, False]) 465 466 isabstract_checks.clear() 467 class AbstractChild(AbstractClassExample): 468 pass 469 class AbstractGrandchild(AbstractChild): 470 pass 471 class ConcreteGrandchild(ClassExample): 472 pass 473 self.assertEqual(isabstract_checks, [True, True, False]) 474 475 476class TestInterpreterStack(IsTestBase): 477 def __init__(self, *args, **kwargs): 478 unittest.TestCase.__init__(self, *args, **kwargs) 479 480 git.abuse(7, 8, 9) 481 482 def test_abuse_done(self): 483 self.istest(inspect.istraceback, 'git.ex.__traceback__') 484 self.istest(inspect.isframe, 'mod.fr') 485 486 def test_stack(self): 487 self.assertTrue(len(mod.st) >= 5) 488 frame1, frame2, frame3, frame4, *_ = mod.st 489 frameinfo = revise(*frame1[1:]) 490 self.assertEqual(frameinfo, 491 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0)) 492 self.assertEqual(frame1.positions, dis.Positions(16, 16, 9, 24)) 493 frameinfo = revise(*frame2[1:]) 494 self.assertEqual(frameinfo, 495 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0)) 496 self.assertEqual(frame2.positions, dis.Positions(9, 9, 4, 22)) 497 frameinfo = revise(*frame3[1:]) 498 self.assertEqual(frameinfo, 499 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0)) 500 self.assertEqual(frame3.positions, dis.Positions(43, 43, 12, 25)) 501 frameinfo = revise(*frame4[1:]) 502 self.assertEqual(frameinfo, 503 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0)) 504 self.assertEqual(frame4.positions, dis.Positions(39, 39, 8, 27)) 505 # Test named tuple fields 506 record = mod.st[0] 507 self.assertIs(record.frame, mod.fr) 508 self.assertEqual(record.lineno, 16) 509 self.assertEqual(record.filename, mod.__file__) 510 self.assertEqual(record.function, 'eggs') 511 self.assertIn('inspect.stack()', record.code_context[0]) 512 self.assertEqual(record.index, 0) 513 514 def test_trace(self): 515 self.assertEqual(len(git.tr), 3) 516 frame1, frame2, frame3, = git.tr 517 self.assertEqual(revise(*frame1[1:]), 518 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0)) 519 self.assertEqual(frame1.positions, dis.Positions(43, 43, 12, 25)) 520 self.assertEqual(revise(*frame2[1:]), 521 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0)) 522 self.assertEqual(frame2.positions, dis.Positions(9, 9, 4, 22)) 523 self.assertEqual(revise(*frame3[1:]), 524 (modfile, 18, 'eggs', [' q = y / 0\n'], 0)) 525 self.assertEqual(frame3.positions, dis.Positions(18, 18, 8, 13)) 526 527 def test_frame(self): 528 args, varargs, varkw, locals = inspect.getargvalues(mod.fr) 529 self.assertEqual(args, ['x', 'y']) 530 self.assertEqual(varargs, None) 531 self.assertEqual(varkw, None) 532 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14}) 533 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals), 534 '(x=11, y=14)') 535 536 def test_previous_frame(self): 537 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back) 538 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f']) 539 self.assertEqual(varargs, 'g') 540 self.assertEqual(varkw, 'h') 541 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals), 542 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})') 543 544class GetSourceBase(unittest.TestCase): 545 # Subclasses must override. 546 fodderModule = None 547 548 def setUp(self): 549 with open(inspect.getsourcefile(self.fodderModule), encoding="utf-8") as fp: 550 self.source = fp.read() 551 552 def sourcerange(self, top, bottom): 553 lines = self.source.split("\n") 554 return "\n".join(lines[top-1:bottom]) + ("\n" if bottom else "") 555 556 def assertSourceEqual(self, obj, top, bottom): 557 self.assertEqual(inspect.getsource(obj), 558 self.sourcerange(top, bottom)) 559 560class SlotUser: 561 'Docstrings for __slots__' 562 __slots__ = {'power': 'measured in kilowatts', 563 'distance': 'measured in kilometers'} 564 565class TestRetrievingSourceCode(GetSourceBase): 566 fodderModule = mod 567 568 def test_getclasses(self): 569 classes = inspect.getmembers(mod, inspect.isclass) 570 self.assertEqual(classes, 571 [('FesteringGob', mod.FesteringGob), 572 ('MalodorousPervert', mod.MalodorousPervert), 573 ('ParrotDroppings', mod.ParrotDroppings), 574 ('StupidGit', mod.StupidGit), 575 ('Tit', mod.MalodorousPervert), 576 ('WhichComments', mod.WhichComments), 577 ]) 578 tree = inspect.getclasstree([cls[1] for cls in classes]) 579 self.assertEqual(tree, 580 [(object, ()), 581 [(mod.ParrotDroppings, (object,)), 582 [(mod.FesteringGob, (mod.MalodorousPervert, 583 mod.ParrotDroppings)) 584 ], 585 (mod.StupidGit, (object,)), 586 [(mod.MalodorousPervert, (mod.StupidGit,)), 587 [(mod.FesteringGob, (mod.MalodorousPervert, 588 mod.ParrotDroppings)) 589 ] 590 ], 591 (mod.WhichComments, (object,),) 592 ] 593 ]) 594 tree = inspect.getclasstree([cls[1] for cls in classes], True) 595 self.assertEqual(tree, 596 [(object, ()), 597 [(mod.ParrotDroppings, (object,)), 598 (mod.StupidGit, (object,)), 599 [(mod.MalodorousPervert, (mod.StupidGit,)), 600 [(mod.FesteringGob, (mod.MalodorousPervert, 601 mod.ParrotDroppings)) 602 ] 603 ], 604 (mod.WhichComments, (object,),) 605 ] 606 ]) 607 608 def test_getfunctions(self): 609 functions = inspect.getmembers(mod, inspect.isfunction) 610 self.assertEqual(functions, [('after_closing', mod.after_closing), 611 ('eggs', mod.eggs), 612 ('lobbest', mod.lobbest), 613 ('spam', mod.spam)]) 614 615 @unittest.skipIf(sys.flags.optimize >= 2, 616 "Docstrings are omitted with -O2 and above") 617 def test_getdoc(self): 618 self.assertEqual(inspect.getdoc(mod), 'A module docstring.') 619 self.assertEqual(inspect.getdoc(mod.StupidGit), 620 'A longer,\n\nindented\n\ndocstring.') 621 self.assertEqual(inspect.getdoc(git.abuse), 622 'Another\n\ndocstring\n\ncontaining\n\ntabs') 623 self.assertEqual(inspect.getdoc(SlotUser.power), 624 'measured in kilowatts') 625 self.assertEqual(inspect.getdoc(SlotUser.distance), 626 'measured in kilometers') 627 628 @unittest.skipIf(sys.flags.optimize >= 2, 629 "Docstrings are omitted with -O2 and above") 630 def test_getdoc_inherited(self): 631 self.assertEqual(inspect.getdoc(mod.FesteringGob), 632 'A longer,\n\nindented\n\ndocstring.') 633 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse), 634 'Another\n\ndocstring\n\ncontaining\n\ntabs') 635 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse), 636 'Another\n\ndocstring\n\ncontaining\n\ntabs') 637 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction), 638 'The automatic gainsaying.') 639 640 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings") 641 def test_finddoc(self): 642 finddoc = inspect._finddoc 643 self.assertEqual(finddoc(int), int.__doc__) 644 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__) 645 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__) 646 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__) 647 self.assertEqual(finddoc(int.real), int.real.__doc__) 648 649 cleandoc_testdata = [ 650 # first line should have different margin 651 (' An\n indented\n docstring.', 'An\nindented\n docstring.'), 652 # trailing whitespace are not removed. 653 (' An \n \n indented \n docstring. ', 654 'An \n \nindented \n docstring. '), 655 # NUL is not termination. 656 ('doc\0string\n\n second\0line\n third\0line\0', 657 'doc\0string\n\nsecond\0line\nthird\0line\0'), 658 # first line is lstrip()-ped. other lines are kept when no margin.[w: 659 (' ', ''), 660 # compiler.cleandoc() doesn't strip leading/trailing newlines 661 # to keep maximum backward compatibility. 662 # inspect.cleandoc() removes them. 663 ('\n\n\n first paragraph\n\n second paragraph\n\n', 664 '\n\n\nfirst paragraph\n\n second paragraph\n\n'), 665 (' \n \n \n ', '\n \n \n '), 666 ] 667 668 def test_cleandoc(self): 669 func = inspect.cleandoc 670 for i, (input, expected) in enumerate(self.cleandoc_testdata): 671 # only inspect.cleandoc() strip \n 672 expected = expected.strip('\n') 673 with self.subTest(i=i): 674 self.assertEqual(func(input), expected) 675 676 @cpython_only 677 def test_c_cleandoc(self): 678 try: 679 import _testinternalcapi 680 except ImportError: 681 return unittest.skip("requires _testinternalcapi") 682 func = _testinternalcapi.compiler_cleandoc 683 for i, (input, expected) in enumerate(self.cleandoc_testdata): 684 with self.subTest(i=i): 685 self.assertEqual(func(input), expected) 686 687 def test_getcomments(self): 688 self.assertEqual(inspect.getcomments(mod), '# line 1\n') 689 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n') 690 self.assertEqual(inspect.getcomments(mod2.cls160), '# line 159\n') 691 # If the object source file is not available, return None. 692 co = compile('x=1', '_non_existing_filename.py', 'exec') 693 self.assertIsNone(inspect.getcomments(co)) 694 # If the object has been defined in C, return None. 695 self.assertIsNone(inspect.getcomments(list)) 696 697 def test_getmodule(self): 698 # Check actual module 699 self.assertEqual(inspect.getmodule(mod), mod) 700 # Check class (uses __module__ attribute) 701 self.assertEqual(inspect.getmodule(mod.StupidGit), mod) 702 # Check a method (no __module__ attribute, falls back to filename) 703 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod) 704 # Do it again (check the caching isn't broken) 705 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod) 706 # Check a builtin 707 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"]) 708 # Check filename override 709 self.assertEqual(inspect.getmodule(None, modfile), mod) 710 711 def test_getmodule_file_not_found(self): 712 # See bpo-45406 713 def _getabsfile(obj, _filename): 714 raise FileNotFoundError('bad file') 715 with unittest.mock.patch('inspect.getabsfile', _getabsfile): 716 f = inspect.currentframe() 717 self.assertIsNone(inspect.getmodule(f)) 718 inspect.getouterframes(f) # smoke test 719 720 def test_getframeinfo_get_first_line(self): 721 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50) 722 self.assertEqual(frame_info.code_context[0], "# line 1\n") 723 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n") 724 725 def test_getsource(self): 726 self.assertSourceEqual(git.abuse, 29, 39) 727 self.assertSourceEqual(mod.StupidGit, 21, 51) 728 self.assertSourceEqual(mod.lobbest, 75, 76) 729 self.assertSourceEqual(mod.after_closing, 120, 120) 730 731 def test_getsourcefile(self): 732 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile) 733 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile) 734 fn = "_non_existing_filename_used_for_sourcefile_test.py" 735 co = compile("x=1", fn, "exec") 736 self.assertEqual(inspect.getsourcefile(co), None) 737 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename) 738 try: 739 self.assertEqual(normcase(inspect.getsourcefile(co)), fn) 740 finally: 741 del linecache.cache[co.co_filename] 742 743 def test_getsource_empty_file(self): 744 with temp_cwd() as cwd: 745 with open('empty_file.py', 'w'): 746 pass 747 sys.path.insert(0, cwd) 748 try: 749 import empty_file 750 self.assertEqual(inspect.getsource(empty_file), '\n') 751 self.assertEqual(inspect.getsourcelines(empty_file), (['\n'], 0)) 752 finally: 753 sys.path.remove(cwd) 754 755 def test_getfile(self): 756 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__) 757 758 def test_getfile_builtin_module(self): 759 with self.assertRaises(TypeError) as e: 760 inspect.getfile(sys) 761 self.assertTrue(str(e.exception).startswith('<module')) 762 763 def test_getfile_builtin_class(self): 764 with self.assertRaises(TypeError) as e: 765 inspect.getfile(int) 766 self.assertTrue(str(e.exception).startswith('<class')) 767 768 def test_getfile_builtin_function_or_method(self): 769 with self.assertRaises(TypeError) as e_abs: 770 inspect.getfile(abs) 771 self.assertIn('expected, got', str(e_abs.exception)) 772 with self.assertRaises(TypeError) as e_append: 773 inspect.getfile(list.append) 774 self.assertIn('expected, got', str(e_append.exception)) 775 776 @suppress_immortalization() 777 def test_getfile_class_without_module(self): 778 class CM(type): 779 @property 780 def __module__(cls): 781 raise AttributeError 782 class C(metaclass=CM): 783 pass 784 with self.assertRaises(TypeError): 785 inspect.getfile(C) 786 787 def test_getfile_broken_repr(self): 788 class ErrorRepr: 789 def __repr__(self): 790 raise Exception('xyz') 791 er = ErrorRepr() 792 with self.assertRaises(TypeError): 793 inspect.getfile(er) 794 795 def test_getmodule_recursion(self): 796 from types import ModuleType 797 name = '__inspect_dummy' 798 m = sys.modules[name] = ModuleType(name) 799 m.__file__ = "<string>" # hopefully not a real filename... 800 m.__loader__ = "dummy" # pretend the filename is understood by a loader 801 exec("def x(): pass", m.__dict__) 802 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>') 803 del sys.modules[name] 804 inspect.getmodule(compile('a=10','','single')) 805 806 def test_proceed_with_fake_filename(self): 807 '''doctest monkeypatches linecache to enable inspection''' 808 fn, source = '<test>', 'def x(): pass\n' 809 getlines = linecache.getlines 810 def monkey(filename, module_globals=None): 811 if filename == fn: 812 return source.splitlines(keepends=True) 813 else: 814 return getlines(filename, module_globals) 815 linecache.getlines = monkey 816 try: 817 ns = {} 818 exec(compile(source, fn, 'single'), ns) 819 inspect.getsource(ns["x"]) 820 finally: 821 linecache.getlines = getlines 822 823 def test_getsource_on_code_object(self): 824 self.assertSourceEqual(mod.eggs.__code__, 12, 18) 825 826 def test_getsource_on_generated_class(self): 827 A = type('A', (unittest.TestCase,), {}) 828 self.assertEqual(inspect.getsourcefile(A), __file__) 829 self.assertEqual(inspect.getfile(A), __file__) 830 self.assertIs(inspect.getmodule(A), sys.modules[__name__]) 831 self.assertRaises(OSError, inspect.getsource, A) 832 self.assertRaises(OSError, inspect.getsourcelines, A) 833 self.assertIsNone(inspect.getcomments(A)) 834 835 def test_getsource_on_class_without_firstlineno(self): 836 __firstlineno__ = 1 837 class C: 838 nonlocal __firstlineno__ 839 self.assertRaises(OSError, inspect.getsource, C) 840 841class TestGetsourceStdlib(unittest.TestCase): 842 # Test Python implementations of the stdlib modules 843 844 def test_getsource_stdlib_collections_abc(self): 845 import collections.abc 846 lines, lineno = inspect.getsourcelines(collections.abc.Sequence) 847 self.assertEqual(lines[0], 'class Sequence(Reversible, Collection):\n') 848 src = inspect.getsource(collections.abc.Sequence) 849 self.assertEqual(src.splitlines(True), lines) 850 851 def test_getsource_stdlib_tomllib(self): 852 import tomllib 853 self.assertRaises(OSError, inspect.getsource, tomllib.TOMLDecodeError) 854 self.assertRaises(OSError, inspect.getsourcelines, tomllib.TOMLDecodeError) 855 856 def test_getsource_stdlib_abc(self): 857 # Pure Python implementation 858 abc = import_helper.import_fresh_module('abc', blocked=['_abc']) 859 with support.swap_item(sys.modules, 'abc', abc): 860 self.assertRaises(OSError, inspect.getsource, abc.ABCMeta) 861 self.assertRaises(OSError, inspect.getsourcelines, abc.ABCMeta) 862 # With C acceleration 863 import abc 864 try: 865 src = inspect.getsource(abc.ABCMeta) 866 lines, lineno = inspect.getsourcelines(abc.ABCMeta) 867 except OSError: 868 pass 869 else: 870 self.assertEqual(lines[0], ' class ABCMeta(type):\n') 871 self.assertEqual(src.splitlines(True), lines) 872 873 def test_getsource_stdlib_decimal(self): 874 # Pure Python implementation 875 decimal = import_helper.import_fresh_module('decimal', blocked=['_decimal']) 876 with support.swap_item(sys.modules, 'decimal', decimal): 877 src = inspect.getsource(decimal.Decimal) 878 lines, lineno = inspect.getsourcelines(decimal.Decimal) 879 self.assertEqual(lines[0], 'class Decimal(object):\n') 880 self.assertEqual(src.splitlines(True), lines) 881 882class TestGetsourceInteractive(unittest.TestCase): 883 def test_getclasses_interactive(self): 884 # bpo-44648: simulate a REPL session; 885 # there is no `__file__` in the __main__ module 886 code = "import sys, inspect; \ 887 assert not hasattr(sys.modules['__main__'], '__file__'); \ 888 A = type('A', (), {}); \ 889 inspect.getsource(A)" 890 _, _, stderr = assert_python_failure("-c", code, __isolated=True) 891 self.assertIn(b'OSError: source code not available', stderr) 892 893class TestGettingSourceOfToplevelFrames(GetSourceBase): 894 fodderModule = mod 895 896 def test_range_toplevel_frame(self): 897 self.maxDiff = None 898 self.assertSourceEqual(mod.currentframe, 1, None) 899 900 def test_range_traceback_toplevel_frame(self): 901 self.assertSourceEqual(mod.tb, 1, None) 902 903class TestDecorators(GetSourceBase): 904 fodderModule = mod2 905 906 def test_wrapped_decorator(self): 907 self.assertSourceEqual(mod2.wrapped, 14, 17) 908 909 def test_replacing_decorator(self): 910 self.assertSourceEqual(mod2.gone, 9, 10) 911 912 def test_getsource_unwrap(self): 913 self.assertSourceEqual(mod2.real, 130, 132) 914 915 def test_decorator_with_lambda(self): 916 self.assertSourceEqual(mod2.func114, 113, 115) 917 918class TestOneliners(GetSourceBase): 919 fodderModule = mod2 920 def test_oneline_lambda(self): 921 # Test inspect.getsource with a one-line lambda function. 922 self.assertSourceEqual(mod2.oll, 25, 25) 923 924 def test_threeline_lambda(self): 925 # Test inspect.getsource with a three-line lambda function, 926 # where the second and third lines are _not_ indented. 927 self.assertSourceEqual(mod2.tll, 28, 30) 928 929 def test_twoline_indented_lambda(self): 930 # Test inspect.getsource with a two-line lambda function, 931 # where the second line _is_ indented. 932 self.assertSourceEqual(mod2.tlli, 33, 34) 933 934 def test_parenthesized_multiline_lambda(self): 935 # Test inspect.getsource with a parenthesized multi-line lambda 936 # function. 937 self.assertSourceEqual(mod2.parenthesized_lambda, 279, 279) 938 self.assertSourceEqual(mod2.parenthesized_lambda2, 281, 281) 939 self.assertSourceEqual(mod2.parenthesized_lambda3, 283, 283) 940 941 def test_post_line_parenthesized_lambda(self): 942 # Test inspect.getsource with a parenthesized multi-line lambda 943 # function. 944 self.assertSourceEqual(mod2.post_line_parenthesized_lambda1, 286, 287) 945 946 def test_nested_lambda(self): 947 # Test inspect.getsource with a nested lambda function. 948 self.assertSourceEqual(mod2.nested_lambda, 291, 292) 949 950 def test_onelinefunc(self): 951 # Test inspect.getsource with a regular one-line function. 952 self.assertSourceEqual(mod2.onelinefunc, 37, 37) 953 954 def test_manyargs(self): 955 # Test inspect.getsource with a regular function where 956 # the arguments are on two lines and _not_ indented and 957 # the body on the second line with the last arguments. 958 self.assertSourceEqual(mod2.manyargs, 40, 41) 959 960 def test_twolinefunc(self): 961 # Test inspect.getsource with a regular function where 962 # the body is on two lines, following the argument list and 963 # continued on the next line by a \\. 964 self.assertSourceEqual(mod2.twolinefunc, 44, 45) 965 966 def test_lambda_in_list(self): 967 # Test inspect.getsource with a one-line lambda function 968 # defined in a list, indented. 969 self.assertSourceEqual(mod2.a[1], 49, 49) 970 971 def test_anonymous(self): 972 # Test inspect.getsource with a lambda function defined 973 # as argument to another function. 974 self.assertSourceEqual(mod2.anonymous, 55, 55) 975 976 def test_enum(self): 977 self.assertSourceEqual(mod2.enum322, 322, 323) 978 self.assertSourceEqual(mod2.enum326, 326, 327) 979 self.assertSourceEqual(mod2.flag330, 330, 331) 980 self.assertSourceEqual(mod2.flag334, 334, 335) 981 self.assertRaises(OSError, inspect.getsource, mod2.simple_enum338) 982 self.assertRaises(OSError, inspect.getsource, mod2.simple_enum339) 983 self.assertRaises(OSError, inspect.getsource, mod2.simple_flag340) 984 self.assertRaises(OSError, inspect.getsource, mod2.simple_flag341) 985 986 def test_namedtuple(self): 987 self.assertSourceEqual(mod2.nt346, 346, 348) 988 self.assertRaises(OSError, inspect.getsource, mod2.nt351) 989 990 def test_typeddict(self): 991 self.assertSourceEqual(mod2.td354, 354, 356) 992 self.assertRaises(OSError, inspect.getsource, mod2.td359) 993 994 def test_dataclass(self): 995 self.assertSourceEqual(mod2.dc364, 364, 367) 996 self.assertRaises(OSError, inspect.getsource, mod2.dc370) 997 self.assertRaises(OSError, inspect.getsource, mod2.dc371) 998 999class TestBlockComments(GetSourceBase): 1000 fodderModule = mod 1001 1002 def test_toplevel_class(self): 1003 self.assertSourceEqual(mod.WhichComments, 96, 114) 1004 1005 def test_class_method(self): 1006 self.assertSourceEqual(mod.WhichComments.f, 99, 104) 1007 1008 def test_class_async_method(self): 1009 self.assertSourceEqual(mod.WhichComments.asyncf, 109, 112) 1010 1011class TestBuggyCases(GetSourceBase): 1012 fodderModule = mod2 1013 1014 def test_with_comment(self): 1015 self.assertSourceEqual(mod2.with_comment, 58, 59) 1016 1017 def test_multiline_sig(self): 1018 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64) 1019 1020 def test_nested_class(self): 1021 self.assertSourceEqual(mod2.func69().func71, 71, 72) 1022 1023 def test_one_liner_followed_by_non_name(self): 1024 self.assertSourceEqual(mod2.func77, 77, 77) 1025 1026 def test_one_liner_dedent_non_name(self): 1027 self.assertSourceEqual(mod2.cls82.func83, 83, 83) 1028 1029 def test_with_comment_instead_of_docstring(self): 1030 self.assertSourceEqual(mod2.func88, 88, 90) 1031 1032 def test_method_in_dynamic_class(self): 1033 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97) 1034 1035 # This should not skip for CPython, but might on a repackaged python where 1036 # unicodedata is not an external module, or on pypy. 1037 @unittest.skipIf(not hasattr(unicodedata, '__file__') or 1038 unicodedata.__file__.endswith('.py'), 1039 "unicodedata is not an external binary module") 1040 def test_findsource_binary(self): 1041 self.assertRaises(OSError, inspect.getsource, unicodedata) 1042 self.assertRaises(OSError, inspect.findsource, unicodedata) 1043 1044 def test_findsource_code_in_linecache(self): 1045 lines = ["x=1"] 1046 co = compile(lines[0], "_dynamically_created_file", "exec") 1047 self.assertRaises(OSError, inspect.findsource, co) 1048 self.assertRaises(OSError, inspect.getsource, co) 1049 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename) 1050 try: 1051 self.assertEqual(inspect.findsource(co), (lines,0)) 1052 self.assertEqual(inspect.getsource(co), lines[0]) 1053 finally: 1054 del linecache.cache[co.co_filename] 1055 1056 def test_findsource_without_filename(self): 1057 for fname in ['', '<string>']: 1058 co = compile('x=1', fname, "exec") 1059 self.assertRaises(IOError, inspect.findsource, co) 1060 self.assertRaises(IOError, inspect.getsource, co) 1061 1062 def test_findsource_on_func_with_out_of_bounds_lineno(self): 1063 mod_len = len(inspect.getsource(mod)) 1064 src = '\n' * 2* mod_len + "def f(): pass" 1065 co = compile(src, mod.__file__, "exec") 1066 g, l = {}, {} 1067 eval(co, g, l) 1068 func = l['f'] 1069 self.assertEqual(func.__code__.co_firstlineno, 1+2*mod_len) 1070 with self.assertRaisesRegex(OSError, "lineno is out of bounds"): 1071 inspect.findsource(func) 1072 1073 def test_findsource_on_class_with_out_of_bounds_lineno(self): 1074 mod_len = len(inspect.getsource(mod)) 1075 src = '\n' * 2* mod_len + "class A: pass" 1076 co = compile(src, mod.__file__, "exec") 1077 g, l = {'__name__': mod.__name__}, {} 1078 eval(co, g, l) 1079 cls = l['A'] 1080 self.assertEqual(cls.__firstlineno__, 1+2*mod_len) 1081 with self.assertRaisesRegex(OSError, "lineno is out of bounds"): 1082 inspect.findsource(cls) 1083 1084 def test_getsource_on_method(self): 1085 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119) 1086 1087 def test_getsource_on_class_code_object(self): 1088 self.assertSourceEqual(mod2.ClassWithCodeObject.code, 315, 317) 1089 1090 def test_nested_func(self): 1091 self.assertSourceEqual(mod2.cls135.func136, 136, 139) 1092 1093 def test_class_definition_in_multiline_string_definition(self): 1094 self.assertSourceEqual(mod2.cls149, 149, 152) 1095 1096 def test_class_definition_in_multiline_comment(self): 1097 self.assertSourceEqual(mod2.cls160, 160, 163) 1098 1099 def test_nested_class_definition_indented_string(self): 1100 self.assertSourceEqual(mod2.cls173.cls175, 175, 176) 1101 1102 def test_nested_class_definition(self): 1103 self.assertSourceEqual(mod2.cls183, 183, 188) 1104 self.assertSourceEqual(mod2.cls183.cls185, 185, 188) 1105 1106 def test_class_decorator(self): 1107 self.assertSourceEqual(mod2.cls196, 194, 201) 1108 self.assertSourceEqual(mod2.cls196.cls200, 198, 201) 1109 1110 @support.requires_docstrings 1111 def test_class_inside_conditional(self): 1112 # We skip this test when docstrings are not present, 1113 # because docstrings are one of the main factors of 1114 # finding the correct class in the source code. 1115 self.assertSourceEqual(mod2.cls238.cls239, 239, 240) 1116 1117 def test_multiple_children_classes(self): 1118 self.assertSourceEqual(mod2.cls203, 203, 209) 1119 self.assertSourceEqual(mod2.cls203.cls204, 204, 206) 1120 self.assertSourceEqual(mod2.cls203.cls204.cls205, 205, 206) 1121 self.assertSourceEqual(mod2.cls203.cls207, 207, 209) 1122 self.assertSourceEqual(mod2.cls203.cls207.cls205, 208, 209) 1123 1124 def test_nested_class_definition_inside_function(self): 1125 self.assertSourceEqual(mod2.func212(), 213, 214) 1126 self.assertSourceEqual(mod2.cls213, 218, 222) 1127 self.assertSourceEqual(mod2.cls213().func219(), 220, 221) 1128 1129 def test_class_with_method_from_other_module(self): 1130 with tempfile.TemporaryDirectory() as tempdir: 1131 with open(os.path.join(tempdir, 'inspect_actual%spy' % os.extsep), 1132 'w', encoding='utf-8') as f: 1133 f.write(textwrap.dedent(""" 1134 import inspect_other 1135 class A: 1136 def f(self): 1137 pass 1138 class A: 1139 def f(self): 1140 pass # correct one 1141 A.f = inspect_other.A.f 1142 """)) 1143 1144 with open(os.path.join(tempdir, 'inspect_other%spy' % os.extsep), 1145 'w', encoding='utf-8') as f: 1146 f.write(textwrap.dedent(""" 1147 class A: 1148 def f(self): 1149 pass 1150 """)) 1151 1152 with DirsOnSysPath(tempdir): 1153 import inspect_actual 1154 self.assertIn("correct", inspect.getsource(inspect_actual.A)) 1155 # Remove the module from sys.modules to force it to be reloaded. 1156 # This is necessary when the test is run multiple times. 1157 sys.modules.pop("inspect_actual") 1158 1159 @unittest.skipIf( 1160 support.is_emscripten or support.is_wasi, 1161 "socket.accept is broken" 1162 ) 1163 def test_nested_class_definition_inside_async_function(self): 1164 import asyncio 1165 self.addCleanup(asyncio.set_event_loop_policy, None) 1166 self.assertSourceEqual(asyncio.run(mod2.func225()), 226, 227) 1167 self.assertSourceEqual(mod2.cls226, 231, 235) 1168 self.assertSourceEqual(asyncio.run(mod2.cls226().func232()), 233, 234) 1169 1170 def test_class_definition_same_name_diff_methods(self): 1171 self.assertSourceEqual(mod2.cls296, 296, 298) 1172 self.assertSourceEqual(mod2.cls310, 310, 312) 1173 1174class TestNoEOL(GetSourceBase): 1175 def setUp(self): 1176 self.tempdir = TESTFN + '_dir' 1177 os.mkdir(self.tempdir) 1178 with open(os.path.join(self.tempdir, 'inspect_fodder3%spy' % os.extsep), 1179 'w', encoding='utf-8') as f: 1180 f.write("class X:\n pass # No EOL") 1181 with DirsOnSysPath(self.tempdir): 1182 import inspect_fodder3 as mod3 1183 self.fodderModule = mod3 1184 super().setUp() 1185 1186 def tearDown(self): 1187 shutil.rmtree(self.tempdir) 1188 1189 def test_class(self): 1190 self.assertSourceEqual(self.fodderModule.X, 1, 2) 1191 1192 1193class TestComplexDecorator(GetSourceBase): 1194 fodderModule = mod2 1195 1196 def test_parens_in_decorator(self): 1197 self.assertSourceEqual(self.fodderModule.complex_decorated, 273, 275) 1198 1199class _BrokenDataDescriptor(object): 1200 """ 1201 A broken data descriptor. See bug #1785. 1202 """ 1203 def __get__(*args): 1204 raise AttributeError("broken data descriptor") 1205 1206 def __set__(*args): 1207 raise RuntimeError 1208 1209 def __getattr__(*args): 1210 raise AttributeError("broken data descriptor") 1211 1212 1213class _BrokenMethodDescriptor(object): 1214 """ 1215 A broken method descriptor. See bug #1785. 1216 """ 1217 def __get__(*args): 1218 raise AttributeError("broken method descriptor") 1219 1220 def __getattr__(*args): 1221 raise AttributeError("broken method descriptor") 1222 1223 1224# Helper for testing classify_class_attrs. 1225def attrs_wo_objs(cls): 1226 return [t[:3] for t in inspect.classify_class_attrs(cls)] 1227 1228 1229class TestClassesAndFunctions(unittest.TestCase): 1230 def test_newstyle_mro(self): 1231 # The same w/ new-class MRO. 1232 class A(object): pass 1233 class B(A): pass 1234 class C(A): pass 1235 class D(B, C): pass 1236 1237 expected = (D, B, C, A, object) 1238 got = inspect.getmro(D) 1239 self.assertEqual(expected, got) 1240 1241 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None, 1242 varkw_e=None, defaults_e=None, 1243 posonlyargs_e=[], kwonlyargs_e=[], 1244 kwonlydefaults_e=None, 1245 ann_e={}): 1246 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \ 1247 inspect.getfullargspec(routine) 1248 self.assertEqual(args, args_e) 1249 self.assertEqual(varargs, varargs_e) 1250 self.assertEqual(varkw, varkw_e) 1251 self.assertEqual(defaults, defaults_e) 1252 self.assertEqual(kwonlyargs, kwonlyargs_e) 1253 self.assertEqual(kwonlydefaults, kwonlydefaults_e) 1254 self.assertEqual(ann, ann_e) 1255 1256 def test_getfullargspec(self): 1257 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1', 1258 kwonlyargs_e=['arg2'], 1259 kwonlydefaults_e={'arg2':1}) 1260 1261 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'], 1262 ann_e={'arg1' : list}) 1263 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [], 1264 kwonlyargs_e=['arg']) 1265 1266 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'], 1267 kwonlyargs_e=['e', 'f']) 1268 1269 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs, 1270 ['a', 'b', 'c', 'd'], 1271 varargs_e='args', 1272 varkw_e='kwargs', 1273 kwonlyargs_e=['e', 'f']) 1274 1275 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'], 1276 defaults_e=(1,2,3), 1277 kwonlyargs_e=['e', 'f'], 1278 kwonlydefaults_e={'e': 4, 'f': 5}) 1279 1280 def test_argspec_api_ignores_wrapped(self): 1281 # Issue 20684: low level introspection API must ignore __wrapped__ 1282 @functools.wraps(mod.spam) 1283 def ham(x, y): 1284 pass 1285 # Basic check 1286 self.assertFullArgSpecEquals(ham, ['x', 'y']) 1287 self.assertFullArgSpecEquals(functools.partial(ham), 1288 ['x', 'y']) 1289 1290 def test_getfullargspec_signature_attr(self): 1291 def test(): 1292 pass 1293 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY) 1294 test.__signature__ = inspect.Signature(parameters=(spam_param,)) 1295 1296 self.assertFullArgSpecEquals(test, ['spam']) 1297 1298 def test_getfullargspec_signature_annos(self): 1299 def test(a:'spam') -> 'ham': pass 1300 spec = inspect.getfullargspec(test) 1301 self.assertEqual(test.__annotations__, spec.annotations) 1302 1303 def test(): pass 1304 spec = inspect.getfullargspec(test) 1305 self.assertEqual(test.__annotations__, spec.annotations) 1306 1307 @unittest.skipIf(MISSING_C_DOCSTRINGS, 1308 "Signature information for builtins requires docstrings") 1309 def test_getfullargspec_builtin_methods(self): 1310 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj']) 1311 1312 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj']) 1313 1314 self.assertFullArgSpecEquals( 1315 os.stat, 1316 args_e=['path'], 1317 kwonlyargs_e=['dir_fd', 'follow_symlinks'], 1318 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True}) 1319 1320 @cpython_only 1321 @unittest.skipIf(MISSING_C_DOCSTRINGS, 1322 "Signature information for builtins requires docstrings") 1323 def test_getfullargspec_builtin_func(self): 1324 _testcapi = import_helper.import_module("_testcapi") 1325 builtin = _testcapi.docstring_with_signature_with_defaults 1326 spec = inspect.getfullargspec(builtin) 1327 self.assertEqual(spec.defaults[0], 'avocado') 1328 1329 @cpython_only 1330 @unittest.skipIf(MISSING_C_DOCSTRINGS, 1331 "Signature information for builtins requires docstrings") 1332 def test_getfullargspec_builtin_func_no_signature(self): 1333 _testcapi = import_helper.import_module("_testcapi") 1334 builtin = _testcapi.docstring_no_signature 1335 with self.assertRaises(TypeError): 1336 inspect.getfullargspec(builtin) 1337 1338 cls = _testcapi.DocStringNoSignatureTest 1339 obj = _testcapi.DocStringNoSignatureTest() 1340 tests = [ 1341 (_testcapi.docstring_no_signature_noargs, meth_noargs), 1342 (_testcapi.docstring_no_signature_o, meth_o), 1343 (cls.meth_noargs, meth_self_noargs), 1344 (cls.meth_o, meth_self_o), 1345 (obj.meth_noargs, meth_self_noargs), 1346 (obj.meth_o, meth_self_o), 1347 (cls.meth_noargs_class, meth_type_noargs), 1348 (cls.meth_o_class, meth_type_o), 1349 (cls.meth_noargs_static, meth_noargs), 1350 (cls.meth_o_static, meth_o), 1351 (cls.meth_noargs_coexist, meth_self_noargs), 1352 (cls.meth_o_coexist, meth_self_o), 1353 1354 (time.time, meth_noargs), 1355 (str.lower, meth_self_noargs), 1356 (''.lower, meth_self_noargs), 1357 (set.add, meth_self_o), 1358 (set().add, meth_self_o), 1359 (set.__contains__, meth_self_o), 1360 (set().__contains__, meth_self_o), 1361 (datetime.datetime.__dict__['utcnow'], meth_type_noargs), 1362 (datetime.datetime.utcnow, meth_type_noargs), 1363 (dict.__dict__['__class_getitem__'], meth_type_o), 1364 (dict.__class_getitem__, meth_type_o), 1365 ] 1366 try: 1367 import _stat 1368 except ImportError: 1369 # if the _stat extension is not available, stat.S_IMODE() is 1370 # implemented in Python, not in C 1371 pass 1372 else: 1373 tests.append((stat.S_IMODE, meth_o)) 1374 for builtin, template in tests: 1375 with self.subTest(builtin): 1376 self.assertEqual(inspect.getfullargspec(builtin), 1377 inspect.getfullargspec(template)) 1378 1379 def test_getfullargspec_definition_order_preserved_on_kwonly(self): 1380 for fn in signatures_with_lexicographic_keyword_only_parameters(): 1381 signature = inspect.getfullargspec(fn) 1382 l = list(signature.kwonlyargs) 1383 sorted_l = sorted(l) 1384 self.assertTrue(l) 1385 self.assertEqual(l, sorted_l) 1386 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn) 1387 l = list(signature.kwonlyargs) 1388 self.assertEqual(l, unsorted_keyword_only_parameters) 1389 1390 def test_classify_newstyle(self): 1391 class A(object): 1392 1393 def s(): pass 1394 s = staticmethod(s) 1395 1396 def c(cls): pass 1397 c = classmethod(c) 1398 1399 def getp(self): pass 1400 p = property(getp) 1401 1402 def m(self): pass 1403 1404 def m1(self): pass 1405 1406 datablob = '1' 1407 1408 dd = _BrokenDataDescriptor() 1409 md = _BrokenMethodDescriptor() 1410 1411 attrs = attrs_wo_objs(A) 1412 1413 self.assertIn(('__new__', 'static method', object), attrs, 1414 'missing __new__') 1415 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__') 1416 1417 self.assertIn(('s', 'static method', A), attrs, 'missing static method') 1418 self.assertIn(('c', 'class method', A), attrs, 'missing class method') 1419 self.assertIn(('p', 'property', A), attrs, 'missing property') 1420 self.assertIn(('m', 'method', A), attrs, 1421 'missing plain method: %r' % attrs) 1422 self.assertIn(('m1', 'method', A), attrs, 'missing plain method') 1423 self.assertIn(('datablob', 'data', A), attrs, 'missing data') 1424 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor') 1425 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor') 1426 1427 class B(A): 1428 1429 def m(self): pass 1430 1431 attrs = attrs_wo_objs(B) 1432 self.assertIn(('s', 'static method', A), attrs, 'missing static method') 1433 self.assertIn(('c', 'class method', A), attrs, 'missing class method') 1434 self.assertIn(('p', 'property', A), attrs, 'missing property') 1435 self.assertIn(('m', 'method', B), attrs, 'missing plain method') 1436 self.assertIn(('m1', 'method', A), attrs, 'missing plain method') 1437 self.assertIn(('datablob', 'data', A), attrs, 'missing data') 1438 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor') 1439 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor') 1440 1441 1442 class C(A): 1443 1444 def m(self): pass 1445 def c(self): pass 1446 1447 attrs = attrs_wo_objs(C) 1448 self.assertIn(('s', 'static method', A), attrs, 'missing static method') 1449 self.assertIn(('c', 'method', C), attrs, 'missing plain method') 1450 self.assertIn(('p', 'property', A), attrs, 'missing property') 1451 self.assertIn(('m', 'method', C), attrs, 'missing plain method') 1452 self.assertIn(('m1', 'method', A), attrs, 'missing plain method') 1453 self.assertIn(('datablob', 'data', A), attrs, 'missing data') 1454 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor') 1455 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor') 1456 1457 class D(B, C): 1458 1459 def m1(self): pass 1460 1461 attrs = attrs_wo_objs(D) 1462 self.assertIn(('s', 'static method', A), attrs, 'missing static method') 1463 self.assertIn(('c', 'method', C), attrs, 'missing plain method') 1464 self.assertIn(('p', 'property', A), attrs, 'missing property') 1465 self.assertIn(('m', 'method', B), attrs, 'missing plain method') 1466 self.assertIn(('m1', 'method', D), attrs, 'missing plain method') 1467 self.assertIn(('datablob', 'data', A), attrs, 'missing data') 1468 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor') 1469 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor') 1470 1471 def test_classify_builtin_types(self): 1472 # Simple sanity check that all built-in types can have their 1473 # attributes classified. 1474 for name in dir(__builtins__): 1475 builtin = getattr(__builtins__, name) 1476 if isinstance(builtin, type): 1477 inspect.classify_class_attrs(builtin) 1478 1479 attrs = attrs_wo_objs(bool) 1480 self.assertIn(('__new__', 'static method', bool), attrs, 1481 'missing __new__') 1482 self.assertIn(('from_bytes', 'class method', int), attrs, 1483 'missing class method') 1484 self.assertIn(('to_bytes', 'method', int), attrs, 1485 'missing plain method') 1486 self.assertIn(('__add__', 'method', int), attrs, 1487 'missing plain method') 1488 self.assertIn(('__and__', 'method', bool), attrs, 1489 'missing plain method') 1490 1491 def test_classify_DynamicClassAttribute(self): 1492 class Meta(type): 1493 def __getattr__(self, name): 1494 if name == 'ham': 1495 return 'spam' 1496 return super().__getattr__(name) 1497 class VA(metaclass=Meta): 1498 @types.DynamicClassAttribute 1499 def ham(self): 1500 return 'eggs' 1501 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham']) 1502 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA)) 1503 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam') 1504 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA)) 1505 1506 def test_classify_overrides_bool(self): 1507 class NoBool(object): 1508 def __eq__(self, other): 1509 return NoBool() 1510 1511 def __bool__(self): 1512 raise NotImplementedError( 1513 "This object does not specify a boolean value") 1514 1515 class HasNB(object): 1516 dd = NoBool() 1517 1518 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd) 1519 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB)) 1520 1521 def test_classify_metaclass_class_attribute(self): 1522 class Meta(type): 1523 fish = 'slap' 1524 def __dir__(self): 1525 return ['__class__', '__module__', '__name__', 'fish'] 1526 class Class(metaclass=Meta): 1527 pass 1528 should_find = inspect.Attribute('fish', 'data', Meta, 'slap') 1529 self.assertIn(should_find, inspect.classify_class_attrs(Class)) 1530 1531 def test_classify_VirtualAttribute(self): 1532 class Meta(type): 1533 def __dir__(cls): 1534 return ['__class__', '__module__', '__name__', 'BOOM'] 1535 def __getattr__(self, name): 1536 if name =='BOOM': 1537 return 42 1538 return super().__getattr(name) 1539 class Class(metaclass=Meta): 1540 pass 1541 should_find = inspect.Attribute('BOOM', 'data', Meta, 42) 1542 self.assertIn(should_find, inspect.classify_class_attrs(Class)) 1543 1544 def test_classify_VirtualAttribute_multi_classes(self): 1545 class Meta1(type): 1546 def __dir__(cls): 1547 return ['__class__', '__module__', '__name__', 'one'] 1548 def __getattr__(self, name): 1549 if name =='one': 1550 return 1 1551 return super().__getattr__(name) 1552 class Meta2(type): 1553 def __dir__(cls): 1554 return ['__class__', '__module__', '__name__', 'two'] 1555 def __getattr__(self, name): 1556 if name =='two': 1557 return 2 1558 return super().__getattr__(name) 1559 class Meta3(Meta1, Meta2): 1560 def __dir__(cls): 1561 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] + 1562 Meta1.__dir__(cls) + Meta2.__dir__(cls)))) 1563 def __getattr__(self, name): 1564 if name =='three': 1565 return 3 1566 return super().__getattr__(name) 1567 class Class1(metaclass=Meta1): 1568 pass 1569 class Class2(Class1, metaclass=Meta3): 1570 pass 1571 1572 should_find1 = inspect.Attribute('one', 'data', Meta1, 1) 1573 should_find2 = inspect.Attribute('two', 'data', Meta2, 2) 1574 should_find3 = inspect.Attribute('three', 'data', Meta3, 3) 1575 cca = inspect.classify_class_attrs(Class2) 1576 for sf in (should_find1, should_find2, should_find3): 1577 self.assertIn(sf, cca) 1578 1579 def test_classify_class_attrs_with_buggy_dir(self): 1580 class M(type): 1581 def __dir__(cls): 1582 return ['__class__', '__name__', 'missing'] 1583 class C(metaclass=M): 1584 pass 1585 attrs = [a[0] for a in inspect.classify_class_attrs(C)] 1586 self.assertNotIn('missing', attrs) 1587 1588 def test_getmembers_descriptors(self): 1589 class A(object): 1590 dd = _BrokenDataDescriptor() 1591 md = _BrokenMethodDescriptor() 1592 1593 def pred_wrapper(pred): 1594 # A quick'n'dirty way to discard standard attributes of new-style 1595 # classes. 1596 class Empty(object): 1597 pass 1598 def wrapped(x): 1599 if '__name__' in dir(x) and hasattr(Empty, x.__name__): 1600 return False 1601 return pred(x) 1602 return wrapped 1603 1604 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor) 1605 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor) 1606 1607 self.assertEqual(inspect.getmembers(A, ismethoddescriptor), 1608 [('md', A.__dict__['md'])]) 1609 self.assertEqual(inspect.getmembers(A, isdatadescriptor), 1610 [('dd', A.__dict__['dd'])]) 1611 1612 class B(A): 1613 pass 1614 1615 self.assertEqual(inspect.getmembers(B, ismethoddescriptor), 1616 [('md', A.__dict__['md'])]) 1617 self.assertEqual(inspect.getmembers(B, isdatadescriptor), 1618 [('dd', A.__dict__['dd'])]) 1619 1620 def test_getmembers_method(self): 1621 class B: 1622 def f(self): 1623 pass 1624 1625 self.assertIn(('f', B.f), inspect.getmembers(B)) 1626 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod)) 1627 b = B() 1628 self.assertIn(('f', b.f), inspect.getmembers(b)) 1629 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod)) 1630 1631 def test_getmembers_custom_dir(self): 1632 class CorrectDir: 1633 def __init__(self, attr): 1634 self.attr = attr 1635 def method(self): 1636 return self.attr + 1 1637 def __dir__(self): 1638 return ['attr', 'method'] 1639 1640 cd = CorrectDir(5) 1641 self.assertEqual(inspect.getmembers(cd), [ 1642 ('attr', 5), 1643 ('method', cd.method), 1644 ]) 1645 self.assertEqual(inspect.getmembers(cd, inspect.ismethod), [ 1646 ('method', cd.method), 1647 ]) 1648 1649 def test_getmembers_custom_broken_dir(self): 1650 # inspect.getmembers calls `dir()` on the passed object inside. 1651 # if `__dir__` mentions some non-existent attribute, 1652 # we still need to return others correctly. 1653 class BrokenDir: 1654 existing = 1 1655 def method(self): 1656 return self.existing + 1 1657 def __dir__(self): 1658 return ['method', 'missing', 'existing'] 1659 1660 bd = BrokenDir() 1661 self.assertEqual(inspect.getmembers(bd), [ 1662 ('existing', 1), 1663 ('method', bd.method), 1664 ]) 1665 self.assertEqual(inspect.getmembers(bd, inspect.ismethod), [ 1666 ('method', bd.method), 1667 ]) 1668 1669 def test_getmembers_custom_duplicated_dir(self): 1670 # Duplicates in `__dir__` must not fail and return just one result. 1671 class DuplicatedDir: 1672 attr = 1 1673 def __dir__(self): 1674 return ['attr', 'attr'] 1675 1676 dd = DuplicatedDir() 1677 self.assertEqual(inspect.getmembers(dd), [ 1678 ('attr', 1), 1679 ]) 1680 1681 def test_getmembers_VirtualAttribute(self): 1682 class M(type): 1683 def __getattr__(cls, name): 1684 if name == 'eggs': 1685 return 'scrambled' 1686 return super().__getattr__(name) 1687 class A(metaclass=M): 1688 @types.DynamicClassAttribute 1689 def eggs(self): 1690 return 'spam' 1691 class B: 1692 def __getattr__(self, attribute): 1693 return None 1694 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A)) 1695 self.assertIn(('eggs', 'spam'), inspect.getmembers(A())) 1696 b = B() 1697 self.assertIn(('__getattr__', b.__getattr__), inspect.getmembers(b)) 1698 1699 def test_getmembers_static(self): 1700 class A: 1701 @property 1702 def name(self): 1703 raise NotImplementedError 1704 @types.DynamicClassAttribute 1705 def eggs(self): 1706 raise NotImplementedError 1707 1708 a = A() 1709 instance_members = inspect.getmembers_static(a) 1710 class_members = inspect.getmembers_static(A) 1711 self.assertIn(('name', inspect.getattr_static(a, 'name')), instance_members) 1712 self.assertIn(('eggs', inspect.getattr_static(a, 'eggs')), instance_members) 1713 self.assertIn(('name', inspect.getattr_static(A, 'name')), class_members) 1714 self.assertIn(('eggs', inspect.getattr_static(A, 'eggs')), class_members) 1715 1716 def test_getmembers_with_buggy_dir(self): 1717 class M(type): 1718 def __dir__(cls): 1719 return ['__class__', '__name__', 'missing'] 1720 class C(metaclass=M): 1721 pass 1722 attrs = [a[0] for a in inspect.getmembers(C)] 1723 self.assertNotIn('missing', attrs) 1724 1725 def test_get_annotations_with_stock_annotations(self): 1726 def foo(a:int, b:str): pass 1727 self.assertEqual(inspect.get_annotations(foo), {'a': int, 'b': str}) 1728 1729 foo.__annotations__ = {'a': 'foo', 'b':'str'} 1730 self.assertEqual(inspect.get_annotations(foo), {'a': 'foo', 'b': 'str'}) 1731 1732 self.assertEqual(inspect.get_annotations(foo, eval_str=True, locals=locals()), {'a': foo, 'b': str}) 1733 self.assertEqual(inspect.get_annotations(foo, eval_str=True, globals=locals()), {'a': foo, 'b': str}) 1734 1735 isa = inspect_stock_annotations 1736 self.assertEqual(inspect.get_annotations(isa), {'a': int, 'b': str}) 1737 self.assertEqual(inspect.get_annotations(isa.MyClass), {'a': int, 'b': str}) 1738 self.assertEqual(inspect.get_annotations(isa.function), {'a': int, 'b': str, 'return': isa.MyClass}) 1739 self.assertEqual(inspect.get_annotations(isa.function2), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass}) 1740 self.assertEqual(inspect.get_annotations(isa.function3), {'a': 'int', 'b': 'str', 'c': 'MyClass'}) 1741 self.assertEqual(inspect.get_annotations(inspect), {}) # inspect module has no annotations 1742 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass), {}) 1743 self.assertEqual(inspect.get_annotations(isa.unannotated_function), {}) 1744 1745 self.assertEqual(inspect.get_annotations(isa, eval_str=True), {'a': int, 'b': str}) 1746 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=True), {'a': int, 'b': str}) 1747 self.assertEqual(inspect.get_annotations(isa.function, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass}) 1748 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=True), {'a': int, 'b': str, 'c': isa.MyClass, 'return': isa.MyClass}) 1749 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=True), {'a': int, 'b': str, 'c': isa.MyClass}) 1750 self.assertEqual(inspect.get_annotations(inspect, eval_str=True), {}) 1751 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=True), {}) 1752 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=True), {}) 1753 1754 self.assertEqual(inspect.get_annotations(isa, eval_str=False), {'a': int, 'b': str}) 1755 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=False), {'a': int, 'b': str}) 1756 self.assertEqual(inspect.get_annotations(isa.function, eval_str=False), {'a': int, 'b': str, 'return': isa.MyClass}) 1757 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=False), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass}) 1758 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=False), {'a': 'int', 'b': 'str', 'c': 'MyClass'}) 1759 self.assertEqual(inspect.get_annotations(inspect, eval_str=False), {}) 1760 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=False), {}) 1761 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=False), {}) 1762 1763 def times_three(fn): 1764 @functools.wraps(fn) 1765 def wrapper(a, b): 1766 return fn(a*3, b*3) 1767 return wrapper 1768 1769 wrapped = times_three(isa.function) 1770 self.assertEqual(wrapped(1, 'x'), isa.MyClass(3, 'xxx')) 1771 self.assertIsNot(wrapped.__globals__, isa.function.__globals__) 1772 self.assertEqual(inspect.get_annotations(wrapped), {'a': int, 'b': str, 'return': isa.MyClass}) 1773 self.assertEqual(inspect.get_annotations(wrapped, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass}) 1774 self.assertEqual(inspect.get_annotations(wrapped, eval_str=False), {'a': int, 'b': str, 'return': isa.MyClass}) 1775 1776 def test_get_annotations_with_stringized_annotations(self): 1777 isa = inspect_stringized_annotations 1778 self.assertEqual(inspect.get_annotations(isa), {'a': 'int', 'b': 'str'}) 1779 self.assertEqual(inspect.get_annotations(isa.MyClass), {'a': 'int', 'b': 'str'}) 1780 self.assertEqual(inspect.get_annotations(isa.function), {'a': 'int', 'b': 'str', 'return': 'MyClass'}) 1781 self.assertEqual(inspect.get_annotations(isa.function2), {'a': 'int', 'b': "'str'", 'c': 'MyClass', 'return': 'MyClass'}) 1782 self.assertEqual(inspect.get_annotations(isa.function3), {'a': "'int'", 'b': "'str'", 'c': "'MyClass'"}) 1783 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass), {}) 1784 self.assertEqual(inspect.get_annotations(isa.unannotated_function), {}) 1785 1786 self.assertEqual(inspect.get_annotations(isa, eval_str=True), {'a': int, 'b': str}) 1787 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=True), {'a': int, 'b': str}) 1788 self.assertEqual(inspect.get_annotations(isa.function, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass}) 1789 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=True), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass}) 1790 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=True), {'a': 'int', 'b': 'str', 'c': 'MyClass'}) 1791 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=True), {}) 1792 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=True), {}) 1793 1794 self.assertEqual(inspect.get_annotations(isa, eval_str=False), {'a': 'int', 'b': 'str'}) 1795 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=False), {'a': 'int', 'b': 'str'}) 1796 self.assertEqual(inspect.get_annotations(isa.function, eval_str=False), {'a': 'int', 'b': 'str', 'return': 'MyClass'}) 1797 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=False), {'a': 'int', 'b': "'str'", 'c': 'MyClass', 'return': 'MyClass'}) 1798 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=False), {'a': "'int'", 'b': "'str'", 'c': "'MyClass'"}) 1799 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=False), {}) 1800 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=False), {}) 1801 1802 isa2 = inspect_stringized_annotations_2 1803 self.assertEqual(inspect.get_annotations(isa2), {}) 1804 self.assertEqual(inspect.get_annotations(isa2, eval_str=True), {}) 1805 self.assertEqual(inspect.get_annotations(isa2, eval_str=False), {}) 1806 1807 def times_three(fn): 1808 @functools.wraps(fn) 1809 def wrapper(a, b): 1810 return fn(a*3, b*3) 1811 return wrapper 1812 1813 wrapped = times_three(isa.function) 1814 self.assertEqual(wrapped(1, 'x'), isa.MyClass(3, 'xxx')) 1815 self.assertIsNot(wrapped.__globals__, isa.function.__globals__) 1816 self.assertEqual(inspect.get_annotations(wrapped), {'a': 'int', 'b': 'str', 'return': 'MyClass'}) 1817 self.assertEqual(inspect.get_annotations(wrapped, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass}) 1818 self.assertEqual(inspect.get_annotations(wrapped, eval_str=False), {'a': 'int', 'b': 'str', 'return': 'MyClass'}) 1819 1820 # test that local namespace lookups work 1821 self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations), {'x': 'mytype'}) 1822 self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations, eval_str=True), {'x': int}) 1823 1824 def test_pep695_generic_class_with_future_annotations(self): 1825 ann_module695 = inspect_stringized_annotations_pep695 1826 A_annotations = inspect.get_annotations(ann_module695.A, eval_str=True) 1827 A_type_params = ann_module695.A.__type_params__ 1828 self.assertIs(A_annotations["x"], A_type_params[0]) 1829 self.assertEqual(A_annotations["y"].__args__[0], Unpack[A_type_params[1]]) 1830 self.assertIs(A_annotations["z"].__args__[0], A_type_params[2]) 1831 1832 def test_pep695_generic_class_with_future_annotations_and_local_shadowing(self): 1833 B_annotations = inspect.get_annotations( 1834 inspect_stringized_annotations_pep695.B, eval_str=True 1835 ) 1836 self.assertEqual(B_annotations, {"x": int, "y": str, "z": bytes}) 1837 1838 def test_pep695_generic_class_with_future_annotations_name_clash_with_global_vars(self): 1839 ann_module695 = inspect_stringized_annotations_pep695 1840 C_annotations = inspect.get_annotations(ann_module695.C, eval_str=True) 1841 self.assertEqual( 1842 set(C_annotations.values()), 1843 set(ann_module695.C.__type_params__) 1844 ) 1845 1846 def test_pep_695_generic_function_with_future_annotations(self): 1847 ann_module695 = inspect_stringized_annotations_pep695 1848 generic_func_annotations = inspect.get_annotations( 1849 ann_module695.generic_function, eval_str=True 1850 ) 1851 func_t_params = ann_module695.generic_function.__type_params__ 1852 self.assertEqual( 1853 generic_func_annotations.keys(), {"x", "y", "z", "zz", "return"} 1854 ) 1855 self.assertIs(generic_func_annotations["x"], func_t_params[0]) 1856 self.assertEqual(generic_func_annotations["y"], Unpack[func_t_params[1]]) 1857 self.assertIs(generic_func_annotations["z"].__origin__, func_t_params[2]) 1858 self.assertIs(generic_func_annotations["zz"].__origin__, func_t_params[2]) 1859 1860 def test_pep_695_generic_function_with_future_annotations_name_clash_with_global_vars(self): 1861 self.assertEqual( 1862 set( 1863 inspect.get_annotations( 1864 inspect_stringized_annotations_pep695.generic_function_2, 1865 eval_str=True 1866 ).values() 1867 ), 1868 set( 1869 inspect_stringized_annotations_pep695.generic_function_2.__type_params__ 1870 ) 1871 ) 1872 1873 def test_pep_695_generic_method_with_future_annotations(self): 1874 ann_module695 = inspect_stringized_annotations_pep695 1875 generic_method_annotations = inspect.get_annotations( 1876 ann_module695.D.generic_method, eval_str=True 1877 ) 1878 params = { 1879 param.__name__: param 1880 for param in ann_module695.D.generic_method.__type_params__ 1881 } 1882 self.assertEqual( 1883 generic_method_annotations, 1884 {"x": params["Foo"], "y": params["Bar"], "return": None} 1885 ) 1886 1887 def test_pep_695_generic_method_with_future_annotations_name_clash_with_global_vars(self): 1888 self.assertEqual( 1889 set( 1890 inspect.get_annotations( 1891 inspect_stringized_annotations_pep695.D.generic_method_2, 1892 eval_str=True 1893 ).values() 1894 ), 1895 set( 1896 inspect_stringized_annotations_pep695.D.generic_method_2.__type_params__ 1897 ) 1898 ) 1899 1900 def test_pep_695_generic_method_with_future_annotations_name_clash_with_global_and_local_vars(self): 1901 self.assertEqual( 1902 inspect.get_annotations( 1903 inspect_stringized_annotations_pep695.E, eval_str=True 1904 ), 1905 {"x": str}, 1906 ) 1907 1908 def test_pep_695_generics_with_future_annotations_nested_in_function(self): 1909 results = inspect_stringized_annotations_pep695.nested() 1910 1911 self.assertEqual( 1912 set(results.F_annotations.values()), 1913 set(results.F.__type_params__) 1914 ) 1915 self.assertEqual( 1916 set(results.F_meth_annotations.values()), 1917 set(results.F.generic_method.__type_params__) 1918 ) 1919 self.assertNotEqual( 1920 set(results.F_meth_annotations.values()), 1921 set(results.F.__type_params__) 1922 ) 1923 self.assertEqual( 1924 set(results.F_meth_annotations.values()).intersection(results.F.__type_params__), 1925 set() 1926 ) 1927 1928 self.assertEqual(results.G_annotations, {"x": str}) 1929 1930 self.assertEqual( 1931 set(results.generic_func_annotations.values()), 1932 set(results.generic_func.__type_params__) 1933 ) 1934 1935 1936class TestFormatAnnotation(unittest.TestCase): 1937 def test_typing_replacement(self): 1938 from test.typinganndata.ann_module9 import ann, ann1 1939 self.assertEqual(inspect.formatannotation(ann), 'Union[List[str], int]') 1940 self.assertEqual(inspect.formatannotation(ann1), 'Union[List[testModule.typing.A], int]') 1941 1942 1943class TestIsMethodDescriptor(unittest.TestCase): 1944 1945 def test_custom_descriptors(self): 1946 class MethodDescriptor: 1947 def __get__(self, *_): pass 1948 class MethodDescriptorSub(MethodDescriptor): 1949 pass 1950 class DataDescriptorWithNoGet: 1951 def __set__(self, *_): pass 1952 class DataDescriptorWithGetSet: 1953 def __get__(self, *_): pass 1954 def __set__(self, *_): pass 1955 class DataDescriptorWithGetDelete: 1956 def __get__(self, *_): pass 1957 def __delete__(self, *_): pass 1958 class DataDescriptorSub(DataDescriptorWithNoGet, 1959 DataDescriptorWithGetDelete): 1960 pass 1961 1962 # Custom method descriptors: 1963 self.assertTrue( 1964 inspect.ismethoddescriptor(MethodDescriptor()), 1965 '__get__ and no __set__/__delete__ => method descriptor') 1966 self.assertTrue( 1967 inspect.ismethoddescriptor(MethodDescriptorSub()), 1968 '__get__ (inherited) and no __set__/__delete__' 1969 ' => method descriptor') 1970 1971 # Custom data descriptors: 1972 self.assertFalse( 1973 inspect.ismethoddescriptor(DataDescriptorWithNoGet()), 1974 '__set__ (and no __get__) => not a method descriptor') 1975 self.assertFalse( 1976 inspect.ismethoddescriptor(DataDescriptorWithGetSet()), 1977 '__get__ and __set__ => not a method descriptor') 1978 self.assertFalse( 1979 inspect.ismethoddescriptor(DataDescriptorWithGetDelete()), 1980 '__get__ and __delete__ => not a method descriptor') 1981 self.assertFalse( 1982 inspect.ismethoddescriptor(DataDescriptorSub()), 1983 '__get__, __set__ and __delete__ => not a method descriptor') 1984 1985 # Classes of descriptors (are *not* descriptors themselves): 1986 self.assertFalse(inspect.ismethoddescriptor(MethodDescriptor)) 1987 self.assertFalse(inspect.ismethoddescriptor(MethodDescriptorSub)) 1988 self.assertFalse(inspect.ismethoddescriptor(DataDescriptorSub)) 1989 1990 def test_builtin_descriptors(self): 1991 builtin_slot_wrapper = int.__add__ # This one is mentioned in docs. 1992 class Owner: 1993 def instance_method(self): pass 1994 @classmethod 1995 def class_method(cls): pass 1996 @staticmethod 1997 def static_method(): pass 1998 @property 1999 def a_property(self): pass 2000 class Slotermeyer: 2001 __slots__ = 'a_slot', 2002 def function(): 2003 pass 2004 a_lambda = lambda: None 2005 2006 # Example builtin method descriptors: 2007 self.assertTrue( 2008 inspect.ismethoddescriptor(builtin_slot_wrapper), 2009 'a builtin slot wrapper is a method descriptor') 2010 self.assertTrue( 2011 inspect.ismethoddescriptor(Owner.__dict__['class_method']), 2012 'a classmethod object is a method descriptor') 2013 self.assertTrue( 2014 inspect.ismethoddescriptor(Owner.__dict__['static_method']), 2015 'a staticmethod object is a method descriptor') 2016 2017 # Example builtin data descriptors: 2018 self.assertFalse( 2019 inspect.ismethoddescriptor(Owner.__dict__['a_property']), 2020 'a property is not a method descriptor') 2021 self.assertFalse( 2022 inspect.ismethoddescriptor(Slotermeyer.__dict__['a_slot']), 2023 'a slot is not a method descriptor') 2024 2025 # `types.MethodType`/`types.FunctionType` instances (they *are* 2026 # method descriptors, but `ismethoddescriptor()` explicitly 2027 # excludes them): 2028 self.assertFalse(inspect.ismethoddescriptor(Owner().instance_method)) 2029 self.assertFalse(inspect.ismethoddescriptor(Owner().class_method)) 2030 self.assertFalse(inspect.ismethoddescriptor(Owner().static_method)) 2031 self.assertFalse(inspect.ismethoddescriptor(Owner.instance_method)) 2032 self.assertFalse(inspect.ismethoddescriptor(Owner.class_method)) 2033 self.assertFalse(inspect.ismethoddescriptor(Owner.static_method)) 2034 self.assertFalse(inspect.ismethoddescriptor(function)) 2035 self.assertFalse(inspect.ismethoddescriptor(a_lambda)) 2036 self.assertFalse(inspect.ismethoddescriptor(functools.partial(function))) 2037 2038 def test_descriptor_being_a_class(self): 2039 class MethodDescriptorMeta(type): 2040 def __get__(self, *_): pass 2041 class ClassBeingMethodDescriptor(metaclass=MethodDescriptorMeta): 2042 pass 2043 # `ClassBeingMethodDescriptor` itself *is* a method descriptor, 2044 # but it is *also* a class, and `ismethoddescriptor()` explicitly 2045 # excludes classes. 2046 self.assertFalse( 2047 inspect.ismethoddescriptor(ClassBeingMethodDescriptor), 2048 'classes (instances of type) are explicitly excluded') 2049 2050 def test_non_descriptors(self): 2051 class Test: 2052 pass 2053 self.assertFalse(inspect.ismethoddescriptor(Test())) 2054 self.assertFalse(inspect.ismethoddescriptor(Test)) 2055 self.assertFalse(inspect.ismethoddescriptor([42])) 2056 self.assertFalse(inspect.ismethoddescriptor(42)) 2057 2058 2059class TestIsDataDescriptor(unittest.TestCase): 2060 2061 def test_custom_descriptors(self): 2062 class NonDataDescriptor: 2063 def __get__(self, value, type=None): pass 2064 class DataDescriptor0: 2065 def __set__(self, name, value): pass 2066 class DataDescriptor1: 2067 def __delete__(self, name): pass 2068 class DataDescriptor2: 2069 __set__ = None 2070 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()), 2071 'class with only __get__ not a data descriptor') 2072 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()), 2073 'class with __set__ is a data descriptor') 2074 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()), 2075 'class with __delete__ is a data descriptor') 2076 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()), 2077 'class with __set__ = None is a data descriptor') 2078 2079 def test_slot(self): 2080 class Slotted: 2081 __slots__ = 'foo', 2082 self.assertTrue(inspect.isdatadescriptor(Slotted.foo), 2083 'a slot is a data descriptor') 2084 2085 def test_property(self): 2086 class Propertied: 2087 @property 2088 def a_property(self): 2089 pass 2090 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property), 2091 'a property is a data descriptor') 2092 2093 def test_functions(self): 2094 class Test(object): 2095 def instance_method(self): pass 2096 @classmethod 2097 def class_method(cls): pass 2098 @staticmethod 2099 def static_method(): pass 2100 def function(): 2101 pass 2102 a_lambda = lambda: None 2103 self.assertFalse(inspect.isdatadescriptor(Test().instance_method), 2104 'a instance method is not a data descriptor') 2105 self.assertFalse(inspect.isdatadescriptor(Test().class_method), 2106 'a class method is not a data descriptor') 2107 self.assertFalse(inspect.isdatadescriptor(Test().static_method), 2108 'a static method is not a data descriptor') 2109 self.assertFalse(inspect.isdatadescriptor(function), 2110 'a function is not a data descriptor') 2111 self.assertFalse(inspect.isdatadescriptor(a_lambda), 2112 'a lambda is not a data descriptor') 2113 2114 2115_global_ref = object() 2116class TestGetClosureVars(unittest.TestCase): 2117 2118 def test_name_resolution(self): 2119 # Basic test of the 4 different resolution mechanisms 2120 def f(nonlocal_ref): 2121 def g(local_ref): 2122 print(local_ref, nonlocal_ref, _global_ref, unbound_ref) 2123 return g 2124 _arg = object() 2125 nonlocal_vars = {"nonlocal_ref": _arg} 2126 global_vars = {"_global_ref": _global_ref} 2127 builtin_vars = {"print": print} 2128 unbound_names = {"unbound_ref"} 2129 expected = inspect.ClosureVars(nonlocal_vars, global_vars, 2130 builtin_vars, unbound_names) 2131 self.assertEqual(inspect.getclosurevars(f(_arg)), expected) 2132 2133 def test_generator_closure(self): 2134 def f(nonlocal_ref): 2135 def g(local_ref): 2136 print(local_ref, nonlocal_ref, _global_ref, unbound_ref) 2137 yield 2138 return g 2139 _arg = object() 2140 nonlocal_vars = {"nonlocal_ref": _arg} 2141 global_vars = {"_global_ref": _global_ref} 2142 builtin_vars = {"print": print} 2143 unbound_names = {"unbound_ref"} 2144 expected = inspect.ClosureVars(nonlocal_vars, global_vars, 2145 builtin_vars, unbound_names) 2146 self.assertEqual(inspect.getclosurevars(f(_arg)), expected) 2147 2148 def test_method_closure(self): 2149 class C: 2150 def f(self, nonlocal_ref): 2151 def g(local_ref): 2152 print(local_ref, nonlocal_ref, _global_ref, unbound_ref) 2153 return g 2154 _arg = object() 2155 nonlocal_vars = {"nonlocal_ref": _arg} 2156 global_vars = {"_global_ref": _global_ref} 2157 builtin_vars = {"print": print} 2158 unbound_names = {"unbound_ref"} 2159 expected = inspect.ClosureVars(nonlocal_vars, global_vars, 2160 builtin_vars, unbound_names) 2161 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected) 2162 2163 def test_attribute_same_name_as_global_var(self): 2164 class C: 2165 _global_ref = object() 2166 def f(): 2167 print(C._global_ref, _global_ref) 2168 nonlocal_vars = {"C": C} 2169 global_vars = {"_global_ref": _global_ref} 2170 builtin_vars = {"print": print} 2171 unbound_names = {"_global_ref"} 2172 expected = inspect.ClosureVars(nonlocal_vars, global_vars, 2173 builtin_vars, unbound_names) 2174 self.assertEqual(inspect.getclosurevars(f), expected) 2175 2176 def test_nonlocal_vars(self): 2177 # More complex tests of nonlocal resolution 2178 def _nonlocal_vars(f): 2179 return inspect.getclosurevars(f).nonlocals 2180 2181 def make_adder(x): 2182 def add(y): 2183 return x + y 2184 return add 2185 2186 def curry(func, arg1): 2187 return lambda arg2: func(arg1, arg2) 2188 2189 def less_than(a, b): 2190 return a < b 2191 2192 # The infamous Y combinator. 2193 def Y(le): 2194 def g(f): 2195 return le(lambda x: f(f)(x)) 2196 Y.g_ref = g 2197 return g(g) 2198 2199 def check_y_combinator(func): 2200 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref}) 2201 2202 inc = make_adder(1) 2203 add_two = make_adder(2) 2204 greater_than_five = curry(less_than, 5) 2205 2206 self.assertEqual(_nonlocal_vars(inc), {'x': 1}) 2207 self.assertEqual(_nonlocal_vars(add_two), {'x': 2}) 2208 self.assertEqual(_nonlocal_vars(greater_than_five), 2209 {'arg1': 5, 'func': less_than}) 2210 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)), 2211 {'x': 3}) 2212 Y(check_y_combinator) 2213 2214 def test_getclosurevars_empty(self): 2215 def foo(): pass 2216 _empty = inspect.ClosureVars({}, {}, {}, set()) 2217 self.assertEqual(inspect.getclosurevars(lambda: True), _empty) 2218 self.assertEqual(inspect.getclosurevars(foo), _empty) 2219 2220 def test_getclosurevars_error(self): 2221 class T: pass 2222 self.assertRaises(TypeError, inspect.getclosurevars, 1) 2223 self.assertRaises(TypeError, inspect.getclosurevars, list) 2224 self.assertRaises(TypeError, inspect.getclosurevars, {}) 2225 2226 def _private_globals(self): 2227 code = """def f(): print(path)""" 2228 ns = {} 2229 exec(code, ns) 2230 return ns["f"], ns 2231 2232 def test_builtins_fallback(self): 2233 f, ns = self._private_globals() 2234 ns.pop("__builtins__", None) 2235 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"}) 2236 self.assertEqual(inspect.getclosurevars(f), expected) 2237 2238 def test_builtins_as_dict(self): 2239 f, ns = self._private_globals() 2240 ns["__builtins__"] = {"path":1} 2241 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"}) 2242 self.assertEqual(inspect.getclosurevars(f), expected) 2243 2244 def test_builtins_as_module(self): 2245 f, ns = self._private_globals() 2246 ns["__builtins__"] = os 2247 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"}) 2248 self.assertEqual(inspect.getclosurevars(f), expected) 2249 2250 2251class TestGetcallargsFunctions(unittest.TestCase): 2252 2253 def assertEqualCallArgs(self, func, call_params_string, locs=None): 2254 locs = dict(locs or {}, func=func) 2255 r1 = eval('func(%s)' % call_params_string, None, locs) 2256 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None, 2257 locs) 2258 self.assertEqual(r1, r2) 2259 2260 def assertEqualException(self, func, call_param_string, locs=None): 2261 locs = dict(locs or {}, func=func) 2262 try: 2263 eval('func(%s)' % call_param_string, None, locs) 2264 except Exception as e: 2265 ex1 = e 2266 else: 2267 self.fail('Exception not raised') 2268 try: 2269 eval('inspect.getcallargs(func, %s)' % call_param_string, None, 2270 locs) 2271 except Exception as e: 2272 ex2 = e 2273 else: 2274 self.fail('Exception not raised') 2275 self.assertIs(type(ex1), type(ex2)) 2276 self.assertEqual(str(ex1), str(ex2)) 2277 del ex1, ex2 2278 2279 def makeCallable(self, signature): 2280 """Create a function that returns its locals()""" 2281 code = "lambda %s: locals()" 2282 return eval(code % signature) 2283 2284 def test_plain(self): 2285 f = self.makeCallable('a, b=1') 2286 self.assertEqualCallArgs(f, '2') 2287 self.assertEqualCallArgs(f, '2, 3') 2288 self.assertEqualCallArgs(f, 'a=2') 2289 self.assertEqualCallArgs(f, 'b=3, a=2') 2290 self.assertEqualCallArgs(f, '2, b=3') 2291 # expand *iterable / **mapping 2292 self.assertEqualCallArgs(f, '*(2,)') 2293 self.assertEqualCallArgs(f, '*[2]') 2294 self.assertEqualCallArgs(f, '*(2, 3)') 2295 self.assertEqualCallArgs(f, '*[2, 3]') 2296 self.assertEqualCallArgs(f, '**{"a":2}') 2297 self.assertEqualCallArgs(f, 'b=3, **{"a":2}') 2298 self.assertEqualCallArgs(f, '2, **{"b":3}') 2299 self.assertEqualCallArgs(f, '**{"b":3, "a":2}') 2300 # expand UserList / UserDict 2301 self.assertEqualCallArgs(f, '*collections.UserList([2])') 2302 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])') 2303 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)') 2304 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)') 2305 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)') 2306 2307 def test_varargs(self): 2308 f = self.makeCallable('a, b=1, *c') 2309 self.assertEqualCallArgs(f, '2') 2310 self.assertEqualCallArgs(f, '2, 3') 2311 self.assertEqualCallArgs(f, '2, 3, 4') 2312 self.assertEqualCallArgs(f, '*(2,3,4)') 2313 self.assertEqualCallArgs(f, '2, *[3,4]') 2314 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])') 2315 2316 def test_varkw(self): 2317 f = self.makeCallable('a, b=1, **c') 2318 self.assertEqualCallArgs(f, 'a=2') 2319 self.assertEqualCallArgs(f, '2, b=3, c=4') 2320 self.assertEqualCallArgs(f, 'b=3, a=2, c=4') 2321 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}') 2322 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}') 2323 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}') 2324 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)') 2325 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)') 2326 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)') 2327 2328 def test_varkw_only(self): 2329 # issue11256: 2330 f = self.makeCallable('**c') 2331 self.assertEqualCallArgs(f, '') 2332 self.assertEqualCallArgs(f, 'a=1') 2333 self.assertEqualCallArgs(f, 'a=1, b=2') 2334 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}') 2335 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)') 2336 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)') 2337 2338 def test_keyword_only(self): 2339 f = self.makeCallable('a=3, *, c, d=2') 2340 self.assertEqualCallArgs(f, 'c=3') 2341 self.assertEqualCallArgs(f, 'c=3, a=3') 2342 self.assertEqualCallArgs(f, 'a=2, c=4') 2343 self.assertEqualCallArgs(f, '4, c=4') 2344 self.assertEqualException(f, '') 2345 self.assertEqualException(f, '3') 2346 self.assertEqualException(f, 'a=3') 2347 self.assertEqualException(f, 'd=4') 2348 2349 f = self.makeCallable('*, c, d=2') 2350 self.assertEqualCallArgs(f, 'c=3') 2351 self.assertEqualCallArgs(f, 'c=3, d=4') 2352 self.assertEqualCallArgs(f, 'd=4, c=3') 2353 2354 def test_multiple_features(self): 2355 f = self.makeCallable('a, b=2, *f, **g') 2356 self.assertEqualCallArgs(f, '2, 3, 7') 2357 self.assertEqualCallArgs(f, '2, 3, x=8') 2358 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]') 2359 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9') 2360 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9') 2361 self.assertEqualCallArgs(f, 'x=8, *collections.UserList(' 2362 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}') 2363 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, ' 2364 '(4,[5,6])]), **collections.UserDict(' 2365 'y=9, z=10)') 2366 2367 f = self.makeCallable('a, b=2, *f, x, y=99, **g') 2368 self.assertEqualCallArgs(f, '2, 3, x=8') 2369 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]') 2370 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10') 2371 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10') 2372 self.assertEqualCallArgs(f, 'x=8, *collections.UserList(' 2373 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}') 2374 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, ' 2375 '(4,[5,6])]), q=0, **collections.UserDict(' 2376 'y=9, z=10)') 2377 2378 def test_errors(self): 2379 f0 = self.makeCallable('') 2380 f1 = self.makeCallable('a, b') 2381 f2 = self.makeCallable('a, b=1') 2382 # f0 takes no arguments 2383 self.assertEqualException(f0, '1') 2384 self.assertEqualException(f0, 'x=1') 2385 self.assertEqualException(f0, '1,x=1') 2386 # f1 takes exactly 2 arguments 2387 self.assertEqualException(f1, '') 2388 self.assertEqualException(f1, '1') 2389 self.assertEqualException(f1, 'a=2') 2390 self.assertEqualException(f1, 'b=3') 2391 # f2 takes at least 1 argument 2392 self.assertEqualException(f2, '') 2393 self.assertEqualException(f2, 'b=3') 2394 for f in f1, f2: 2395 # f1/f2 takes exactly/at most 2 arguments 2396 self.assertEqualException(f, '2, 3, 4') 2397 self.assertEqualException(f, '1, 2, 3, a=1') 2398 self.assertEqualException(f, '2, 3, 4, c=5') 2399 self.assertEqualException(f, '2, 3, 4, a=1, c=5') 2400 # f got an unexpected keyword argument 2401 self.assertEqualException(f, 'c=2') 2402 self.assertEqualException(f, '2, c=3') 2403 self.assertEqualException(f, '2, 3, c=4') 2404 self.assertEqualException(f, '2, c=4, b=3') 2405 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}') 2406 # f got multiple values for keyword argument 2407 self.assertEqualException(f, '1, a=2') 2408 self.assertEqualException(f, '1, **{"a":2}') 2409 self.assertEqualException(f, '1, 2, b=3') 2410 self.assertEqualException(f, '1, c=3, a=2') 2411 # issue11256: 2412 f3 = self.makeCallable('**c') 2413 self.assertEqualException(f3, '1, 2') 2414 self.assertEqualException(f3, '1, 2, a=1, b=2') 2415 f4 = self.makeCallable('*, a, b=0') 2416 self.assertEqualException(f4, '1, 2') 2417 self.assertEqualException(f4, '1, 2, a=1, b=2') 2418 self.assertEqualException(f4, 'a=1, a=3') 2419 self.assertEqualException(f4, 'a=1, c=3') 2420 self.assertEqualException(f4, 'a=1, a=3, b=4') 2421 self.assertEqualException(f4, 'a=1, b=2, a=3, b=4') 2422 self.assertEqualException(f4, 'a=1, a=2, a=3, b=4') 2423 2424 # issue #20816: getcallargs() fails to iterate over non-existent 2425 # kwonlydefaults and raises a wrong TypeError 2426 def f5(*, a): pass 2427 with self.assertRaisesRegex(TypeError, 2428 'missing 1 required keyword-only'): 2429 inspect.getcallargs(f5) 2430 2431 2432 # issue20817: 2433 def f6(a, b, c): 2434 pass 2435 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"): 2436 inspect.getcallargs(f6) 2437 2438 # bpo-33197 2439 with self.assertRaisesRegex(ValueError, 2440 'variadic keyword parameters cannot' 2441 ' have default values'): 2442 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD, 2443 default=42) 2444 with self.assertRaisesRegex(ValueError, 2445 "value 5 is not a valid Parameter.kind"): 2446 inspect.Parameter("bar", kind=5, default=42) 2447 2448 with self.assertRaisesRegex(TypeError, 2449 'name must be a str, not a int'): 2450 inspect.Parameter(123, kind=4) 2451 2452class TestGetcallargsMethods(TestGetcallargsFunctions): 2453 2454 def setUp(self): 2455 class Foo(object): 2456 pass 2457 self.cls = Foo 2458 self.inst = Foo() 2459 2460 def makeCallable(self, signature): 2461 assert 'self' not in signature 2462 mk = super(TestGetcallargsMethods, self).makeCallable 2463 self.cls.method = mk('self, ' + signature) 2464 return self.inst.method 2465 2466class TestGetcallargsUnboundMethods(TestGetcallargsMethods): 2467 2468 def makeCallable(self, signature): 2469 super(TestGetcallargsUnboundMethods, self).makeCallable(signature) 2470 return self.cls.method 2471 2472 def assertEqualCallArgs(self, func, call_params_string, locs=None): 2473 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs( 2474 *self._getAssertEqualParams(func, call_params_string, locs)) 2475 2476 def assertEqualException(self, func, call_params_string, locs=None): 2477 return super(TestGetcallargsUnboundMethods, self).assertEqualException( 2478 *self._getAssertEqualParams(func, call_params_string, locs)) 2479 2480 def _getAssertEqualParams(self, func, call_params_string, locs=None): 2481 assert 'inst' not in call_params_string 2482 locs = dict(locs or {}, inst=self.inst) 2483 return (func, 'inst,' + call_params_string, locs) 2484 2485 2486class TestGetattrStatic(unittest.TestCase): 2487 2488 def test_basic(self): 2489 class Thing(object): 2490 x = object() 2491 2492 thing = Thing() 2493 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x) 2494 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x) 2495 with self.assertRaises(AttributeError): 2496 inspect.getattr_static(thing, 'y') 2497 2498 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3) 2499 2500 def test_inherited(self): 2501 class Thing(object): 2502 x = object() 2503 class OtherThing(Thing): 2504 pass 2505 2506 something = OtherThing() 2507 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x) 2508 2509 def test_instance_attr(self): 2510 class Thing(object): 2511 x = 2 2512 def __init__(self, x): 2513 self.x = x 2514 thing = Thing(3) 2515 self.assertEqual(inspect.getattr_static(thing, 'x'), 3) 2516 del thing.x 2517 self.assertEqual(inspect.getattr_static(thing, 'x'), 2) 2518 2519 def test_property(self): 2520 class Thing(object): 2521 @property 2522 def x(self): 2523 raise AttributeError("I'm pretending not to exist") 2524 thing = Thing() 2525 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x) 2526 2527 def test_descriptor_raises_AttributeError(self): 2528 class descriptor(object): 2529 def __get__(*_): 2530 raise AttributeError("I'm pretending not to exist") 2531 desc = descriptor() 2532 class Thing(object): 2533 x = desc 2534 thing = Thing() 2535 self.assertEqual(inspect.getattr_static(thing, 'x'), desc) 2536 2537 def test_classAttribute(self): 2538 class Thing(object): 2539 x = object() 2540 2541 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x) 2542 2543 def test_classVirtualAttribute(self): 2544 class Thing(object): 2545 @types.DynamicClassAttribute 2546 def x(self): 2547 return self._x 2548 _x = object() 2549 2550 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x']) 2551 2552 def test_inherited_classattribute(self): 2553 class Thing(object): 2554 x = object() 2555 class OtherThing(Thing): 2556 pass 2557 2558 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x) 2559 2560 def test_slots(self): 2561 class Thing(object): 2562 y = 'bar' 2563 __slots__ = ['x'] 2564 def __init__(self): 2565 self.x = 'foo' 2566 thing = Thing() 2567 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x) 2568 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar') 2569 2570 del thing.x 2571 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x) 2572 2573 def test_metaclass(self): 2574 class meta(type): 2575 attr = 'foo' 2576 class Thing(object, metaclass=meta): 2577 pass 2578 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo') 2579 2580 class sub(meta): 2581 pass 2582 class OtherThing(object, metaclass=sub): 2583 x = 3 2584 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo') 2585 2586 class OtherOtherThing(OtherThing): 2587 pass 2588 # this test is odd, but it was added as it exposed a bug 2589 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3) 2590 2591 def test_no_dict_no_slots(self): 2592 self.assertEqual(inspect.getattr_static(1, 'foo', None), None) 2593 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None) 2594 2595 def test_no_dict_no_slots_instance_member(self): 2596 # returns descriptor 2597 with open(__file__, encoding='utf-8') as handle: 2598 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name) 2599 2600 def test_inherited_slots(self): 2601 # returns descriptor 2602 class Thing(object): 2603 __slots__ = ['x'] 2604 def __init__(self): 2605 self.x = 'foo' 2606 2607 class OtherThing(Thing): 2608 pass 2609 # it would be nice if this worked... 2610 # we get the descriptor instead of the instance attribute 2611 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x) 2612 2613 def test_descriptor(self): 2614 class descriptor(object): 2615 def __get__(self, instance, owner): 2616 return 3 2617 class Foo(object): 2618 d = descriptor() 2619 2620 foo = Foo() 2621 2622 # for a non data descriptor we return the instance attribute 2623 foo.__dict__['d'] = 1 2624 self.assertEqual(inspect.getattr_static(foo, 'd'), 1) 2625 2626 # if the descriptor is a data-descriptor we should return the 2627 # descriptor 2628 descriptor.__set__ = lambda s, i, v: None 2629 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d']) 2630 2631 del descriptor.__set__ 2632 descriptor.__delete__ = lambda s, i, o: None 2633 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d']) 2634 2635 def test_metaclass_with_descriptor(self): 2636 class descriptor(object): 2637 def __get__(self, instance, owner): 2638 return 3 2639 class meta(type): 2640 d = descriptor() 2641 class Thing(object, metaclass=meta): 2642 pass 2643 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d']) 2644 2645 2646 def test_class_as_property(self): 2647 class Base(object): 2648 foo = 3 2649 2650 class Something(Base): 2651 executed = False 2652 @property 2653 def __class__(self): 2654 self.executed = True 2655 return object 2656 2657 instance = Something() 2658 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3) 2659 self.assertFalse(instance.executed) 2660 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3) 2661 2662 def test_mro_as_property(self): 2663 class Meta(type): 2664 @property 2665 def __mro__(self): 2666 return (object,) 2667 2668 class Base(object): 2669 foo = 3 2670 2671 class Something(Base, metaclass=Meta): 2672 pass 2673 2674 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3) 2675 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3) 2676 2677 def test_dict_as_property(self): 2678 test = self 2679 test.called = False 2680 2681 class Foo(dict): 2682 a = 3 2683 @property 2684 def __dict__(self): 2685 test.called = True 2686 return {} 2687 2688 foo = Foo() 2689 foo.a = 4 2690 self.assertEqual(inspect.getattr_static(foo, 'a'), 3) 2691 self.assertFalse(test.called) 2692 2693 class Bar(Foo): pass 2694 2695 bar = Bar() 2696 bar.a = 5 2697 self.assertEqual(inspect.getattr_static(bar, 'a'), 3) 2698 self.assertFalse(test.called) 2699 2700 def test_mutated_mro(self): 2701 test = self 2702 test.called = False 2703 2704 class Foo(dict): 2705 a = 3 2706 @property 2707 def __dict__(self): 2708 test.called = True 2709 return {} 2710 2711 class Bar(dict): 2712 a = 4 2713 2714 class Baz(Bar): pass 2715 2716 baz = Baz() 2717 self.assertEqual(inspect.getattr_static(baz, 'a'), 4) 2718 Baz.__bases__ = (Foo,) 2719 self.assertEqual(inspect.getattr_static(baz, 'a'), 3) 2720 self.assertFalse(test.called) 2721 2722 def test_custom_object_dict(self): 2723 test = self 2724 test.called = False 2725 2726 class Custom(dict): 2727 def get(self, key, default=None): 2728 test.called = True 2729 super().get(key, default) 2730 2731 class Foo(object): 2732 a = 3 2733 foo = Foo() 2734 foo.__dict__ = Custom() 2735 self.assertEqual(inspect.getattr_static(foo, 'a'), 3) 2736 self.assertFalse(test.called) 2737 2738 def test_metaclass_dict_as_property(self): 2739 class Meta(type): 2740 @property 2741 def __dict__(self): 2742 self.executed = True 2743 2744 class Thing(metaclass=Meta): 2745 executed = False 2746 2747 def __init__(self): 2748 self.spam = 42 2749 2750 instance = Thing() 2751 self.assertEqual(inspect.getattr_static(instance, "spam"), 42) 2752 self.assertFalse(Thing.executed) 2753 2754 def test_module(self): 2755 sentinel = object() 2756 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel), 2757 sentinel) 2758 2759 def test_metaclass_with_metaclass_with_dict_as_property(self): 2760 class MetaMeta(type): 2761 @property 2762 def __dict__(self): 2763 self.executed = True 2764 return dict(spam=42) 2765 2766 class Meta(type, metaclass=MetaMeta): 2767 executed = False 2768 2769 class Thing(metaclass=Meta): 2770 pass 2771 2772 with self.assertRaises(AttributeError): 2773 inspect.getattr_static(Thing, "spam") 2774 self.assertFalse(Thing.executed) 2775 2776 def test_custom___getattr__(self): 2777 test = self 2778 test.called = False 2779 2780 class Foo: 2781 def __getattr__(self, attr): 2782 test.called = True 2783 return {} 2784 2785 with self.assertRaises(AttributeError): 2786 inspect.getattr_static(Foo(), 'whatever') 2787 2788 self.assertFalse(test.called) 2789 2790 def test_custom___getattribute__(self): 2791 test = self 2792 test.called = False 2793 2794 class Foo: 2795 def __getattribute__(self, attr): 2796 test.called = True 2797 return {} 2798 2799 with self.assertRaises(AttributeError): 2800 inspect.getattr_static(Foo(), 'really_could_be_anything') 2801 2802 self.assertFalse(test.called) 2803 2804 @suppress_immortalization() 2805 def test_cache_does_not_cause_classes_to_persist(self): 2806 # regression test for gh-118013: 2807 # check that the internal _shadowed_dict cache does not cause 2808 # dynamically created classes to have extended lifetimes even 2809 # when no other strong references to those classes remain. 2810 # Since these classes can themselves hold strong references to 2811 # other objects, this can cause unexpected memory consumption. 2812 class Foo: pass 2813 Foo.instance = Foo() 2814 weakref_to_class = weakref.ref(Foo) 2815 inspect.getattr_static(Foo.instance, 'whatever', 'irrelevant') 2816 del Foo 2817 gc.collect() 2818 self.assertIsNone(weakref_to_class()) 2819 2820 2821class TestGetGeneratorState(unittest.TestCase): 2822 2823 def setUp(self): 2824 def number_generator(): 2825 for number in range(5): 2826 yield number 2827 self.generator = number_generator() 2828 2829 def _generatorstate(self): 2830 return inspect.getgeneratorstate(self.generator) 2831 2832 def test_created(self): 2833 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED) 2834 2835 def test_suspended(self): 2836 next(self.generator) 2837 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED) 2838 2839 def test_closed_after_exhaustion(self): 2840 for i in self.generator: 2841 pass 2842 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED) 2843 2844 def test_closed_after_immediate_exception(self): 2845 with self.assertRaises(RuntimeError): 2846 self.generator.throw(RuntimeError) 2847 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED) 2848 2849 def test_closed_after_close(self): 2850 self.generator.close() 2851 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED) 2852 2853 def test_running(self): 2854 # As mentioned on issue #10220, checking for the RUNNING state only 2855 # makes sense inside the generator itself. 2856 # The following generator checks for this by using the closure's 2857 # reference to self and the generator state checking helper method 2858 def running_check_generator(): 2859 for number in range(5): 2860 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING) 2861 yield number 2862 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING) 2863 self.generator = running_check_generator() 2864 # Running up to the first yield 2865 next(self.generator) 2866 # Running after the first yield 2867 next(self.generator) 2868 2869 def test_easy_debugging(self): 2870 # repr() and str() of a generator state should contain the state name 2871 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split() 2872 for name in names: 2873 state = getattr(inspect, name) 2874 self.assertIn(name, repr(state)) 2875 self.assertIn(name, str(state)) 2876 2877 def test_getgeneratorlocals(self): 2878 def each(lst, a=None): 2879 b=(1, 2, 3) 2880 for v in lst: 2881 if v == 3: 2882 c = 12 2883 yield v 2884 2885 numbers = each([1, 2, 3]) 2886 self.assertEqual(inspect.getgeneratorlocals(numbers), 2887 {'a': None, 'lst': [1, 2, 3]}) 2888 next(numbers) 2889 self.assertEqual(inspect.getgeneratorlocals(numbers), 2890 {'a': None, 'lst': [1, 2, 3], 'v': 1, 2891 'b': (1, 2, 3)}) 2892 next(numbers) 2893 self.assertEqual(inspect.getgeneratorlocals(numbers), 2894 {'a': None, 'lst': [1, 2, 3], 'v': 2, 2895 'b': (1, 2, 3)}) 2896 next(numbers) 2897 self.assertEqual(inspect.getgeneratorlocals(numbers), 2898 {'a': None, 'lst': [1, 2, 3], 'v': 3, 2899 'b': (1, 2, 3), 'c': 12}) 2900 try: 2901 next(numbers) 2902 except StopIteration: 2903 pass 2904 self.assertEqual(inspect.getgeneratorlocals(numbers), {}) 2905 2906 def test_getgeneratorlocals_empty(self): 2907 def yield_one(): 2908 yield 1 2909 one = yield_one() 2910 self.assertEqual(inspect.getgeneratorlocals(one), {}) 2911 try: 2912 next(one) 2913 except StopIteration: 2914 pass 2915 self.assertEqual(inspect.getgeneratorlocals(one), {}) 2916 2917 def test_getgeneratorlocals_error(self): 2918 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1) 2919 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True) 2920 self.assertRaises(TypeError, inspect.getgeneratorlocals, set) 2921 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3)) 2922 2923 2924class TestGetCoroutineState(unittest.TestCase): 2925 2926 def setUp(self): 2927 @types.coroutine 2928 def number_coroutine(): 2929 for number in range(5): 2930 yield number 2931 async def coroutine(): 2932 await number_coroutine() 2933 self.coroutine = coroutine() 2934 2935 def tearDown(self): 2936 self.coroutine.close() 2937 2938 def _coroutinestate(self): 2939 return inspect.getcoroutinestate(self.coroutine) 2940 2941 def test_created(self): 2942 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED) 2943 2944 def test_suspended(self): 2945 self.coroutine.send(None) 2946 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED) 2947 2948 def test_closed_after_exhaustion(self): 2949 while True: 2950 try: 2951 self.coroutine.send(None) 2952 except StopIteration: 2953 break 2954 2955 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED) 2956 2957 def test_closed_after_immediate_exception(self): 2958 with self.assertRaises(RuntimeError): 2959 self.coroutine.throw(RuntimeError) 2960 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED) 2961 2962 def test_closed_after_close(self): 2963 self.coroutine.close() 2964 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED) 2965 2966 def test_easy_debugging(self): 2967 # repr() and str() of a coroutine state should contain the state name 2968 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split() 2969 for name in names: 2970 state = getattr(inspect, name) 2971 self.assertIn(name, repr(state)) 2972 self.assertIn(name, str(state)) 2973 2974 def test_getcoroutinelocals(self): 2975 @types.coroutine 2976 def gencoro(): 2977 yield 2978 2979 gencoro = gencoro() 2980 async def func(a=None): 2981 b = 'spam' 2982 await gencoro 2983 2984 coro = func() 2985 self.assertEqual(inspect.getcoroutinelocals(coro), 2986 {'a': None, 'gencoro': gencoro}) 2987 coro.send(None) 2988 self.assertEqual(inspect.getcoroutinelocals(coro), 2989 {'a': None, 'gencoro': gencoro, 'b': 'spam'}) 2990 2991 2992@support.requires_working_socket() 2993class TestGetAsyncGenState(unittest.IsolatedAsyncioTestCase): 2994 2995 def setUp(self): 2996 async def number_asyncgen(): 2997 for number in range(5): 2998 yield number 2999 self.asyncgen = number_asyncgen() 3000 3001 async def asyncTearDown(self): 3002 await self.asyncgen.aclose() 3003 3004 def _asyncgenstate(self): 3005 return inspect.getasyncgenstate(self.asyncgen) 3006 3007 def test_created(self): 3008 self.assertEqual(self._asyncgenstate(), inspect.AGEN_CREATED) 3009 3010 async def test_suspended(self): 3011 value = await anext(self.asyncgen) 3012 self.assertEqual(self._asyncgenstate(), inspect.AGEN_SUSPENDED) 3013 self.assertEqual(value, 0) 3014 3015 async def test_closed_after_exhaustion(self): 3016 countdown = 7 3017 with self.assertRaises(StopAsyncIteration): 3018 while countdown := countdown - 1: 3019 await anext(self.asyncgen) 3020 self.assertEqual(countdown, 1) 3021 self.assertEqual(self._asyncgenstate(), inspect.AGEN_CLOSED) 3022 3023 async def test_closed_after_immediate_exception(self): 3024 with self.assertRaises(RuntimeError): 3025 await self.asyncgen.athrow(RuntimeError) 3026 self.assertEqual(self._asyncgenstate(), inspect.AGEN_CLOSED) 3027 3028 async def test_running(self): 3029 async def running_check_asyncgen(): 3030 for number in range(5): 3031 self.assertEqual(self._asyncgenstate(), inspect.AGEN_RUNNING) 3032 yield number 3033 self.assertEqual(self._asyncgenstate(), inspect.AGEN_RUNNING) 3034 self.asyncgen = running_check_asyncgen() 3035 # Running up to the first yield 3036 await anext(self.asyncgen) 3037 self.assertEqual(self._asyncgenstate(), inspect.AGEN_SUSPENDED) 3038 # Running after the first yield 3039 await anext(self.asyncgen) 3040 self.assertEqual(self._asyncgenstate(), inspect.AGEN_SUSPENDED) 3041 3042 def test_easy_debugging(self): 3043 # repr() and str() of a asyncgen state should contain the state name 3044 names = 'AGEN_CREATED AGEN_RUNNING AGEN_SUSPENDED AGEN_CLOSED'.split() 3045 for name in names: 3046 state = getattr(inspect, name) 3047 self.assertIn(name, repr(state)) 3048 self.assertIn(name, str(state)) 3049 3050 async def test_getasyncgenlocals(self): 3051 async def each(lst, a=None): 3052 b=(1, 2, 3) 3053 for v in lst: 3054 if v == 3: 3055 c = 12 3056 yield v 3057 3058 numbers = each([1, 2, 3]) 3059 self.assertEqual(inspect.getasyncgenlocals(numbers), 3060 {'a': None, 'lst': [1, 2, 3]}) 3061 await anext(numbers) 3062 self.assertEqual(inspect.getasyncgenlocals(numbers), 3063 {'a': None, 'lst': [1, 2, 3], 'v': 1, 3064 'b': (1, 2, 3)}) 3065 await anext(numbers) 3066 self.assertEqual(inspect.getasyncgenlocals(numbers), 3067 {'a': None, 'lst': [1, 2, 3], 'v': 2, 3068 'b': (1, 2, 3)}) 3069 await anext(numbers) 3070 self.assertEqual(inspect.getasyncgenlocals(numbers), 3071 {'a': None, 'lst': [1, 2, 3], 'v': 3, 3072 'b': (1, 2, 3), 'c': 12}) 3073 with self.assertRaises(StopAsyncIteration): 3074 await anext(numbers) 3075 self.assertEqual(inspect.getasyncgenlocals(numbers), {}) 3076 3077 async def test_getasyncgenlocals_empty(self): 3078 async def yield_one(): 3079 yield 1 3080 one = yield_one() 3081 self.assertEqual(inspect.getasyncgenlocals(one), {}) 3082 await anext(one) 3083 self.assertEqual(inspect.getasyncgenlocals(one), {}) 3084 with self.assertRaises(StopAsyncIteration): 3085 await anext(one) 3086 self.assertEqual(inspect.getasyncgenlocals(one), {}) 3087 3088 def test_getasyncgenlocals_error(self): 3089 self.assertRaises(TypeError, inspect.getasyncgenlocals, 1) 3090 self.assertRaises(TypeError, inspect.getasyncgenlocals, lambda x: True) 3091 self.assertRaises(TypeError, inspect.getasyncgenlocals, set) 3092 self.assertRaises(TypeError, inspect.getasyncgenlocals, (2,3)) 3093 3094 3095class MySignature(inspect.Signature): 3096 # Top-level to make it picklable; 3097 # used in test_signature_object_pickle 3098 pass 3099 3100class MyParameter(inspect.Parameter): 3101 # Top-level to make it picklable; 3102 # used in test_signature_object_pickle 3103 pass 3104 3105 3106 3107class TestSignatureObject(unittest.TestCase): 3108 @staticmethod 3109 def signature(func, **kw): 3110 sig = inspect.signature(func, **kw) 3111 return (tuple((param.name, 3112 (... if param.default is param.empty else param.default), 3113 (... if param.annotation is param.empty 3114 else param.annotation), 3115 str(param.kind).lower()) 3116 for param in sig.parameters.values()), 3117 (... if sig.return_annotation is sig.empty 3118 else sig.return_annotation)) 3119 3120 def test_signature_object(self): 3121 S = inspect.Signature 3122 P = inspect.Parameter 3123 3124 self.assertEqual(str(S()), '()') 3125 self.assertEqual(repr(S().parameters), 'mappingproxy(OrderedDict())') 3126 3127 def test(po, /, pk, pkd=100, *args, ko, kod=10, **kwargs): 3128 pass 3129 3130 sig = inspect.signature(test) 3131 self.assertTrue(repr(sig).startswith('<Signature')) 3132 self.assertTrue('(po, /, pk' in repr(sig)) 3133 3134 # We need two functions, because it is impossible to represent 3135 # all param kinds in a single one. 3136 def test2(pod=42, /): 3137 pass 3138 3139 sig2 = inspect.signature(test2) 3140 self.assertTrue(repr(sig2).startswith('<Signature')) 3141 self.assertTrue('(pod=42, /)' in repr(sig2)) 3142 3143 po = sig.parameters['po'] 3144 pod = sig2.parameters['pod'] 3145 pk = sig.parameters['pk'] 3146 pkd = sig.parameters['pkd'] 3147 args = sig.parameters['args'] 3148 ko = sig.parameters['ko'] 3149 kod = sig.parameters['kod'] 3150 kwargs = sig.parameters['kwargs'] 3151 3152 S((po, pk, args, ko, kwargs)) 3153 S((po, pk, ko, kod)) 3154 S((po, pod, ko)) 3155 S((po, pod, kod)) 3156 S((pod, ko, kod)) 3157 S((pod, kod)) 3158 S((pod, args, kod, kwargs)) 3159 # keyword-only parameters without default values 3160 # can follow keyword-only parameters with default values: 3161 S((kod, ko)) 3162 S((kod, ko, kwargs)) 3163 S((args, kod, ko)) 3164 3165 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 3166 S((pk, po, args, ko, kwargs)) 3167 3168 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 3169 S((po, args, pk, ko, kwargs)) 3170 3171 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 3172 S((args, po, pk, ko, kwargs)) 3173 3174 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 3175 S((po, pk, args, kwargs, ko)) 3176 3177 kwargs2 = kwargs.replace(name='args') 3178 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'): 3179 S((po, pk, args, kwargs2, ko)) 3180 3181 with self.assertRaisesRegex(ValueError, 'follows default argument'): 3182 S((pod, po)) 3183 3184 with self.assertRaisesRegex(ValueError, 'follows default argument'): 3185 S((pod, pk)) 3186 3187 with self.assertRaisesRegex(ValueError, 'follows default argument'): 3188 S((po, pod, pk)) 3189 3190 with self.assertRaisesRegex(ValueError, 'follows default argument'): 3191 S((po, pkd, pk)) 3192 3193 with self.assertRaisesRegex(ValueError, 'follows default argument'): 3194 S((pkd, pk)) 3195 3196 def test_signature_object_pickle(self): 3197 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass 3198 foo_partial = functools.partial(foo, a=1) 3199 3200 sig = inspect.signature(foo_partial) 3201 3202 for ver in range(pickle.HIGHEST_PROTOCOL + 1): 3203 with self.subTest(pickle_ver=ver, subclass=False): 3204 sig_pickled = pickle.loads(pickle.dumps(sig, ver)) 3205 self.assertEqual(sig, sig_pickled) 3206 3207 # Test that basic sub-classing works 3208 sig = inspect.signature(foo) 3209 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY) 3210 myparams = collections.OrderedDict(sig.parameters, a=myparam) 3211 mysig = MySignature().replace(parameters=myparams.values(), 3212 return_annotation=sig.return_annotation) 3213 self.assertTrue(isinstance(mysig, MySignature)) 3214 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter)) 3215 3216 for ver in range(pickle.HIGHEST_PROTOCOL + 1): 3217 with self.subTest(pickle_ver=ver, subclass=True): 3218 sig_pickled = pickle.loads(pickle.dumps(mysig, ver)) 3219 self.assertEqual(mysig, sig_pickled) 3220 self.assertTrue(isinstance(sig_pickled, MySignature)) 3221 self.assertTrue(isinstance(sig_pickled.parameters['z'], 3222 MyParameter)) 3223 3224 def test_signature_immutability(self): 3225 def test(a): 3226 pass 3227 sig = inspect.signature(test) 3228 3229 with self.assertRaises(AttributeError): 3230 sig.foo = 'bar' 3231 3232 with self.assertRaises(TypeError): 3233 sig.parameters['a'] = None 3234 3235 def test_signature_on_noarg(self): 3236 def test(): 3237 pass 3238 self.assertEqual(self.signature(test), ((), ...)) 3239 3240 def test_signature_on_wargs(self): 3241 def test(a, b:'foo') -> 123: 3242 pass 3243 self.assertEqual(self.signature(test), 3244 ((('a', ..., ..., "positional_or_keyword"), 3245 ('b', ..., 'foo', "positional_or_keyword")), 3246 123)) 3247 3248 def test_signature_on_wkwonly(self): 3249 def test(*, a:float, b:str) -> int: 3250 pass 3251 self.assertEqual(self.signature(test), 3252 ((('a', ..., float, "keyword_only"), 3253 ('b', ..., str, "keyword_only")), 3254 int)) 3255 3256 def test_signature_on_complex_args(self): 3257 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int): 3258 pass 3259 self.assertEqual(self.signature(test), 3260 ((('a', ..., ..., "positional_or_keyword"), 3261 ('b', 10, 'foo', "positional_or_keyword"), 3262 ('args', ..., 'bar', "var_positional"), 3263 ('spam', ..., 'baz', "keyword_only"), 3264 ('ham', 123, ..., "keyword_only"), 3265 ('kwargs', ..., int, "var_keyword")), 3266 ...)) 3267 3268 def test_signature_without_self(self): 3269 def test_args_only(*args): # NOQA 3270 pass 3271 3272 def test_args_kwargs_only(*args, **kwargs): # NOQA 3273 pass 3274 3275 class A: 3276 @classmethod 3277 def test_classmethod(*args): # NOQA 3278 pass 3279 3280 @staticmethod 3281 def test_staticmethod(*args): # NOQA 3282 pass 3283 3284 f1 = functools.partialmethod((test_classmethod), 1) 3285 f2 = functools.partialmethod((test_args_only), 1) 3286 f3 = functools.partialmethod((test_staticmethod), 1) 3287 f4 = functools.partialmethod((test_args_kwargs_only),1) 3288 3289 self.assertEqual(self.signature(test_args_only), 3290 ((('args', ..., ..., 'var_positional'),), ...)) 3291 self.assertEqual(self.signature(test_args_kwargs_only), 3292 ((('args', ..., ..., 'var_positional'), 3293 ('kwargs', ..., ..., 'var_keyword')), ...)) 3294 self.assertEqual(self.signature(A.f1), 3295 ((('args', ..., ..., 'var_positional'),), ...)) 3296 self.assertEqual(self.signature(A.f2), 3297 ((('args', ..., ..., 'var_positional'),), ...)) 3298 self.assertEqual(self.signature(A.f3), 3299 ((('args', ..., ..., 'var_positional'),), ...)) 3300 self.assertEqual(self.signature(A.f4), 3301 ((('args', ..., ..., 'var_positional'), 3302 ('kwargs', ..., ..., 'var_keyword')), ...)) 3303 @cpython_only 3304 @unittest.skipIf(MISSING_C_DOCSTRINGS, 3305 "Signature information for builtins requires docstrings") 3306 def test_signature_on_builtins(self): 3307 _testcapi = import_helper.import_module("_testcapi") 3308 3309 def test_unbound_method(o): 3310 """Use this to test unbound methods (things that should have a self)""" 3311 signature = inspect.signature(o) 3312 self.assertTrue(isinstance(signature, inspect.Signature)) 3313 self.assertEqual(list(signature.parameters.values())[0].name, 'self') 3314 return signature 3315 3316 def test_callable(o): 3317 """Use this to test bound methods or normal callables (things that don't expect self)""" 3318 signature = inspect.signature(o) 3319 self.assertTrue(isinstance(signature, inspect.Signature)) 3320 if signature.parameters: 3321 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self') 3322 return signature 3323 3324 signature = test_callable(_testcapi.docstring_with_signature_with_defaults) 3325 def p(name): return signature.parameters[name].default 3326 self.assertEqual(p('s'), 'avocado') 3327 self.assertEqual(p('b'), b'bytes') 3328 self.assertEqual(p('d'), 3.14) 3329 self.assertEqual(p('i'), 35) 3330 self.assertEqual(p('n'), None) 3331 self.assertEqual(p('t'), True) 3332 self.assertEqual(p('f'), False) 3333 self.assertEqual(p('local'), 3) 3334 self.assertEqual(p('sys'), sys.maxsize) 3335 self.assertEqual(p('exp'), sys.maxsize - 1) 3336 3337 test_callable(object) 3338 3339 # normal method 3340 # (PyMethodDescr_Type, "method_descriptor") 3341 test_unbound_method(_pickle.Pickler.dump) 3342 d = _pickle.Pickler(io.StringIO()) 3343 test_callable(d.dump) 3344 3345 # static method 3346 test_callable(bytes.maketrans) 3347 test_callable(b'abc'.maketrans) 3348 3349 # class method 3350 test_callable(dict.fromkeys) 3351 test_callable({}.fromkeys) 3352 3353 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor") 3354 test_unbound_method(type.__call__) 3355 test_unbound_method(int.__add__) 3356 test_callable((3).__add__) 3357 3358 # _PyMethodWrapper_Type 3359 # support for 'method-wrapper' 3360 test_callable(min.__call__) 3361 3362 # This doesn't work now. 3363 # (We don't have a valid signature for "type" in 3.4) 3364 class ThisWorksNow: 3365 __call__ = type 3366 # TODO: Support type. 3367 self.assertEqual(ThisWorksNow()(1), int) 3368 self.assertEqual(ThisWorksNow()('A', (), {}).__name__, 'A') 3369 with self.assertRaisesRegex(ValueError, "no signature found"): 3370 test_callable(ThisWorksNow()) 3371 3372 # Regression test for issue #20786 3373 test_unbound_method(dict.__delitem__) 3374 test_unbound_method(property.__delete__) 3375 3376 # Regression test for issue #20586 3377 test_callable(_testcapi.docstring_with_signature_but_no_doc) 3378 3379 # Regression test for gh-104955 3380 method = bytearray.__release_buffer__ 3381 sig = test_unbound_method(method) 3382 self.assertEqual(list(sig.parameters), ['self', 'buffer']) 3383 3384 @cpython_only 3385 @unittest.skipIf(MISSING_C_DOCSTRINGS, 3386 "Signature information for builtins requires docstrings") 3387 def test_signature_on_decorated_builtins(self): 3388 _testcapi = import_helper.import_module("_testcapi") 3389 func = _testcapi.docstring_with_signature_with_defaults 3390 3391 def decorator(func): 3392 @functools.wraps(func) 3393 def wrapper(*args, **kwargs) -> int: 3394 return func(*args, **kwargs) 3395 return wrapper 3396 3397 decorated_func = decorator(func) 3398 3399 self.assertEqual(inspect.signature(func), 3400 inspect.signature(decorated_func)) 3401 3402 def wrapper_like(*args, **kwargs) -> int: pass 3403 self.assertEqual(inspect.signature(decorated_func, 3404 follow_wrapped=False), 3405 inspect.signature(wrapper_like)) 3406 3407 @cpython_only 3408 def test_signature_on_builtins_no_signature(self): 3409 _testcapi = import_helper.import_module("_testcapi") 3410 with self.assertRaisesRegex(ValueError, 3411 'no signature found for builtin'): 3412 inspect.signature(_testcapi.docstring_no_signature) 3413 3414 with self.assertRaisesRegex(ValueError, 3415 'no signature found for builtin'): 3416 inspect.signature(str) 3417 3418 cls = _testcapi.DocStringNoSignatureTest 3419 obj = _testcapi.DocStringNoSignatureTest() 3420 tests = [ 3421 (_testcapi.docstring_no_signature_noargs, meth_noargs), 3422 (_testcapi.docstring_no_signature_o, meth_o), 3423 (cls.meth_noargs, meth_self_noargs), 3424 (cls.meth_o, meth_self_o), 3425 (obj.meth_noargs, meth_noargs), 3426 (obj.meth_o, meth_o), 3427 (cls.meth_noargs_class, meth_noargs), 3428 (cls.meth_o_class, meth_o), 3429 (cls.meth_noargs_static, meth_noargs), 3430 (cls.meth_o_static, meth_o), 3431 (cls.meth_noargs_coexist, meth_self_noargs), 3432 (cls.meth_o_coexist, meth_self_o), 3433 3434 (time.time, meth_noargs), 3435 (str.lower, meth_self_noargs), 3436 (''.lower, meth_noargs), 3437 (set.add, meth_self_o), 3438 (set().add, meth_o), 3439 (set.__contains__, meth_self_o), 3440 (set().__contains__, meth_o), 3441 (datetime.datetime.__dict__['utcnow'], meth_type_noargs), 3442 (datetime.datetime.utcnow, meth_noargs), 3443 (dict.__dict__['__class_getitem__'], meth_type_o), 3444 (dict.__class_getitem__, meth_o), 3445 ] 3446 try: 3447 import _stat 3448 except ImportError: 3449 # if the _stat extension is not available, stat.S_IMODE() is 3450 # implemented in Python, not in C 3451 pass 3452 else: 3453 tests.append((stat.S_IMODE, meth_o)) 3454 for builtin, template in tests: 3455 with self.subTest(builtin): 3456 self.assertEqual(inspect.signature(builtin), 3457 inspect.signature(template)) 3458 3459 @unittest.skipIf(MISSING_C_DOCSTRINGS, 3460 "Signature information for builtins requires docstrings") 3461 def test_signature_parsing_with_defaults(self): 3462 _testcapi = import_helper.import_module("_testcapi") 3463 meth = _testcapi.DocStringUnrepresentableSignatureTest.with_default 3464 self.assertEqual(str(inspect.signature(meth)), '(self, /, x=1)') 3465 3466 def test_signature_on_non_function(self): 3467 with self.assertRaisesRegex(TypeError, 'is not a callable object'): 3468 inspect.signature(42) 3469 3470 def test_signature_from_functionlike_object(self): 3471 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs): 3472 pass 3473 3474 class funclike: 3475 # Has to be callable, and have correct 3476 # __code__, __annotations__, __defaults__, __name__, 3477 # and __kwdefaults__ attributes 3478 3479 def __init__(self, func): 3480 self.__name__ = func.__name__ 3481 self.__code__ = func.__code__ 3482 self.__annotations__ = func.__annotations__ 3483 self.__defaults__ = func.__defaults__ 3484 self.__kwdefaults__ = func.__kwdefaults__ 3485 self.func = func 3486 3487 def __call__(self, *args, **kwargs): 3488 return self.func(*args, **kwargs) 3489 3490 sig_func = inspect.Signature.from_callable(func) 3491 3492 sig_funclike = inspect.Signature.from_callable(funclike(func)) 3493 self.assertEqual(sig_funclike, sig_func) 3494 3495 sig_funclike = inspect.signature(funclike(func)) 3496 self.assertEqual(sig_funclike, sig_func) 3497 3498 # If object is not a duck type of function, then 3499 # signature will try to get a signature for its '__call__' 3500 # method 3501 fl = funclike(func) 3502 del fl.__defaults__ 3503 self.assertEqual(self.signature(fl), 3504 ((('args', ..., ..., "var_positional"), 3505 ('kwargs', ..., ..., "var_keyword")), 3506 ...)) 3507 3508 # Test with cython-like builtins: 3509 _orig_isdesc = inspect.ismethoddescriptor 3510 def _isdesc(obj): 3511 if hasattr(obj, '_builtinmock'): 3512 return True 3513 return _orig_isdesc(obj) 3514 3515 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc): 3516 builtin_func = funclike(func) 3517 # Make sure that our mock setup is working 3518 self.assertFalse(inspect.ismethoddescriptor(builtin_func)) 3519 builtin_func._builtinmock = True 3520 self.assertTrue(inspect.ismethoddescriptor(builtin_func)) 3521 self.assertEqual(inspect.signature(builtin_func), sig_func) 3522 3523 def test_signature_functionlike_class(self): 3524 # We only want to duck type function-like objects, 3525 # not classes. 3526 3527 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs): 3528 pass 3529 3530 class funclike: 3531 def __init__(self, marker): 3532 pass 3533 3534 __name__ = func.__name__ 3535 __code__ = func.__code__ 3536 __annotations__ = func.__annotations__ 3537 __defaults__ = func.__defaults__ 3538 __kwdefaults__ = func.__kwdefaults__ 3539 3540 self.assertEqual(str(inspect.signature(funclike)), '(marker)') 3541 3542 def test_signature_on_method(self): 3543 class Test: 3544 def __init__(*args): 3545 pass 3546 def m1(self, arg1, arg2=1) -> int: 3547 pass 3548 def m2(*args): 3549 pass 3550 def __call__(*, a): 3551 pass 3552 3553 self.assertEqual(self.signature(Test().m1), 3554 ((('arg1', ..., ..., "positional_or_keyword"), 3555 ('arg2', 1, ..., "positional_or_keyword")), 3556 int)) 3557 3558 self.assertEqual(self.signature(Test().m2), 3559 ((('args', ..., ..., "var_positional"),), 3560 ...)) 3561 3562 self.assertEqual(self.signature(Test), 3563 ((('args', ..., ..., "var_positional"),), 3564 ...)) 3565 3566 with self.assertRaisesRegex(ValueError, 'invalid method signature'): 3567 self.signature(Test()) 3568 3569 def test_signature_wrapped_bound_method(self): 3570 # Issue 24298 3571 class Test: 3572 def m1(self, arg1, arg2=1) -> int: 3573 pass 3574 @functools.wraps(Test().m1) 3575 def m1d(*args, **kwargs): 3576 pass 3577 self.assertEqual(self.signature(m1d), 3578 ((('arg1', ..., ..., "positional_or_keyword"), 3579 ('arg2', 1, ..., "positional_or_keyword")), 3580 int)) 3581 3582 def test_signature_on_classmethod(self): 3583 self.assertEqual(self.signature(classmethod), 3584 ((('function', ..., ..., "positional_only"),), 3585 ...)) 3586 3587 class Test: 3588 @classmethod 3589 def foo(cls, arg1, *, arg2=1): 3590 pass 3591 3592 meth = Test().foo 3593 self.assertEqual(self.signature(meth), 3594 ((('arg1', ..., ..., "positional_or_keyword"), 3595 ('arg2', 1, ..., "keyword_only")), 3596 ...)) 3597 3598 meth = Test.foo 3599 self.assertEqual(self.signature(meth), 3600 ((('arg1', ..., ..., "positional_or_keyword"), 3601 ('arg2', 1, ..., "keyword_only")), 3602 ...)) 3603 3604 def test_signature_on_staticmethod(self): 3605 self.assertEqual(self.signature(staticmethod), 3606 ((('function', ..., ..., "positional_only"),), 3607 ...)) 3608 3609 class Test: 3610 @staticmethod 3611 def foo(cls, *, arg): 3612 pass 3613 3614 meth = Test().foo 3615 self.assertEqual(self.signature(meth), 3616 ((('cls', ..., ..., "positional_or_keyword"), 3617 ('arg', ..., ..., "keyword_only")), 3618 ...)) 3619 3620 meth = Test.foo 3621 self.assertEqual(self.signature(meth), 3622 ((('cls', ..., ..., "positional_or_keyword"), 3623 ('arg', ..., ..., "keyword_only")), 3624 ...)) 3625 3626 def test_signature_on_partial(self): 3627 from functools import partial 3628 3629 def test(): 3630 pass 3631 3632 self.assertEqual(self.signature(partial(test)), ((), ...)) 3633 3634 with self.assertRaisesRegex(ValueError, "has incorrect arguments"): 3635 inspect.signature(partial(test, 1)) 3636 3637 with self.assertRaisesRegex(ValueError, "has incorrect arguments"): 3638 inspect.signature(partial(test, a=1)) 3639 3640 def test(a, b, *, c, d): 3641 pass 3642 3643 self.assertEqual(self.signature(partial(test)), 3644 ((('a', ..., ..., "positional_or_keyword"), 3645 ('b', ..., ..., "positional_or_keyword"), 3646 ('c', ..., ..., "keyword_only"), 3647 ('d', ..., ..., "keyword_only")), 3648 ...)) 3649 3650 self.assertEqual(self.signature(partial(test, 1)), 3651 ((('b', ..., ..., "positional_or_keyword"), 3652 ('c', ..., ..., "keyword_only"), 3653 ('d', ..., ..., "keyword_only")), 3654 ...)) 3655 3656 self.assertEqual(self.signature(partial(test, 1, c=2)), 3657 ((('b', ..., ..., "positional_or_keyword"), 3658 ('c', 2, ..., "keyword_only"), 3659 ('d', ..., ..., "keyword_only")), 3660 ...)) 3661 3662 self.assertEqual(self.signature(partial(test, b=1, c=2)), 3663 ((('a', ..., ..., "positional_or_keyword"), 3664 ('b', 1, ..., "keyword_only"), 3665 ('c', 2, ..., "keyword_only"), 3666 ('d', ..., ..., "keyword_only")), 3667 ...)) 3668 3669 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)), 3670 ((('b', 1, ..., "keyword_only"), 3671 ('c', 2, ..., "keyword_only"), 3672 ('d', ..., ..., "keyword_only")), 3673 ...)) 3674 3675 self.assertEqual(self.signature(partial(test, a=1)), 3676 ((('a', 1, ..., "keyword_only"), 3677 ('b', ..., ..., "keyword_only"), 3678 ('c', ..., ..., "keyword_only"), 3679 ('d', ..., ..., "keyword_only")), 3680 ...)) 3681 3682 def test(a, *args, b, **kwargs): 3683 pass 3684 3685 self.assertEqual(self.signature(partial(test, 1)), 3686 ((('args', ..., ..., "var_positional"), 3687 ('b', ..., ..., "keyword_only"), 3688 ('kwargs', ..., ..., "var_keyword")), 3689 ...)) 3690 3691 self.assertEqual(self.signature(partial(test, a=1)), 3692 ((('a', 1, ..., "keyword_only"), 3693 ('b', ..., ..., "keyword_only"), 3694 ('kwargs', ..., ..., "var_keyword")), 3695 ...)) 3696 3697 self.assertEqual(self.signature(partial(test, 1, 2, 3)), 3698 ((('args', ..., ..., "var_positional"), 3699 ('b', ..., ..., "keyword_only"), 3700 ('kwargs', ..., ..., "var_keyword")), 3701 ...)) 3702 3703 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)), 3704 ((('args', ..., ..., "var_positional"), 3705 ('b', ..., ..., "keyword_only"), 3706 ('kwargs', ..., ..., "var_keyword")), 3707 ...)) 3708 3709 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)), 3710 ((('args', ..., ..., "var_positional"), 3711 ('b', 0, ..., "keyword_only"), 3712 ('kwargs', ..., ..., "var_keyword")), 3713 ...)) 3714 3715 self.assertEqual(self.signature(partial(test, b=0)), 3716 ((('a', ..., ..., "positional_or_keyword"), 3717 ('args', ..., ..., "var_positional"), 3718 ('b', 0, ..., "keyword_only"), 3719 ('kwargs', ..., ..., "var_keyword")), 3720 ...)) 3721 3722 self.assertEqual(self.signature(partial(test, b=0, test=1)), 3723 ((('a', ..., ..., "positional_or_keyword"), 3724 ('args', ..., ..., "var_positional"), 3725 ('b', 0, ..., "keyword_only"), 3726 ('kwargs', ..., ..., "var_keyword")), 3727 ...)) 3728 3729 def test(a, b, c:int) -> 42: 3730 pass 3731 3732 sig = test.__signature__ = inspect.signature(test) 3733 3734 self.assertEqual(self.signature(partial(partial(test, 1))), 3735 ((('b', ..., ..., "positional_or_keyword"), 3736 ('c', ..., int, "positional_or_keyword")), 3737 42)) 3738 3739 self.assertEqual(self.signature(partial(partial(test, 1), 2)), 3740 ((('c', ..., int, "positional_or_keyword"),), 3741 42)) 3742 3743 def foo(a): 3744 return a 3745 _foo = partial(partial(foo, a=10), a=20) 3746 self.assertEqual(self.signature(_foo), 3747 ((('a', 20, ..., "keyword_only"),), 3748 ...)) 3749 # check that we don't have any side-effects in signature(), 3750 # and the partial object is still functioning 3751 self.assertEqual(_foo(), 20) 3752 3753 def foo(a, b, c): 3754 return a, b, c 3755 _foo = partial(partial(foo, 1, b=20), b=30) 3756 3757 self.assertEqual(self.signature(_foo), 3758 ((('b', 30, ..., "keyword_only"), 3759 ('c', ..., ..., "keyword_only")), 3760 ...)) 3761 self.assertEqual(_foo(c=10), (1, 30, 10)) 3762 3763 def foo(a, b, c, *, d): 3764 return a, b, c, d 3765 _foo = partial(partial(foo, d=20, c=20), b=10, d=30) 3766 self.assertEqual(self.signature(_foo), 3767 ((('a', ..., ..., "positional_or_keyword"), 3768 ('b', 10, ..., "keyword_only"), 3769 ('c', 20, ..., "keyword_only"), 3770 ('d', 30, ..., "keyword_only"), 3771 ), 3772 ...)) 3773 ba = inspect.signature(_foo).bind(a=200, b=11) 3774 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30)) 3775 3776 def foo(a=1, b=2, c=3): 3777 return a, b, c 3778 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13) 3779 3780 ba = inspect.signature(_foo).bind(a=11) 3781 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13)) 3782 3783 ba = inspect.signature(_foo).bind(11, 12) 3784 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13)) 3785 3786 ba = inspect.signature(_foo).bind(11, b=12) 3787 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13)) 3788 3789 ba = inspect.signature(_foo).bind(b=12) 3790 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13)) 3791 3792 _foo = partial(_foo, b=10, c=20) 3793 ba = inspect.signature(_foo).bind(12) 3794 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20)) 3795 3796 3797 def foo(a, b, /, c, d, **kwargs): 3798 pass 3799 sig = inspect.signature(foo) 3800 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)') 3801 3802 self.assertEqual(self.signature(partial(foo, 1)), 3803 ((('b', ..., ..., 'positional_only'), 3804 ('c', ..., ..., 'positional_or_keyword'), 3805 ('d', ..., ..., 'positional_or_keyword'), 3806 ('kwargs', ..., ..., 'var_keyword')), 3807 ...)) 3808 3809 self.assertEqual(self.signature(partial(foo, 1, 2)), 3810 ((('c', ..., ..., 'positional_or_keyword'), 3811 ('d', ..., ..., 'positional_or_keyword'), 3812 ('kwargs', ..., ..., 'var_keyword')), 3813 ...)) 3814 3815 self.assertEqual(self.signature(partial(foo, 1, 2, 3)), 3816 ((('d', ..., ..., 'positional_or_keyword'), 3817 ('kwargs', ..., ..., 'var_keyword')), 3818 ...)) 3819 3820 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)), 3821 ((('c', 3, ..., 'keyword_only'), 3822 ('d', ..., ..., 'keyword_only'), 3823 ('kwargs', ..., ..., 'var_keyword')), 3824 ...)) 3825 3826 self.assertEqual(self.signature(partial(foo, 1, c=3)), 3827 ((('b', ..., ..., 'positional_only'), 3828 ('c', 3, ..., 'keyword_only'), 3829 ('d', ..., ..., 'keyword_only'), 3830 ('kwargs', ..., ..., 'var_keyword')), 3831 ...)) 3832 3833 def test_signature_on_partialmethod(self): 3834 from functools import partialmethod 3835 3836 class Spam: 3837 def test(): 3838 pass 3839 ham = partialmethod(test) 3840 3841 with self.assertRaisesRegex(ValueError, "has incorrect arguments"): 3842 inspect.signature(Spam.ham) 3843 3844 class Spam: 3845 def test(it, a, *, c) -> 'spam': 3846 pass 3847 ham = partialmethod(test, c=1) 3848 3849 self.assertEqual(self.signature(Spam.ham, eval_str=False), 3850 ((('it', ..., ..., 'positional_or_keyword'), 3851 ('a', ..., ..., 'positional_or_keyword'), 3852 ('c', 1, ..., 'keyword_only')), 3853 'spam')) 3854 3855 self.assertEqual(self.signature(Spam().ham, eval_str=False), 3856 ((('a', ..., ..., 'positional_or_keyword'), 3857 ('c', 1, ..., 'keyword_only')), 3858 'spam')) 3859 3860 class Spam: 3861 def test(self: 'anno', x): 3862 pass 3863 3864 g = partialmethod(test, 1) 3865 3866 self.assertEqual(self.signature(Spam.g, eval_str=False), 3867 ((('self', ..., 'anno', 'positional_or_keyword'),), 3868 ...)) 3869 3870 def test_signature_on_fake_partialmethod(self): 3871 def foo(a): pass 3872 foo.__partialmethod__ = 'spam' 3873 self.assertEqual(str(inspect.signature(foo)), '(a)') 3874 3875 def test_signature_on_decorated(self): 3876 def decorator(func): 3877 @functools.wraps(func) 3878 def wrapper(*args, **kwargs) -> int: 3879 return func(*args, **kwargs) 3880 return wrapper 3881 3882 class Foo: 3883 @decorator 3884 def bar(self, a, b): 3885 pass 3886 3887 bar = decorator(Foo().bar) 3888 3889 self.assertEqual(self.signature(Foo.bar), 3890 ((('self', ..., ..., "positional_or_keyword"), 3891 ('a', ..., ..., "positional_or_keyword"), 3892 ('b', ..., ..., "positional_or_keyword")), 3893 ...)) 3894 3895 self.assertEqual(self.signature(Foo().bar), 3896 ((('a', ..., ..., "positional_or_keyword"), 3897 ('b', ..., ..., "positional_or_keyword")), 3898 ...)) 3899 3900 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False), 3901 ((('args', ..., ..., "var_positional"), 3902 ('kwargs', ..., ..., "var_keyword")), 3903 ...)) # functools.wraps will copy __annotations__ 3904 # from "func" to "wrapper", hence no 3905 # return_annotation 3906 3907 self.assertEqual(self.signature(bar), 3908 ((('a', ..., ..., "positional_or_keyword"), 3909 ('b', ..., ..., "positional_or_keyword")), 3910 ...)) 3911 3912 # Test that we handle method wrappers correctly 3913 def decorator(func): 3914 @functools.wraps(func) 3915 def wrapper(*args, **kwargs) -> int: 3916 return func(42, *args, **kwargs) 3917 sig = inspect.signature(func) 3918 new_params = tuple(sig.parameters.values())[1:] 3919 wrapper.__signature__ = sig.replace(parameters=new_params) 3920 return wrapper 3921 3922 class Foo: 3923 @decorator 3924 def __call__(self, a, b): 3925 pass 3926 3927 self.assertEqual(self.signature(Foo.__call__), 3928 ((('a', ..., ..., "positional_or_keyword"), 3929 ('b', ..., ..., "positional_or_keyword")), 3930 ...)) 3931 3932 self.assertEqual(self.signature(Foo().__call__), 3933 ((('b', ..., ..., "positional_or_keyword"),), 3934 ...)) 3935 3936 # Test we handle __signature__ partway down the wrapper stack 3937 def wrapped_foo_call(): 3938 pass 3939 wrapped_foo_call.__wrapped__ = Foo.__call__ 3940 3941 self.assertEqual(self.signature(wrapped_foo_call), 3942 ((('a', ..., ..., "positional_or_keyword"), 3943 ('b', ..., ..., "positional_or_keyword")), 3944 ...)) 3945 3946 3947 def test_signature_on_class(self): 3948 class C: 3949 def __init__(self, a): 3950 pass 3951 3952 self.assertEqual(self.signature(C), 3953 ((('a', ..., ..., "positional_or_keyword"),), 3954 ...)) 3955 3956 class CM(type): 3957 def __call__(cls, a): 3958 pass 3959 class C(metaclass=CM): 3960 def __init__(self, b): 3961 pass 3962 3963 self.assertEqual(self.signature(C), 3964 ((('a', ..., ..., "positional_or_keyword"),), 3965 ...)) 3966 3967 with self.subTest('classmethod'): 3968 class CM(type): 3969 @classmethod 3970 def __call__(cls, a): 3971 return a 3972 class C(metaclass=CM): 3973 def __init__(self, b): 3974 pass 3975 3976 self.assertEqual(C(1), 1) 3977 self.assertEqual(self.signature(C), 3978 ((('a', ..., ..., "positional_or_keyword"),), 3979 ...)) 3980 3981 with self.subTest('staticmethod'): 3982 class CM(type): 3983 @staticmethod 3984 def __call__(a): 3985 return a 3986 class C(metaclass=CM): 3987 def __init__(self, b): 3988 pass 3989 3990 self.assertEqual(C(1), 1) 3991 self.assertEqual(self.signature(C), 3992 ((('a', ..., ..., "positional_or_keyword"),), 3993 ...)) 3994 3995 with self.subTest('MethodType'): 3996 class A: 3997 def call(self, a): 3998 return a 3999 class CM(type): 4000 __call__ = A().call 4001 class C(metaclass=CM): 4002 def __init__(self, b): 4003 pass 4004 4005 self.assertEqual(C(1), 1) 4006 self.assertEqual(self.signature(C), 4007 ((('a', ..., ..., "positional_or_keyword"),), 4008 ...)) 4009 4010 with self.subTest('partial'): 4011 class CM(type): 4012 __call__ = functools.partial(lambda x, a: (x, a), 2) 4013 class C(metaclass=CM): 4014 def __init__(self, b): 4015 pass 4016 4017 with self.assertWarns(FutureWarning): 4018 self.assertEqual(C(1), (2, 1)) 4019 with self.assertWarns(FutureWarning): 4020 self.assertEqual(self.signature(C), 4021 ((('a', ..., ..., "positional_or_keyword"),), 4022 ...)) 4023 4024 with self.subTest('partialmethod'): 4025 class CM(type): 4026 __call__ = functools.partialmethod(lambda self, x, a: (x, a), 2) 4027 class C(metaclass=CM): 4028 def __init__(self, b): 4029 pass 4030 4031 self.assertEqual(C(1), (2, 1)) 4032 self.assertEqual(self.signature(C), 4033 ((('a', ..., ..., "positional_or_keyword"),), 4034 ...)) 4035 4036 with self.subTest('BuiltinMethodType'): 4037 class CM(type): 4038 __call__ = ':'.join 4039 class C(metaclass=CM): 4040 def __init__(self, b): 4041 pass 4042 4043 self.assertEqual(C(['a', 'bc']), 'a:bc') 4044 # BUG: Returns '<Signature (b)>' 4045 with self.assertRaises(AssertionError): 4046 self.assertEqual(self.signature(C), self.signature(''.join)) 4047 4048 with self.subTest('MethodWrapperType'): 4049 class CM(type): 4050 __call__ = (2).__pow__ 4051 class C(metaclass=CM): 4052 def __init__(self, b): 4053 pass 4054 4055 self.assertEqual(C(3), 8) 4056 self.assertEqual(C(3, 7), 1) 4057 # BUG: Returns '<Signature (b)>' 4058 with self.assertRaises(AssertionError): 4059 self.assertEqual(self.signature(C), self.signature((0).__pow__)) 4060 4061 class CM(type): 4062 def __new__(mcls, name, bases, dct, *, foo=1): 4063 return super().__new__(mcls, name, bases, dct) 4064 class C(metaclass=CM): 4065 def __init__(self, b): 4066 pass 4067 4068 self.assertEqual(self.signature(C), 4069 ((('b', ..., ..., "positional_or_keyword"),), 4070 ...)) 4071 4072 self.assertEqual(self.signature(CM), 4073 ((('name', ..., ..., "positional_or_keyword"), 4074 ('bases', ..., ..., "positional_or_keyword"), 4075 ('dct', ..., ..., "positional_or_keyword"), 4076 ('foo', 1, ..., "keyword_only")), 4077 ...)) 4078 4079 class CMM(type): 4080 def __new__(mcls, name, bases, dct, *, foo=1): 4081 return super().__new__(mcls, name, bases, dct) 4082 def __call__(cls, nm, bs, dt): 4083 return type(nm, bs, dt) 4084 class CM(type, metaclass=CMM): 4085 def __new__(mcls, name, bases, dct, *, bar=2): 4086 return super().__new__(mcls, name, bases, dct) 4087 class C(metaclass=CM): 4088 def __init__(self, b): 4089 pass 4090 4091 self.assertEqual(self.signature(CMM), 4092 ((('name', ..., ..., "positional_or_keyword"), 4093 ('bases', ..., ..., "positional_or_keyword"), 4094 ('dct', ..., ..., "positional_or_keyword"), 4095 ('foo', 1, ..., "keyword_only")), 4096 ...)) 4097 4098 self.assertEqual(self.signature(CM), 4099 ((('nm', ..., ..., "positional_or_keyword"), 4100 ('bs', ..., ..., "positional_or_keyword"), 4101 ('dt', ..., ..., "positional_or_keyword")), 4102 ...)) 4103 4104 self.assertEqual(self.signature(C), 4105 ((('b', ..., ..., "positional_or_keyword"),), 4106 ...)) 4107 4108 class CM(type): 4109 def __init__(cls, name, bases, dct, *, bar=2): 4110 return super().__init__(name, bases, dct) 4111 class C(metaclass=CM): 4112 def __init__(self, b): 4113 pass 4114 4115 self.assertEqual(self.signature(CM), 4116 ((('name', ..., ..., "positional_or_keyword"), 4117 ('bases', ..., ..., "positional_or_keyword"), 4118 ('dct', ..., ..., "positional_or_keyword"), 4119 ('bar', 2, ..., "keyword_only")), 4120 ...)) 4121 4122 def test_signature_on_class_with_init(self): 4123 class C: 4124 def __init__(self, b): 4125 pass 4126 4127 C(1) # does not raise 4128 self.assertEqual(self.signature(C), 4129 ((('b', ..., ..., "positional_or_keyword"),), 4130 ...)) 4131 4132 with self.subTest('classmethod'): 4133 class C: 4134 @classmethod 4135 def __init__(cls, b): 4136 pass 4137 4138 C(1) # does not raise 4139 self.assertEqual(self.signature(C), 4140 ((('b', ..., ..., "positional_or_keyword"),), 4141 ...)) 4142 4143 with self.subTest('staticmethod'): 4144 class C: 4145 @staticmethod 4146 def __init__(b): 4147 pass 4148 4149 C(1) # does not raise 4150 self.assertEqual(self.signature(C), 4151 ((('b', ..., ..., "positional_or_keyword"),), 4152 ...)) 4153 4154 with self.subTest('MethodType'): 4155 class A: 4156 def call(self, a): 4157 pass 4158 class C: 4159 __init__ = A().call 4160 4161 C(1) # does not raise 4162 self.assertEqual(self.signature(C), 4163 ((('a', ..., ..., "positional_or_keyword"),), 4164 ...)) 4165 4166 with self.subTest('partial'): 4167 class C: 4168 __init__ = functools.partial(lambda x, a: None, 2) 4169 4170 with self.assertWarns(FutureWarning): 4171 C(1) # does not raise 4172 with self.assertWarns(FutureWarning): 4173 self.assertEqual(self.signature(C), 4174 ((('a', ..., ..., "positional_or_keyword"),), 4175 ...)) 4176 4177 with self.subTest('partialmethod'): 4178 class C: 4179 def _init(self, x, a): 4180 self.a = (x, a) 4181 __init__ = functools.partialmethod(_init, 2) 4182 4183 self.assertEqual(C(1).a, (2, 1)) 4184 self.assertEqual(self.signature(C), 4185 ((('a', ..., ..., "positional_or_keyword"),), 4186 ...)) 4187 4188 def test_signature_on_class_with_new(self): 4189 with self.subTest('FunctionType'): 4190 class C: 4191 def __new__(cls, a): 4192 return a 4193 4194 self.assertEqual(C(1), 1) 4195 self.assertEqual(self.signature(C), 4196 ((('a', ..., ..., "positional_or_keyword"),), 4197 ...)) 4198 4199 with self.subTest('classmethod'): 4200 class C: 4201 @classmethod 4202 def __new__(cls, cls2, a): 4203 return a 4204 4205 self.assertEqual(C(1), 1) 4206 self.assertEqual(self.signature(C), 4207 ((('a', ..., ..., "positional_or_keyword"),), 4208 ...)) 4209 4210 with self.subTest('staticmethod'): 4211 class C: 4212 @staticmethod 4213 def __new__(cls, a): 4214 return a 4215 4216 self.assertEqual(C(1), 1) 4217 self.assertEqual(self.signature(C), 4218 ((('a', ..., ..., "positional_or_keyword"),), 4219 ...)) 4220 4221 with self.subTest('MethodType'): 4222 class A: 4223 def call(self, cls, a): 4224 return a 4225 class C: 4226 __new__ = A().call 4227 4228 self.assertEqual(C(1), 1) 4229 self.assertEqual(self.signature(C), 4230 ((('a', ..., ..., "positional_or_keyword"),), 4231 ...)) 4232 4233 with self.subTest('partial'): 4234 class C: 4235 __new__ = functools.partial(lambda x, cls, a: (x, a), 2) 4236 4237 self.assertEqual(C(1), (2, 1)) 4238 self.assertEqual(self.signature(C), 4239 ((('a', ..., ..., "positional_or_keyword"),), 4240 ...)) 4241 4242 with self.subTest('partialmethod'): 4243 class C: 4244 __new__ = functools.partialmethod(lambda cls, x, a: (x, a), 2) 4245 4246 self.assertEqual(C(1), (2, 1)) 4247 self.assertEqual(self.signature(C), 4248 ((('a', ..., ..., "positional_or_keyword"),), 4249 ...)) 4250 4251 with self.subTest('BuiltinMethodType'): 4252 class C: 4253 __new__ = str.__subclasscheck__ 4254 4255 self.assertEqual(C(), False) 4256 # TODO: Support BuiltinMethodType 4257 # self.assertEqual(self.signature(C), ((), ...)) 4258 self.assertRaises(ValueError, self.signature, C) 4259 4260 with self.subTest('MethodWrapperType'): 4261 class C: 4262 __new__ = type.__or__.__get__(int, type) 4263 4264 self.assertEqual(C(), C | int) 4265 # TODO: Support MethodWrapperType 4266 # self.assertEqual(self.signature(C), ((), ...)) 4267 self.assertRaises(ValueError, self.signature, C) 4268 4269 # TODO: Test ClassMethodDescriptorType 4270 4271 with self.subTest('MethodDescriptorType'): 4272 class C: 4273 __new__ = type.__dict__['__subclasscheck__'] 4274 4275 self.assertEqual(C(C), True) 4276 self.assertEqual(self.signature(C), self.signature(C.__subclasscheck__)) 4277 4278 with self.subTest('WrapperDescriptorType'): 4279 class C: 4280 __new__ = type.__or__ 4281 4282 self.assertEqual(C(int), C | int) 4283 # TODO: Support WrapperDescriptorType 4284 # self.assertEqual(self.signature(C), self.signature(C.__or__)) 4285 self.assertRaises(ValueError, self.signature, C) 4286 4287 def test_signature_on_subclass(self): 4288 class A: 4289 def __new__(cls, a=1, *args, **kwargs): 4290 return object.__new__(cls) 4291 class B(A): 4292 def __init__(self, b): 4293 pass 4294 class C(A): 4295 def __new__(cls, a=1, b=2, *args, **kwargs): 4296 return object.__new__(cls) 4297 class D(A): 4298 pass 4299 4300 self.assertEqual(self.signature(B), 4301 ((('b', ..., ..., "positional_or_keyword"),), 4302 ...)) 4303 self.assertEqual(self.signature(C), 4304 ((('a', 1, ..., 'positional_or_keyword'), 4305 ('b', 2, ..., 'positional_or_keyword'), 4306 ('args', ..., ..., 'var_positional'), 4307 ('kwargs', ..., ..., 'var_keyword')), 4308 ...)) 4309 self.assertEqual(self.signature(D), 4310 ((('a', 1, ..., 'positional_or_keyword'), 4311 ('args', ..., ..., 'var_positional'), 4312 ('kwargs', ..., ..., 'var_keyword')), 4313 ...)) 4314 4315 def test_signature_on_generic_subclass(self): 4316 from typing import Generic, TypeVar 4317 4318 T = TypeVar('T') 4319 4320 class A(Generic[T]): 4321 def __init__(self, *, a: int) -> None: 4322 pass 4323 4324 self.assertEqual(self.signature(A), 4325 ((('a', ..., int, 'keyword_only'),), 4326 None)) 4327 4328 @unittest.skipIf(MISSING_C_DOCSTRINGS, 4329 "Signature information for builtins requires docstrings") 4330 def test_signature_on_class_without_init(self): 4331 # Test classes without user-defined __init__ or __new__ 4332 class C: pass 4333 self.assertEqual(str(inspect.signature(C)), '()') 4334 class D(C): pass 4335 self.assertEqual(str(inspect.signature(D)), '()') 4336 4337 # Test meta-classes without user-defined __init__ or __new__ 4338 class C(type): pass 4339 class D(C): pass 4340 self.assertEqual(C('A', (), {}).__name__, 'A') 4341 # TODO: Support type. 4342 with self.assertRaisesRegex(ValueError, "callable.*is not supported"): 4343 self.assertEqual(inspect.signature(C), None) 4344 self.assertEqual(D('A', (), {}).__name__, 'A') 4345 with self.assertRaisesRegex(ValueError, "callable.*is not supported"): 4346 self.assertEqual(inspect.signature(D), None) 4347 4348 @unittest.skipIf(MISSING_C_DOCSTRINGS, 4349 "Signature information for builtins requires docstrings") 4350 def test_signature_on_builtin_class(self): 4351 expected = ('(file, protocol=None, fix_imports=True, ' 4352 'buffer_callback=None)') 4353 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected) 4354 4355 class P(_pickle.Pickler): pass 4356 class EmptyTrait: pass 4357 class P2(EmptyTrait, P): pass 4358 self.assertEqual(str(inspect.signature(P)), expected) 4359 self.assertEqual(str(inspect.signature(P2)), expected) 4360 4361 class P3(P2): 4362 def __init__(self, spam): 4363 pass 4364 self.assertEqual(str(inspect.signature(P3)), '(spam)') 4365 4366 class MetaP(type): 4367 def __call__(cls, foo, bar): 4368 pass 4369 class P4(P2, metaclass=MetaP): 4370 pass 4371 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)') 4372 4373 def test_signature_on_callable_objects(self): 4374 class Foo: 4375 def __call__(self, a): 4376 pass 4377 4378 self.assertEqual(self.signature(Foo()), 4379 ((('a', ..., ..., "positional_or_keyword"),), 4380 ...)) 4381 4382 class Spam: 4383 pass 4384 with self.assertRaisesRegex(TypeError, "is not a callable object"): 4385 inspect.signature(Spam()) 4386 4387 class Bar(Spam, Foo): 4388 pass 4389 4390 self.assertEqual(self.signature(Bar()), 4391 ((('a', ..., ..., "positional_or_keyword"),), 4392 ...)) 4393 4394 with self.subTest('classmethod'): 4395 class C: 4396 @classmethod 4397 def __call__(cls, a): 4398 pass 4399 4400 self.assertEqual(self.signature(C()), 4401 ((('a', ..., ..., "positional_or_keyword"),), 4402 ...)) 4403 4404 with self.subTest('staticmethod'): 4405 class C: 4406 @staticmethod 4407 def __call__(a): 4408 pass 4409 4410 self.assertEqual(self.signature(C()), 4411 ((('a', ..., ..., "positional_or_keyword"),), 4412 ...)) 4413 4414 with self.subTest('MethodType'): 4415 class A: 4416 def call(self, a): 4417 return a 4418 class C: 4419 __call__ = A().call 4420 4421 self.assertEqual(C()(1), 1) 4422 self.assertEqual(self.signature(C()), 4423 ((('a', ..., ..., "positional_or_keyword"),), 4424 ...)) 4425 4426 with self.subTest('partial'): 4427 class C: 4428 __call__ = functools.partial(lambda x, a: (x, a), 2) 4429 4430 c = C() 4431 with self.assertWarns(FutureWarning): 4432 self.assertEqual(c(1), (2, 1)) 4433 with self.assertWarns(FutureWarning): 4434 self.assertEqual(self.signature(c), 4435 ((('a', ..., ..., "positional_or_keyword"),), 4436 ...)) 4437 4438 with self.subTest('partialmethod'): 4439 class C: 4440 __call__ = functools.partialmethod(lambda self, x, a: (x, a), 2) 4441 4442 self.assertEqual(C()(1), (2, 1)) 4443 self.assertEqual(self.signature(C()), 4444 ((('a', ..., ..., "positional_or_keyword"),), 4445 ...)) 4446 4447 with self.subTest('BuiltinMethodType'): 4448 class C: 4449 __call__ = ':'.join 4450 4451 self.assertEqual(C()(['a', 'bc']), 'a:bc') 4452 self.assertEqual(self.signature(C()), self.signature(''.join)) 4453 4454 with self.subTest('MethodWrapperType'): 4455 class C: 4456 __call__ = (2).__pow__ 4457 4458 self.assertEqual(C()(3), 8) 4459 self.assertEqual(self.signature(C()), self.signature((0).__pow__)) 4460 4461 with self.subTest('ClassMethodDescriptorType'): 4462 class C(dict): 4463 __call__ = dict.__dict__['fromkeys'] 4464 4465 res = C()([1, 2], 3) 4466 self.assertEqual(res, {1: 3, 2: 3}) 4467 self.assertEqual(type(res), C) 4468 self.assertEqual(self.signature(C()), self.signature(dict.fromkeys)) 4469 4470 with self.subTest('MethodDescriptorType'): 4471 class C(str): 4472 __call__ = str.join 4473 4474 self.assertEqual(C(':')(['a', 'bc']), 'a:bc') 4475 self.assertEqual(self.signature(C()), self.signature(''.join)) 4476 4477 with self.subTest('WrapperDescriptorType'): 4478 class C(int): 4479 __call__ = int.__pow__ 4480 4481 self.assertEqual(C(2)(3), 8) 4482 self.assertEqual(self.signature(C()), self.signature((0).__pow__)) 4483 4484 with self.subTest('MemberDescriptorType'): 4485 class C: 4486 __slots__ = '__call__' 4487 c = C() 4488 c.__call__ = lambda a: a 4489 self.assertEqual(c(1), 1) 4490 self.assertEqual(self.signature(c), 4491 ((('a', ..., ..., "positional_or_keyword"),), 4492 ...)) 4493 4494 def test_signature_on_callable_objects_with_text_signature_attr(self): 4495 class C: 4496 __text_signature__ = '(a, /, b, c=True)' 4497 def __call__(self, *args, **kwargs): 4498 pass 4499 4500 self.assertEqual(self.signature(C), ((), ...)) 4501 self.assertEqual(self.signature(C()), 4502 ((('a', ..., ..., "positional_only"), 4503 ('b', ..., ..., "positional_or_keyword"), 4504 ('c', True, ..., "positional_or_keyword"), 4505 ), 4506 ...)) 4507 4508 c = C() 4509 c.__text_signature__ = '(x, y)' 4510 self.assertEqual(self.signature(c), 4511 ((('x', ..., ..., "positional_or_keyword"), 4512 ('y', ..., ..., "positional_or_keyword"), 4513 ), 4514 ...)) 4515 4516 def test_signature_on_wrapper(self): 4517 class Wrapper: 4518 def __call__(self, b): 4519 pass 4520 wrapper = Wrapper() 4521 wrapper.__wrapped__ = lambda a: None 4522 self.assertEqual(self.signature(wrapper), 4523 ((('a', ..., ..., "positional_or_keyword"),), 4524 ...)) 4525 # wrapper loop: 4526 wrapper = Wrapper() 4527 wrapper.__wrapped__ = wrapper 4528 with self.assertRaisesRegex(ValueError, 'wrapper loop'): 4529 self.signature(wrapper) 4530 4531 def test_signature_on_lambdas(self): 4532 self.assertEqual(self.signature((lambda a=10: a)), 4533 ((('a', 10, ..., "positional_or_keyword"),), 4534 ...)) 4535 4536 def test_signature_on_mocks(self): 4537 # https://github.com/python/cpython/issues/96127 4538 for mock in ( 4539 unittest.mock.Mock(), 4540 unittest.mock.AsyncMock(), 4541 unittest.mock.MagicMock(), 4542 ): 4543 with self.subTest(mock=mock): 4544 self.assertEqual(str(inspect.signature(mock)), '(*args, **kwargs)') 4545 4546 def test_signature_on_noncallable_mocks(self): 4547 for mock in ( 4548 unittest.mock.NonCallableMock(), 4549 unittest.mock.NonCallableMagicMock(), 4550 ): 4551 with self.subTest(mock=mock): 4552 with self.assertRaises(TypeError): 4553 inspect.signature(mock) 4554 4555 def test_signature_equality(self): 4556 def foo(a, *, b:int) -> float: pass 4557 self.assertFalse(inspect.signature(foo) == 42) 4558 self.assertTrue(inspect.signature(foo) != 42) 4559 self.assertTrue(inspect.signature(foo) == ALWAYS_EQ) 4560 self.assertFalse(inspect.signature(foo) != ALWAYS_EQ) 4561 4562 def bar(a, *, b:int) -> float: pass 4563 self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) 4564 self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) 4565 self.assertEqual( 4566 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 4567 4568 def bar(a, *, b:int) -> int: pass 4569 self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) 4570 self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) 4571 self.assertNotEqual( 4572 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 4573 4574 def bar(a, *, b:int): pass 4575 self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) 4576 self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) 4577 self.assertNotEqual( 4578 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 4579 4580 def bar(a, *, b:int=42) -> float: pass 4581 self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) 4582 self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) 4583 self.assertNotEqual( 4584 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 4585 4586 def bar(a, *, c) -> float: pass 4587 self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) 4588 self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) 4589 self.assertNotEqual( 4590 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 4591 4592 def bar(a, b:int) -> float: pass 4593 self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) 4594 self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) 4595 self.assertNotEqual( 4596 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 4597 def spam(b:int, a) -> float: pass 4598 self.assertFalse(inspect.signature(spam) == inspect.signature(bar)) 4599 self.assertTrue(inspect.signature(spam) != inspect.signature(bar)) 4600 self.assertNotEqual( 4601 hash(inspect.signature(spam)), hash(inspect.signature(bar))) 4602 4603 def foo(*, a, b, c): pass 4604 def bar(*, c, b, a): pass 4605 self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) 4606 self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) 4607 self.assertEqual( 4608 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 4609 4610 def foo(*, a=1, b, c): pass 4611 def bar(*, c, b, a=1): pass 4612 self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) 4613 self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) 4614 self.assertEqual( 4615 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 4616 4617 def foo(pos, *, a=1, b, c): pass 4618 def bar(pos, *, c, b, a=1): pass 4619 self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) 4620 self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) 4621 self.assertEqual( 4622 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 4623 4624 def foo(pos, *, a, b, c): pass 4625 def bar(pos, *, c, b, a=1): pass 4626 self.assertFalse(inspect.signature(foo) == inspect.signature(bar)) 4627 self.assertTrue(inspect.signature(foo) != inspect.signature(bar)) 4628 self.assertNotEqual( 4629 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 4630 4631 def foo(pos, *args, a=42, b, c, **kwargs:int): pass 4632 def bar(pos, *args, c, b, a=42, **kwargs:int): pass 4633 self.assertTrue(inspect.signature(foo) == inspect.signature(bar)) 4634 self.assertFalse(inspect.signature(foo) != inspect.signature(bar)) 4635 self.assertEqual( 4636 hash(inspect.signature(foo)), hash(inspect.signature(bar))) 4637 4638 def test_signature_hashable(self): 4639 S = inspect.Signature 4640 P = inspect.Parameter 4641 4642 def foo(a): pass 4643 foo_sig = inspect.signature(foo) 4644 4645 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)]) 4646 4647 self.assertEqual(hash(foo_sig), hash(manual_sig)) 4648 self.assertNotEqual(hash(foo_sig), 4649 hash(manual_sig.replace(return_annotation='spam'))) 4650 4651 def bar(a) -> 1: pass 4652 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar))) 4653 4654 def foo(a={}): pass 4655 with self.assertRaisesRegex(TypeError, 'unhashable type'): 4656 hash(inspect.signature(foo)) 4657 4658 def foo(a) -> {}: pass 4659 with self.assertRaisesRegex(TypeError, 'unhashable type'): 4660 hash(inspect.signature(foo)) 4661 4662 def test_signature_str(self): 4663 def foo(a:int=1, *, b, c=None, **kwargs) -> 42: 4664 pass 4665 self.assertEqual(str(inspect.signature(foo)), 4666 '(a: int = 1, *, b, c=None, **kwargs) -> 42') 4667 self.assertEqual(str(inspect.signature(foo)), 4668 inspect.signature(foo).format()) 4669 4670 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42: 4671 pass 4672 self.assertEqual(str(inspect.signature(foo)), 4673 '(a: int = 1, *args, b, c=None, **kwargs) -> 42') 4674 self.assertEqual(str(inspect.signature(foo)), 4675 inspect.signature(foo).format()) 4676 4677 def foo(): 4678 pass 4679 self.assertEqual(str(inspect.signature(foo)), '()') 4680 self.assertEqual(str(inspect.signature(foo)), 4681 inspect.signature(foo).format()) 4682 4683 def foo(a: list[str]) -> tuple[str, float]: 4684 pass 4685 self.assertEqual(str(inspect.signature(foo)), 4686 '(a: list[str]) -> tuple[str, float]') 4687 self.assertEqual(str(inspect.signature(foo)), 4688 inspect.signature(foo).format()) 4689 4690 from typing import Tuple 4691 def foo(a: list[str]) -> Tuple[str, float]: 4692 pass 4693 self.assertEqual(str(inspect.signature(foo)), 4694 '(a: list[str]) -> Tuple[str, float]') 4695 self.assertEqual(str(inspect.signature(foo)), 4696 inspect.signature(foo).format()) 4697 4698 def test_signature_str_positional_only(self): 4699 P = inspect.Parameter 4700 S = inspect.Signature 4701 4702 def test(a_po, /, *, b, **kwargs): 4703 return a_po, kwargs 4704 4705 self.assertEqual(str(inspect.signature(test)), 4706 '(a_po, /, *, b, **kwargs)') 4707 self.assertEqual(str(inspect.signature(test)), 4708 inspect.signature(test).format()) 4709 4710 test = S(parameters=[P('foo', P.POSITIONAL_ONLY)]) 4711 self.assertEqual(str(test), '(foo, /)') 4712 self.assertEqual(str(test), test.format()) 4713 4714 test = S(parameters=[P('foo', P.POSITIONAL_ONLY), 4715 P('bar', P.VAR_KEYWORD)]) 4716 self.assertEqual(str(test), '(foo, /, **bar)') 4717 self.assertEqual(str(test), test.format()) 4718 4719 test = S(parameters=[P('foo', P.POSITIONAL_ONLY), 4720 P('bar', P.VAR_POSITIONAL)]) 4721 self.assertEqual(str(test), '(foo, /, *bar)') 4722 self.assertEqual(str(test), test.format()) 4723 4724 def test_signature_format(self): 4725 from typing import Annotated, Literal 4726 4727 def func(x: Annotated[int, 'meta'], y: Literal['a', 'b'], z: 'LiteralString'): 4728 pass 4729 4730 expected_singleline = "(x: Annotated[int, 'meta'], y: Literal['a', 'b'], z: 'LiteralString')" 4731 expected_multiline = """( 4732 x: Annotated[int, 'meta'], 4733 y: Literal['a', 'b'], 4734 z: 'LiteralString' 4735)""" 4736 self.assertEqual( 4737 inspect.signature(func).format(), 4738 expected_singleline, 4739 ) 4740 self.assertEqual( 4741 inspect.signature(func).format(max_width=None), 4742 expected_singleline, 4743 ) 4744 self.assertEqual( 4745 inspect.signature(func).format(max_width=len(expected_singleline)), 4746 expected_singleline, 4747 ) 4748 self.assertEqual( 4749 inspect.signature(func).format(max_width=len(expected_singleline) - 1), 4750 expected_multiline, 4751 ) 4752 self.assertEqual( 4753 inspect.signature(func).format(max_width=0), 4754 expected_multiline, 4755 ) 4756 self.assertEqual( 4757 inspect.signature(func).format(max_width=-1), 4758 expected_multiline, 4759 ) 4760 4761 def test_signature_format_all_arg_types(self): 4762 from typing import Annotated, Literal 4763 4764 def func( 4765 x: Annotated[int, 'meta'], 4766 /, 4767 y: Literal['a', 'b'], 4768 *, 4769 z: 'LiteralString', 4770 **kwargs: object, 4771 ) -> None: 4772 pass 4773 4774 expected_multiline = """( 4775 x: Annotated[int, 'meta'], 4776 /, 4777 y: Literal['a', 'b'], 4778 *, 4779 z: 'LiteralString', 4780 **kwargs: object 4781) -> None""" 4782 self.assertEqual( 4783 inspect.signature(func).format(max_width=-1), 4784 expected_multiline, 4785 ) 4786 4787 def test_signature_replace_parameters(self): 4788 def test(a, b) -> 42: 4789 pass 4790 4791 sig = inspect.signature(test) 4792 parameters = sig.parameters 4793 sig = sig.replace(parameters=list(parameters.values())[1:]) 4794 self.assertEqual(list(sig.parameters), ['b']) 4795 self.assertEqual(sig.parameters['b'], parameters['b']) 4796 self.assertEqual(sig.return_annotation, 42) 4797 sig = sig.replace(parameters=()) 4798 self.assertEqual(dict(sig.parameters), {}) 4799 4800 sig = inspect.signature(test) 4801 parameters = sig.parameters 4802 sig = copy.replace(sig, parameters=list(parameters.values())[1:]) 4803 self.assertEqual(list(sig.parameters), ['b']) 4804 self.assertEqual(sig.parameters['b'], parameters['b']) 4805 self.assertEqual(sig.return_annotation, 42) 4806 sig = copy.replace(sig, parameters=()) 4807 self.assertEqual(dict(sig.parameters), {}) 4808 4809 def test_signature_replace_anno(self): 4810 def test() -> 42: 4811 pass 4812 4813 sig = inspect.signature(test) 4814 sig = sig.replace(return_annotation=None) 4815 self.assertIs(sig.return_annotation, None) 4816 sig = sig.replace(return_annotation=sig.empty) 4817 self.assertIs(sig.return_annotation, sig.empty) 4818 sig = sig.replace(return_annotation=42) 4819 self.assertEqual(sig.return_annotation, 42) 4820 self.assertEqual(sig, inspect.signature(test)) 4821 4822 sig = inspect.signature(test) 4823 sig = copy.replace(sig, return_annotation=None) 4824 self.assertIs(sig.return_annotation, None) 4825 sig = copy.replace(sig, return_annotation=sig.empty) 4826 self.assertIs(sig.return_annotation, sig.empty) 4827 sig = copy.replace(sig, return_annotation=42) 4828 self.assertEqual(sig.return_annotation, 42) 4829 self.assertEqual(sig, inspect.signature(test)) 4830 4831 def test_signature_replaced(self): 4832 def test(): 4833 pass 4834 4835 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY) 4836 sig = test.__signature__ = inspect.Signature(parameters=(spam_param,)) 4837 self.assertEqual(sig, inspect.signature(test)) 4838 4839 def test_signature_on_mangled_parameters(self): 4840 class Spam: 4841 def foo(self, __p1:1=2, *, __p2:2=3): 4842 pass 4843 class Ham(Spam): 4844 pass 4845 4846 self.assertEqual(self.signature(Spam.foo), 4847 ((('self', ..., ..., "positional_or_keyword"), 4848 ('_Spam__p1', 2, 1, "positional_or_keyword"), 4849 ('_Spam__p2', 3, 2, "keyword_only")), 4850 ...)) 4851 4852 self.assertEqual(self.signature(Spam.foo), 4853 self.signature(Ham.foo)) 4854 4855 def test_signature_from_callable_python_obj(self): 4856 class MySignature(inspect.Signature): pass 4857 def foo(a, *, b:1): pass 4858 foo_sig = MySignature.from_callable(foo) 4859 self.assertIsInstance(foo_sig, MySignature) 4860 4861 @unittest.skipIf(MISSING_C_DOCSTRINGS, 4862 "Signature information for builtins requires docstrings") 4863 def test_signature_from_callable_class(self): 4864 # A regression test for a class inheriting its signature from `object`. 4865 class MySignature(inspect.Signature): pass 4866 class foo: pass 4867 foo_sig = MySignature.from_callable(foo) 4868 self.assertIsInstance(foo_sig, MySignature) 4869 4870 @unittest.skipIf(MISSING_C_DOCSTRINGS, 4871 "Signature information for builtins requires docstrings") 4872 def test_signature_from_callable_builtin_obj(self): 4873 class MySignature(inspect.Signature): pass 4874 sig = MySignature.from_callable(_pickle.Pickler) 4875 self.assertIsInstance(sig, MySignature) 4876 4877 def test_signature_definition_order_preserved_on_kwonly(self): 4878 for fn in signatures_with_lexicographic_keyword_only_parameters(): 4879 signature = inspect.signature(fn) 4880 l = list(signature.parameters) 4881 sorted_l = sorted(l) 4882 self.assertTrue(l) 4883 self.assertEqual(l, sorted_l) 4884 signature = inspect.signature(unsorted_keyword_only_parameters_fn) 4885 l = list(signature.parameters) 4886 self.assertEqual(l, unsorted_keyword_only_parameters) 4887 4888 def test_signater_parameters_is_ordered(self): 4889 p1 = inspect.signature(lambda x, y: None).parameters 4890 p2 = inspect.signature(lambda y, x: None).parameters 4891 self.assertNotEqual(p1, p2) 4892 4893 def test_signature_annotations_with_local_namespaces(self): 4894 class Foo: ... 4895 def func(foo: Foo) -> int: pass 4896 def func2(foo: Foo, bar: 'Bar') -> int: pass 4897 4898 for signature_func in (inspect.signature, inspect.Signature.from_callable): 4899 with self.subTest(signature_func = signature_func): 4900 sig1 = signature_func(func) 4901 self.assertEqual(sig1.return_annotation, int) 4902 self.assertEqual(sig1.parameters['foo'].annotation, Foo) 4903 4904 sig2 = signature_func(func, locals=locals()) 4905 self.assertEqual(sig2.return_annotation, int) 4906 self.assertEqual(sig2.parameters['foo'].annotation, Foo) 4907 4908 sig3 = signature_func(func2, globals={'Bar': int}, locals=locals()) 4909 self.assertEqual(sig3.return_annotation, int) 4910 self.assertEqual(sig3.parameters['foo'].annotation, Foo) 4911 self.assertEqual(sig3.parameters['bar'].annotation, 'Bar') 4912 4913 def test_signature_eval_str(self): 4914 isa = inspect_stringized_annotations 4915 sig = inspect.Signature 4916 par = inspect.Parameter 4917 PORK = inspect.Parameter.POSITIONAL_OR_KEYWORD 4918 for signature_func in (inspect.signature, inspect.Signature.from_callable): 4919 with self.subTest(signature_func = signature_func): 4920 self.assertEqual( 4921 signature_func(isa.MyClass), 4922 sig( 4923 parameters=( 4924 par('a', PORK), 4925 par('b', PORK), 4926 ))) 4927 self.assertEqual( 4928 signature_func(isa.function), 4929 sig( 4930 return_annotation='MyClass', 4931 parameters=( 4932 par('a', PORK, annotation='int'), 4933 par('b', PORK, annotation='str'), 4934 ))) 4935 self.assertEqual( 4936 signature_func(isa.function2), 4937 sig( 4938 return_annotation='MyClass', 4939 parameters=( 4940 par('a', PORK, annotation='int'), 4941 par('b', PORK, annotation="'str'"), 4942 par('c', PORK, annotation="MyClass"), 4943 ))) 4944 self.assertEqual( 4945 signature_func(isa.function3), 4946 sig( 4947 parameters=( 4948 par('a', PORK, annotation="'int'"), 4949 par('b', PORK, annotation="'str'"), 4950 par('c', PORK, annotation="'MyClass'"), 4951 ))) 4952 4953 if not MISSING_C_DOCSTRINGS: 4954 self.assertEqual(signature_func(isa.UnannotatedClass), sig()) 4955 self.assertEqual(signature_func(isa.unannotated_function), 4956 sig( 4957 parameters=( 4958 par('a', PORK), 4959 par('b', PORK), 4960 par('c', PORK), 4961 ))) 4962 4963 self.assertEqual( 4964 signature_func(isa.MyClass, eval_str=True), 4965 sig( 4966 parameters=( 4967 par('a', PORK), 4968 par('b', PORK), 4969 ))) 4970 self.assertEqual( 4971 signature_func(isa.function, eval_str=True), 4972 sig( 4973 return_annotation=isa.MyClass, 4974 parameters=( 4975 par('a', PORK, annotation=int), 4976 par('b', PORK, annotation=str), 4977 ))) 4978 self.assertEqual( 4979 signature_func(isa.function2, eval_str=True), 4980 sig( 4981 return_annotation=isa.MyClass, 4982 parameters=( 4983 par('a', PORK, annotation=int), 4984 par('b', PORK, annotation='str'), 4985 par('c', PORK, annotation=isa.MyClass), 4986 ))) 4987 self.assertEqual( 4988 signature_func(isa.function3, eval_str=True), 4989 sig( 4990 parameters=( 4991 par('a', PORK, annotation='int'), 4992 par('b', PORK, annotation='str'), 4993 par('c', PORK, annotation='MyClass'), 4994 ))) 4995 4996 globalns = {'int': float, 'str': complex} 4997 localns = {'str': tuple, 'MyClass': dict} 4998 with self.assertRaises(NameError): 4999 signature_func(isa.function, eval_str=True, globals=globalns) 5000 5001 self.assertEqual( 5002 signature_func(isa.function, eval_str=True, locals=localns), 5003 sig( 5004 return_annotation=dict, 5005 parameters=( 5006 par('a', PORK, annotation=int), 5007 par('b', PORK, annotation=tuple), 5008 ))) 5009 5010 self.assertEqual( 5011 signature_func(isa.function, eval_str=True, globals=globalns, locals=localns), 5012 sig( 5013 return_annotation=dict, 5014 parameters=( 5015 par('a', PORK, annotation=float), 5016 par('b', PORK, annotation=tuple), 5017 ))) 5018 5019 def test_signature_none_annotation(self): 5020 class funclike: 5021 # Has to be callable, and have correct 5022 # __code__, __annotations__, __defaults__, __name__, 5023 # and __kwdefaults__ attributes 5024 5025 def __init__(self, func): 5026 self.__name__ = func.__name__ 5027 self.__code__ = func.__code__ 5028 self.__annotations__ = func.__annotations__ 5029 self.__defaults__ = func.__defaults__ 5030 self.__kwdefaults__ = func.__kwdefaults__ 5031 self.func = func 5032 5033 def __call__(self, *args, **kwargs): 5034 return self.func(*args, **kwargs) 5035 5036 def foo(): pass 5037 foo = funclike(foo) 5038 foo.__annotations__ = None 5039 for signature_func in (inspect.signature, inspect.Signature.from_callable): 5040 with self.subTest(signature_func = signature_func): 5041 self.assertEqual(signature_func(foo), inspect.Signature()) 5042 self.assertEqual(inspect.get_annotations(foo), {}) 5043 5044 def test_signature_as_str(self): 5045 self.maxDiff = None 5046 class S: 5047 __signature__ = '(a, b=2)' 5048 5049 self.assertEqual(self.signature(S), 5050 ((('a', ..., ..., 'positional_or_keyword'), 5051 ('b', 2, ..., 'positional_or_keyword')), 5052 ...)) 5053 5054 def test_signature_as_callable(self): 5055 # __signature__ should be either a staticmethod or a bound classmethod 5056 class S: 5057 @classmethod 5058 def __signature__(cls): 5059 return '(a, b=2)' 5060 5061 self.assertEqual(self.signature(S), 5062 ((('a', ..., ..., 'positional_or_keyword'), 5063 ('b', 2, ..., 'positional_or_keyword')), 5064 ...)) 5065 5066 class S: 5067 @staticmethod 5068 def __signature__(): 5069 return '(a, b=2)' 5070 5071 self.assertEqual(self.signature(S), 5072 ((('a', ..., ..., 'positional_or_keyword'), 5073 ('b', 2, ..., 'positional_or_keyword')), 5074 ...)) 5075 5076 def test_signature_on_derived_classes(self): 5077 # gh-105080: Make sure that signatures are consistent on derived classes 5078 5079 class B: 5080 def __new__(self, *args, **kwargs): 5081 return super().__new__(self) 5082 def __init__(self, value): 5083 self.value = value 5084 5085 class D1(B): 5086 def __init__(self, value): 5087 super().__init__(value) 5088 5089 class D2(D1): 5090 pass 5091 5092 self.assertEqual(inspect.signature(D2), inspect.signature(D1)) 5093 5094 def test_signature_on_non_comparable(self): 5095 class NoncomparableCallable: 5096 def __call__(self, a): 5097 pass 5098 def __eq__(self, other): 5099 1/0 5100 self.assertEqual(self.signature(NoncomparableCallable()), 5101 ((('a', ..., ..., 'positional_or_keyword'),), 5102 ...)) 5103 5104 5105class TestParameterObject(unittest.TestCase): 5106 def test_signature_parameter_kinds(self): 5107 P = inspect.Parameter 5108 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \ 5109 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD) 5110 5111 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY') 5112 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY)) 5113 5114 def test_signature_parameter_object(self): 5115 p = inspect.Parameter('foo', default=10, 5116 kind=inspect.Parameter.POSITIONAL_ONLY) 5117 self.assertEqual(p.name, 'foo') 5118 self.assertEqual(p.default, 10) 5119 self.assertIs(p.annotation, p.empty) 5120 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY) 5121 5122 with self.assertRaisesRegex(ValueError, "value '123' is " 5123 "not a valid Parameter.kind"): 5124 inspect.Parameter('foo', default=10, kind='123') 5125 5126 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'): 5127 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD) 5128 5129 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'): 5130 inspect.Parameter('from', kind=inspect.Parameter.VAR_KEYWORD) 5131 5132 with self.assertRaisesRegex(TypeError, 'name must be a str'): 5133 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD) 5134 5135 with self.assertRaisesRegex(ValueError, 5136 'is not a valid parameter name'): 5137 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD) 5138 5139 with self.assertRaisesRegex(ValueError, 5140 'is not a valid parameter name'): 5141 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD) 5142 5143 with self.assertRaisesRegex(ValueError, 'cannot have default values'): 5144 inspect.Parameter('a', default=42, 5145 kind=inspect.Parameter.VAR_KEYWORD) 5146 5147 with self.assertRaisesRegex(ValueError, 'cannot have default values'): 5148 inspect.Parameter('a', default=42, 5149 kind=inspect.Parameter.VAR_POSITIONAL) 5150 5151 p = inspect.Parameter('a', default=42, 5152 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD) 5153 with self.assertRaisesRegex(ValueError, 'cannot have default values'): 5154 p.replace(kind=inspect.Parameter.VAR_POSITIONAL) 5155 5156 self.assertTrue(repr(p).startswith('<Parameter')) 5157 self.assertTrue('"a=42"' in repr(p)) 5158 5159 def test_signature_parameter_hashable(self): 5160 P = inspect.Parameter 5161 foo = P('foo', kind=P.POSITIONAL_ONLY) 5162 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY))) 5163 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY, 5164 default=42))) 5165 self.assertNotEqual(hash(foo), 5166 hash(foo.replace(kind=P.VAR_POSITIONAL))) 5167 5168 def test_signature_parameter_equality(self): 5169 P = inspect.Parameter 5170 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY) 5171 5172 self.assertTrue(p == p) 5173 self.assertFalse(p != p) 5174 self.assertFalse(p == 42) 5175 self.assertTrue(p != 42) 5176 self.assertTrue(p == ALWAYS_EQ) 5177 self.assertFalse(p != ALWAYS_EQ) 5178 5179 self.assertTrue(p == P('foo', default=42, 5180 kind=inspect.Parameter.KEYWORD_ONLY)) 5181 self.assertFalse(p != P('foo', default=42, 5182 kind=inspect.Parameter.KEYWORD_ONLY)) 5183 5184 def test_signature_parameter_replace(self): 5185 p = inspect.Parameter('foo', default=42, 5186 kind=inspect.Parameter.KEYWORD_ONLY) 5187 5188 self.assertIsNot(p.replace(), p) 5189 self.assertEqual(p.replace(), p) 5190 self.assertIsNot(copy.replace(p), p) 5191 self.assertEqual(copy.replace(p), p) 5192 5193 p2 = p.replace(annotation=1) 5194 self.assertEqual(p2.annotation, 1) 5195 p2 = p2.replace(annotation=p2.empty) 5196 self.assertEqual(p2, p) 5197 p3 = copy.replace(p, annotation=1) 5198 self.assertEqual(p3.annotation, 1) 5199 p3 = copy.replace(p3, annotation=p3.empty) 5200 self.assertEqual(p3, p) 5201 5202 p2 = p2.replace(name='bar') 5203 self.assertEqual(p2.name, 'bar') 5204 self.assertNotEqual(p2, p) 5205 p3 = copy.replace(p3, name='bar') 5206 self.assertEqual(p3.name, 'bar') 5207 self.assertNotEqual(p3, p) 5208 5209 with self.assertRaisesRegex(ValueError, 5210 'name is a required attribute'): 5211 p2 = p2.replace(name=p2.empty) 5212 with self.assertRaisesRegex(ValueError, 5213 'name is a required attribute'): 5214 p3 = copy.replace(p3, name=p3.empty) 5215 5216 p2 = p2.replace(name='foo', default=None) 5217 self.assertIs(p2.default, None) 5218 self.assertNotEqual(p2, p) 5219 p3 = copy.replace(p3, name='foo', default=None) 5220 self.assertIs(p3.default, None) 5221 self.assertNotEqual(p3, p) 5222 5223 p2 = p2.replace(name='foo', default=p2.empty) 5224 self.assertIs(p2.default, p2.empty) 5225 p3 = copy.replace(p3, name='foo', default=p3.empty) 5226 self.assertIs(p3.default, p3.empty) 5227 5228 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD) 5229 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD) 5230 self.assertNotEqual(p2, p) 5231 p3 = copy.replace(p3, default=42, kind=p3.POSITIONAL_OR_KEYWORD) 5232 self.assertEqual(p3.kind, p3.POSITIONAL_OR_KEYWORD) 5233 self.assertNotEqual(p3, p) 5234 5235 with self.assertRaisesRegex(ValueError, 5236 "value <class 'inspect._empty'> " 5237 "is not a valid Parameter.kind"): 5238 p2 = p2.replace(kind=p2.empty) 5239 with self.assertRaisesRegex(ValueError, 5240 "value <class 'inspect._empty'> " 5241 "is not a valid Parameter.kind"): 5242 p3 = copy.replace(p3, kind=p3.empty) 5243 5244 p2 = p2.replace(kind=p2.KEYWORD_ONLY) 5245 self.assertEqual(p2, p) 5246 p3 = copy.replace(p3, kind=p3.KEYWORD_ONLY) 5247 self.assertEqual(p3, p) 5248 5249 def test_signature_parameter_positional_only(self): 5250 with self.assertRaisesRegex(TypeError, 'name must be a str'): 5251 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY) 5252 5253 @cpython_only 5254 def test_signature_parameter_implicit(self): 5255 with self.assertRaisesRegex(ValueError, 5256 'implicit arguments must be passed as ' 5257 'positional or keyword arguments, ' 5258 'not positional-only'): 5259 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY) 5260 5261 param = inspect.Parameter( 5262 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD) 5263 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY) 5264 self.assertEqual(param.name, 'implicit0') 5265 5266 def test_signature_parameter_immutability(self): 5267 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY) 5268 5269 with self.assertRaises(AttributeError): 5270 p.foo = 'bar' 5271 5272 with self.assertRaises(AttributeError): 5273 p.kind = 123 5274 5275 5276class TestSignatureBind(unittest.TestCase): 5277 @staticmethod 5278 def call(func, *args, **kwargs): 5279 sig = inspect.signature(func) 5280 ba = sig.bind(*args, **kwargs) 5281 return func(*ba.args, **ba.kwargs) 5282 5283 def test_signature_bind_empty(self): 5284 def test(): 5285 return 42 5286 5287 self.assertEqual(self.call(test), 42) 5288 with self.assertRaisesRegex(TypeError, 'too many positional arguments'): 5289 self.call(test, 1) 5290 with self.assertRaisesRegex(TypeError, 'too many positional arguments'): 5291 self.call(test, 1, spam=10) 5292 with self.assertRaisesRegex( 5293 TypeError, "got an unexpected keyword argument 'spam'"): 5294 5295 self.call(test, spam=1) 5296 5297 def test_signature_bind_var(self): 5298 def test(*args, **kwargs): 5299 return args, kwargs 5300 5301 self.assertEqual(self.call(test), ((), {})) 5302 self.assertEqual(self.call(test, 1), ((1,), {})) 5303 self.assertEqual(self.call(test, 1, 2), ((1, 2), {})) 5304 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'})) 5305 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'})) 5306 self.assertEqual(self.call(test, args=10), ((), {'args': 10})) 5307 self.assertEqual(self.call(test, 1, 2, foo='bar'), 5308 ((1, 2), {'foo': 'bar'})) 5309 5310 def test_signature_bind_just_args(self): 5311 def test(a, b, c): 5312 return a, b, c 5313 5314 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3)) 5315 5316 with self.assertRaisesRegex(TypeError, 'too many positional arguments'): 5317 self.call(test, 1, 2, 3, 4) 5318 5319 with self.assertRaisesRegex(TypeError, 5320 "missing a required argument: 'b'"): 5321 self.call(test, 1) 5322 5323 with self.assertRaisesRegex(TypeError, 5324 "missing a required argument: 'a'"): 5325 self.call(test) 5326 5327 def test(a, b, c=10): 5328 return a, b, c 5329 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3)) 5330 self.assertEqual(self.call(test, 1, 2), (1, 2, 10)) 5331 5332 def test(a=1, b=2, c=3): 5333 return a, b, c 5334 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13)) 5335 self.assertEqual(self.call(test, a=10), (10, 2, 3)) 5336 self.assertEqual(self.call(test, b=10), (1, 10, 3)) 5337 5338 def test_signature_bind_varargs_order(self): 5339 def test(*args): 5340 return args 5341 5342 self.assertEqual(self.call(test), ()) 5343 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3)) 5344 5345 def test_signature_bind_args_and_varargs(self): 5346 def test(a, b, c=3, *args): 5347 return a, b, c, args 5348 5349 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5))) 5350 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ())) 5351 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ())) 5352 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ())) 5353 5354 with self.assertRaisesRegex(TypeError, 5355 "multiple values for argument 'c'"): 5356 self.call(test, 1, 2, 3, c=4) 5357 5358 def test_signature_bind_just_kwargs(self): 5359 def test(**kwargs): 5360 return kwargs 5361 5362 self.assertEqual(self.call(test), {}) 5363 self.assertEqual(self.call(test, foo='bar', spam='ham'), 5364 {'foo': 'bar', 'spam': 'ham'}) 5365 5366 def test_signature_bind_args_and_kwargs(self): 5367 def test(a, b, c=3, **kwargs): 5368 return a, b, c, kwargs 5369 5370 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {})) 5371 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'), 5372 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'})) 5373 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'), 5374 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'})) 5375 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'), 5376 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'})) 5377 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'), 5378 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'})) 5379 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'), 5380 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'})) 5381 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'), 5382 (1, 2, 4, {'foo': 'bar'})) 5383 self.assertEqual(self.call(test, c=5, a=4, b=3), 5384 (4, 3, 5, {})) 5385 5386 def test_signature_bind_kwonly(self): 5387 def test(*, foo): 5388 return foo 5389 with self.assertRaisesRegex(TypeError, 5390 'too many positional arguments'): 5391 self.call(test, 1) 5392 self.assertEqual(self.call(test, foo=1), 1) 5393 5394 def test(a, *, foo=1, bar): 5395 return foo 5396 with self.assertRaisesRegex(TypeError, 5397 "missing a required argument: 'bar'"): 5398 self.call(test, 1) 5399 5400 def test(foo, *, bar): 5401 return foo, bar 5402 self.assertEqual(self.call(test, 1, bar=2), (1, 2)) 5403 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2)) 5404 5405 with self.assertRaisesRegex( 5406 TypeError, "got an unexpected keyword argument 'spam'"): 5407 5408 self.call(test, bar=2, foo=1, spam=10) 5409 5410 with self.assertRaisesRegex(TypeError, 5411 'too many positional arguments'): 5412 self.call(test, 1, 2) 5413 5414 with self.assertRaisesRegex(TypeError, 5415 'too many positional arguments'): 5416 self.call(test, 1, 2, bar=2) 5417 5418 with self.assertRaisesRegex( 5419 TypeError, "got an unexpected keyword argument 'spam'"): 5420 5421 self.call(test, 1, bar=2, spam='ham') 5422 5423 with self.assertRaisesRegex(TypeError, 5424 "missing a required keyword-only " 5425 "argument: 'bar'"): 5426 self.call(test, 1) 5427 5428 def test(foo, *, bar, **bin): 5429 return foo, bar, bin 5430 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {})) 5431 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {})) 5432 self.assertEqual(self.call(test, 1, bar=2, spam='ham'), 5433 (1, 2, {'spam': 'ham'})) 5434 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2), 5435 (1, 2, {'spam': 'ham'})) 5436 with self.assertRaisesRegex(TypeError, 5437 "missing a required argument: 'foo'"): 5438 self.call(test, spam='ham', bar=2) 5439 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10), 5440 (1, 2, {'bin': 1, 'spam': 10})) 5441 5442 def test_signature_bind_arguments(self): 5443 def test(a, *args, b, z=100, **kwargs): 5444 pass 5445 sig = inspect.signature(test) 5446 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60) 5447 # we won't have 'z' argument in the bound arguments object, as we didn't 5448 # pass it to the 'bind' 5449 self.assertEqual(tuple(ba.arguments.items()), 5450 (('a', 10), ('args', (20,)), ('b', 30), 5451 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60}))) 5452 self.assertEqual(ba.kwargs, 5453 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60}) 5454 self.assertEqual(ba.args, (10, 20)) 5455 5456 def test_signature_bind_positional_only(self): 5457 def test(a_po, b_po, c_po=3, /, foo=42, *, bar=50, **kwargs): 5458 return a_po, b_po, c_po, foo, bar, kwargs 5459 5460 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6), 5461 (1, 2, 4, 5, 6, {})) 5462 5463 self.assertEqual(self.call(test, 1, 2), 5464 (1, 2, 3, 42, 50, {})) 5465 5466 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5), 5467 (1, 2, 3, 4, 5, {})) 5468 5469 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5, c_po=10), 5470 (1, 2, 3, 4, 5, {'c_po': 10})) 5471 5472 self.assertEqual(self.call(test, 1, 2, 30, c_po=31, foo=4, bar=5), 5473 (1, 2, 30, 4, 5, {'c_po': 31})) 5474 5475 self.assertEqual(self.call(test, 1, 2, 30, foo=4, bar=5, c_po=31), 5476 (1, 2, 30, 4, 5, {'c_po': 31})) 5477 5478 self.assertEqual(self.call(test, 1, 2, c_po=4), 5479 (1, 2, 3, 42, 50, {'c_po': 4})) 5480 5481 with self.assertRaisesRegex(TypeError, "missing 2 required positional arguments"): 5482 self.call(test, a_po=1, b_po=2) 5483 5484 def without_var_kwargs(c_po=3, d_po=4, /): 5485 return c_po, d_po 5486 5487 with self.assertRaisesRegex( 5488 TypeError, 5489 "positional-only arguments passed as keyword arguments: 'c_po, d_po'", 5490 ): 5491 self.call(without_var_kwargs, c_po=33, d_po=44) 5492 5493 def test_signature_bind_with_self_arg(self): 5494 # Issue #17071: one of the parameters is named "self 5495 def test(a, self, b): 5496 pass 5497 sig = inspect.signature(test) 5498 ba = sig.bind(1, 2, 3) 5499 self.assertEqual(ba.args, (1, 2, 3)) 5500 ba = sig.bind(1, self=2, b=3) 5501 self.assertEqual(ba.args, (1, 2, 3)) 5502 5503 def test_signature_bind_vararg_name(self): 5504 def test(a, *args): 5505 return a, args 5506 sig = inspect.signature(test) 5507 5508 with self.assertRaisesRegex( 5509 TypeError, "got an unexpected keyword argument 'args'"): 5510 5511 sig.bind(a=0, args=1) 5512 5513 def test(*args, **kwargs): 5514 return args, kwargs 5515 self.assertEqual(self.call(test, args=1), ((), {'args': 1})) 5516 5517 sig = inspect.signature(test) 5518 ba = sig.bind(args=1) 5519 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}}) 5520 5521 @cpython_only 5522 def test_signature_bind_implicit_arg(self): 5523 # Issue #19611: getcallargs should work with comprehensions 5524 def make_set(): 5525 return set(z * z for z in range(5)) 5526 gencomp_code = make_set.__code__.co_consts[1] 5527 gencomp_func = types.FunctionType(gencomp_code, {}) 5528 5529 iterator = iter(range(5)) 5530 self.assertEqual(set(self.call(gencomp_func, iterator)), {0, 1, 4, 9, 16}) 5531 5532 def test_signature_bind_posonly_kwargs(self): 5533 def foo(bar, /, **kwargs): 5534 return bar, kwargs.get(bar) 5535 5536 sig = inspect.signature(foo) 5537 result = sig.bind("pos-only", bar="keyword") 5538 5539 self.assertEqual(result.kwargs, {"bar": "keyword"}) 5540 self.assertIn(("bar", "pos-only"), result.arguments.items()) 5541 5542 5543class TestBoundArguments(unittest.TestCase): 5544 def test_signature_bound_arguments_unhashable(self): 5545 def foo(a): pass 5546 ba = inspect.signature(foo).bind(1) 5547 5548 with self.assertRaisesRegex(TypeError, 'unhashable type'): 5549 hash(ba) 5550 5551 def test_signature_bound_arguments_equality(self): 5552 def foo(a): pass 5553 ba = inspect.signature(foo).bind(1) 5554 self.assertTrue(ba == ba) 5555 self.assertFalse(ba != ba) 5556 self.assertTrue(ba == ALWAYS_EQ) 5557 self.assertFalse(ba != ALWAYS_EQ) 5558 5559 ba2 = inspect.signature(foo).bind(1) 5560 self.assertTrue(ba == ba2) 5561 self.assertFalse(ba != ba2) 5562 5563 ba3 = inspect.signature(foo).bind(2) 5564 self.assertFalse(ba == ba3) 5565 self.assertTrue(ba != ba3) 5566 ba3.arguments['a'] = 1 5567 self.assertTrue(ba == ba3) 5568 self.assertFalse(ba != ba3) 5569 5570 def bar(b): pass 5571 ba4 = inspect.signature(bar).bind(1) 5572 self.assertFalse(ba == ba4) 5573 self.assertTrue(ba != ba4) 5574 5575 def foo(*, a, b): pass 5576 sig = inspect.signature(foo) 5577 ba1 = sig.bind(a=1, b=2) 5578 ba2 = sig.bind(b=2, a=1) 5579 self.assertTrue(ba1 == ba2) 5580 self.assertFalse(ba1 != ba2) 5581 5582 def test_signature_bound_arguments_pickle(self): 5583 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass 5584 sig = inspect.signature(foo) 5585 ba = sig.bind(20, 30, z={}) 5586 5587 for ver in range(pickle.HIGHEST_PROTOCOL + 1): 5588 with self.subTest(pickle_ver=ver): 5589 ba_pickled = pickle.loads(pickle.dumps(ba, ver)) 5590 self.assertEqual(ba, ba_pickled) 5591 5592 def test_signature_bound_arguments_repr(self): 5593 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass 5594 sig = inspect.signature(foo) 5595 ba = sig.bind(20, 30, z={}) 5596 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>') 5597 5598 def test_signature_bound_arguments_apply_defaults(self): 5599 def foo(a, b=1, *args, c:1={}, **kw): pass 5600 sig = inspect.signature(foo) 5601 5602 ba = sig.bind(20) 5603 ba.apply_defaults() 5604 self.assertEqual( 5605 list(ba.arguments.items()), 5606 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})]) 5607 5608 # Make sure that we preserve the order: 5609 # i.e. 'c' should be *before* 'kw'. 5610 ba = sig.bind(10, 20, 30, d=1) 5611 ba.apply_defaults() 5612 self.assertEqual( 5613 list(ba.arguments.items()), 5614 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})]) 5615 5616 # Make sure that BoundArguments produced by bind_partial() 5617 # are supported. 5618 def foo(a, b): pass 5619 sig = inspect.signature(foo) 5620 ba = sig.bind_partial(20) 5621 ba.apply_defaults() 5622 self.assertEqual( 5623 list(ba.arguments.items()), 5624 [('a', 20)]) 5625 5626 # Test no args 5627 def foo(): pass 5628 sig = inspect.signature(foo) 5629 ba = sig.bind() 5630 ba.apply_defaults() 5631 self.assertEqual(list(ba.arguments.items()), []) 5632 5633 # Make sure a no-args binding still acquires proper defaults. 5634 def foo(a='spam'): pass 5635 sig = inspect.signature(foo) 5636 ba = sig.bind() 5637 ba.apply_defaults() 5638 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')]) 5639 5640 def test_signature_bound_arguments_arguments_type(self): 5641 def foo(a): pass 5642 ba = inspect.signature(foo).bind(1) 5643 self.assertIs(type(ba.arguments), dict) 5644 5645class TestSignaturePrivateHelpers(unittest.TestCase): 5646 def _strip_non_python_syntax(self, input, 5647 clean_signature, self_parameter): 5648 computed_clean_signature, \ 5649 computed_self_parameter = \ 5650 inspect._signature_strip_non_python_syntax(input) 5651 self.assertEqual(computed_clean_signature, clean_signature) 5652 self.assertEqual(computed_self_parameter, self_parameter) 5653 5654 def test_signature_strip_non_python_syntax(self): 5655 self._strip_non_python_syntax( 5656 "($module, /, path, mode, *, dir_fd=None, " + 5657 "effective_ids=False,\n follow_symlinks=True)", 5658 "(module, /, path, mode, *, dir_fd=None, " + 5659 "effective_ids=False, follow_symlinks=True)", 5660 0) 5661 5662 self._strip_non_python_syntax( 5663 "($module, word, salt, /)", 5664 "(module, word, salt, /)", 5665 0) 5666 5667 self._strip_non_python_syntax( 5668 "(x, y=None, z=None, /)", 5669 "(x, y=None, z=None, /)", 5670 None) 5671 5672 self._strip_non_python_syntax( 5673 "(x, y=None, z=None)", 5674 "(x, y=None, z=None)", 5675 None) 5676 5677 self._strip_non_python_syntax( 5678 "(x,\n y=None,\n z = None )", 5679 "(x, y=None, z=None)", 5680 None) 5681 5682 self._strip_non_python_syntax( 5683 "", 5684 "", 5685 None) 5686 5687 self._strip_non_python_syntax( 5688 None, 5689 None, 5690 None) 5691 5692class TestSignatureDefinitions(unittest.TestCase): 5693 # This test case provides a home for checking that particular APIs 5694 # have signatures available for introspection 5695 5696 @staticmethod 5697 def is_public(name): 5698 return not name.startswith('_') or name.startswith('__') and name.endswith('__') 5699 5700 @cpython_only 5701 @unittest.skipIf(MISSING_C_DOCSTRINGS, 5702 "Signature information for builtins requires docstrings") 5703 def _test_module_has_signatures(self, module, 5704 no_signature=(), unsupported_signature=(), 5705 methods_no_signature={}, methods_unsupported_signature={}, 5706 good_exceptions=()): 5707 # This checks all builtin callables in CPython have signatures 5708 # A few have signatures Signature can't yet handle, so we skip those 5709 # since they will have to wait until PEP 457 adds the required 5710 # introspection support to the inspect module 5711 # Some others also haven't been converted yet for various other 5712 # reasons, so we also skip those for the time being, but design 5713 # the test to fail in order to indicate when it needs to be 5714 # updated. 5715 no_signature = no_signature or set() 5716 # Check the signatures we expect to be there 5717 ns = vars(module) 5718 try: 5719 names = set(module.__all__) 5720 except AttributeError: 5721 names = set(name for name in ns if self.is_public(name)) 5722 for name, obj in sorted(ns.items()): 5723 if name not in names: 5724 continue 5725 if not callable(obj): 5726 continue 5727 if (isinstance(obj, type) and 5728 issubclass(obj, BaseException) and 5729 name not in good_exceptions): 5730 no_signature.add(name) 5731 if name not in no_signature and name not in unsupported_signature: 5732 with self.subTest('supported', builtin=name): 5733 self.assertIsNotNone(inspect.signature(obj)) 5734 if isinstance(obj, type): 5735 with self.subTest(type=name): 5736 self._test_builtin_methods_have_signatures(obj, 5737 methods_no_signature.get(name, ()), 5738 methods_unsupported_signature.get(name, ())) 5739 # Check callables that haven't been converted don't claim a signature 5740 # This ensures this test will start failing as more signatures are 5741 # added, so the affected items can be moved into the scope of the 5742 # regression test above 5743 for name in no_signature: 5744 with self.subTest('none', builtin=name): 5745 obj = ns[name] 5746 self.assertIsNone(obj.__text_signature__) 5747 self.assertRaises(ValueError, inspect.signature, obj) 5748 for name in unsupported_signature: 5749 with self.subTest('unsupported', builtin=name): 5750 obj = ns[name] 5751 self.assertIsNotNone(obj.__text_signature__) 5752 self.assertRaises(ValueError, inspect.signature, obj) 5753 5754 def _test_builtin_methods_have_signatures(self, cls, no_signature, unsupported_signature): 5755 ns = vars(cls) 5756 for name in ns: 5757 obj = getattr(cls, name, None) 5758 if not callable(obj) or isinstance(obj, type): 5759 continue 5760 if name not in no_signature and name not in unsupported_signature: 5761 with self.subTest('supported', method=name): 5762 self.assertIsNotNone(inspect.signature(obj)) 5763 for name in no_signature: 5764 with self.subTest('none', method=name): 5765 self.assertIsNone(getattr(cls, name).__text_signature__) 5766 self.assertRaises(ValueError, inspect.signature, getattr(cls, name)) 5767 for name in unsupported_signature: 5768 with self.subTest('unsupported', method=name): 5769 self.assertIsNotNone(getattr(cls, name).__text_signature__) 5770 self.assertRaises(ValueError, inspect.signature, getattr(cls, name)) 5771 5772 def test_builtins_have_signatures(self): 5773 no_signature = {'type', 'super', 'bytearray', 'bytes', 'dict', 'int', 'str'} 5774 # These need PEP 457 groups 5775 needs_groups = {"range", "slice", "dir", "getattr", 5776 "next", "iter", "vars"} 5777 no_signature |= needs_groups 5778 # These have unrepresentable parameter default values of NULL 5779 unsupported_signature = {"anext"} 5780 # These need *args support in Argument Clinic 5781 needs_varargs = {"min", "max", "__build_class__"} 5782 no_signature |= needs_varargs 5783 5784 methods_no_signature = { 5785 'dict': {'update'}, 5786 'object': {'__class__'}, 5787 } 5788 methods_unsupported_signature = { 5789 'bytearray': {'count', 'endswith', 'find', 'hex', 'index', 'rfind', 'rindex', 'startswith'}, 5790 'bytes': {'count', 'endswith', 'find', 'hex', 'index', 'rfind', 'rindex', 'startswith'}, 5791 'dict': {'pop'}, 5792 'int': {'__round__'}, 5793 'memoryview': {'cast', 'hex'}, 5794 'str': {'count', 'endswith', 'find', 'index', 'maketrans', 'rfind', 'rindex', 'startswith'}, 5795 } 5796 self._test_module_has_signatures(builtins, 5797 no_signature, unsupported_signature, 5798 methods_no_signature, methods_unsupported_signature) 5799 5800 def test_types_module_has_signatures(self): 5801 unsupported_signature = {'CellType'} 5802 methods_no_signature = { 5803 'AsyncGeneratorType': {'athrow'}, 5804 'CoroutineType': {'throw'}, 5805 'GeneratorType': {'throw'}, 5806 } 5807 self._test_module_has_signatures(types, 5808 unsupported_signature=unsupported_signature, 5809 methods_no_signature=methods_no_signature) 5810 5811 def test_sys_module_has_signatures(self): 5812 no_signature = {'getsizeof', 'set_asyncgen_hooks'} 5813 no_signature |= {name for name in ['getobjects'] 5814 if hasattr(sys, name)} 5815 self._test_module_has_signatures(sys, no_signature) 5816 5817 def test_abc_module_has_signatures(self): 5818 import abc 5819 self._test_module_has_signatures(abc) 5820 5821 def test_atexit_module_has_signatures(self): 5822 import atexit 5823 self._test_module_has_signatures(atexit) 5824 5825 def test_codecs_module_has_signatures(self): 5826 import codecs 5827 methods_no_signature = {'StreamReader': {'charbuffertype'}} 5828 self._test_module_has_signatures(codecs, 5829 methods_no_signature=methods_no_signature) 5830 5831 def test_collections_module_has_signatures(self): 5832 no_signature = {'OrderedDict', 'defaultdict'} 5833 unsupported_signature = {'deque'} 5834 methods_no_signature = { 5835 'OrderedDict': {'update'}, 5836 } 5837 methods_unsupported_signature = { 5838 'deque': {'index'}, 5839 'OrderedDict': {'pop'}, 5840 'UserString': {'maketrans'}, 5841 } 5842 self._test_module_has_signatures(collections, 5843 no_signature, unsupported_signature, 5844 methods_no_signature, methods_unsupported_signature) 5845 5846 def test_collections_abc_module_has_signatures(self): 5847 import collections.abc 5848 self._test_module_has_signatures(collections.abc) 5849 5850 def test_errno_module_has_signatures(self): 5851 import errno 5852 self._test_module_has_signatures(errno) 5853 5854 def test_faulthandler_module_has_signatures(self): 5855 import faulthandler 5856 unsupported_signature = {'dump_traceback', 'dump_traceback_later', 'enable'} 5857 unsupported_signature |= {name for name in ['register'] 5858 if hasattr(faulthandler, name)} 5859 self._test_module_has_signatures(faulthandler, unsupported_signature=unsupported_signature) 5860 5861 def test_functools_module_has_signatures(self): 5862 no_signature = {'reduce'} 5863 self._test_module_has_signatures(functools, no_signature) 5864 5865 def test_gc_module_has_signatures(self): 5866 import gc 5867 no_signature = {'set_threshold'} 5868 self._test_module_has_signatures(gc, no_signature) 5869 5870 def test_io_module_has_signatures(self): 5871 methods_no_signature = { 5872 'BufferedRWPair': {'read', 'peek', 'read1', 'readinto', 'readinto1', 'write'}, 5873 } 5874 self._test_module_has_signatures(io, 5875 methods_no_signature=methods_no_signature) 5876 5877 def test_itertools_module_has_signatures(self): 5878 import itertools 5879 no_signature = {'islice', 'repeat'} 5880 self._test_module_has_signatures(itertools, no_signature) 5881 5882 def test_locale_module_has_signatures(self): 5883 import locale 5884 self._test_module_has_signatures(locale) 5885 5886 def test_marshal_module_has_signatures(self): 5887 import marshal 5888 self._test_module_has_signatures(marshal) 5889 5890 def test_operator_module_has_signatures(self): 5891 import operator 5892 self._test_module_has_signatures(operator) 5893 5894 def test_os_module_has_signatures(self): 5895 unsupported_signature = {'chmod', 'utime'} 5896 unsupported_signature |= {name for name in 5897 ['get_terminal_size', 'posix_spawn', 'posix_spawnp', 5898 'register_at_fork', 'startfile'] 5899 if hasattr(os, name)} 5900 self._test_module_has_signatures(os, unsupported_signature=unsupported_signature) 5901 5902 def test_pwd_module_has_signatures(self): 5903 pwd = import_helper.import_module('pwd') 5904 self._test_module_has_signatures(pwd) 5905 5906 def test_re_module_has_signatures(self): 5907 import re 5908 methods_no_signature = {'Match': {'group'}} 5909 self._test_module_has_signatures(re, 5910 methods_no_signature=methods_no_signature, 5911 good_exceptions={'error', 'PatternError'}) 5912 5913 def test_signal_module_has_signatures(self): 5914 import signal 5915 self._test_module_has_signatures(signal) 5916 5917 def test_stat_module_has_signatures(self): 5918 import stat 5919 self._test_module_has_signatures(stat) 5920 5921 def test_string_module_has_signatures(self): 5922 import string 5923 self._test_module_has_signatures(string) 5924 5925 def test_symtable_module_has_signatures(self): 5926 import symtable 5927 self._test_module_has_signatures(symtable) 5928 5929 def test_sysconfig_module_has_signatures(self): 5930 import sysconfig 5931 self._test_module_has_signatures(sysconfig) 5932 5933 def test_threading_module_has_signatures(self): 5934 import threading 5935 self._test_module_has_signatures(threading) 5936 5937 def test_thread_module_has_signatures(self): 5938 import _thread 5939 no_signature = {'RLock'} 5940 self._test_module_has_signatures(_thread, no_signature) 5941 5942 def test_time_module_has_signatures(self): 5943 no_signature = { 5944 'asctime', 'ctime', 'get_clock_info', 'gmtime', 'localtime', 5945 'strftime', 'strptime' 5946 } 5947 no_signature |= {name for name in 5948 ['clock_getres', 'clock_settime', 'clock_settime_ns', 5949 'pthread_getcpuclockid'] 5950 if hasattr(time, name)} 5951 self._test_module_has_signatures(time, no_signature) 5952 5953 def test_tokenize_module_has_signatures(self): 5954 import tokenize 5955 self._test_module_has_signatures(tokenize) 5956 5957 def test_tracemalloc_module_has_signatures(self): 5958 import tracemalloc 5959 self._test_module_has_signatures(tracemalloc) 5960 5961 def test_typing_module_has_signatures(self): 5962 import typing 5963 no_signature = {'ParamSpec', 'ParamSpecArgs', 'ParamSpecKwargs', 5964 'Text', 'TypeAliasType', 'TypeVar', 'TypeVarTuple'} 5965 methods_no_signature = { 5966 'Generic': {'__class_getitem__', '__init_subclass__'}, 5967 } 5968 methods_unsupported_signature = { 5969 'Text': {'count', 'find', 'index', 'rfind', 'rindex', 'startswith', 'endswith', 'maketrans'}, 5970 } 5971 self._test_module_has_signatures(typing, no_signature, 5972 methods_no_signature=methods_no_signature, 5973 methods_unsupported_signature=methods_unsupported_signature) 5974 5975 def test_warnings_module_has_signatures(self): 5976 unsupported_signature = {'warn', 'warn_explicit'} 5977 self._test_module_has_signatures(warnings, unsupported_signature=unsupported_signature) 5978 5979 def test_weakref_module_has_signatures(self): 5980 import weakref 5981 no_signature = {'ReferenceType', 'ref'} 5982 self._test_module_has_signatures(weakref, no_signature) 5983 5984 def test_python_function_override_signature(self): 5985 def func(*args, **kwargs): 5986 pass 5987 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)' 5988 sig = inspect.signature(func) 5989 self.assertIsNotNone(sig) 5990 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)') 5991 5992 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)' 5993 sig = inspect.signature(func) 5994 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)') 5995 5996 func.__text_signature__ = '(self, a=1+2, b=4-3, c=1 | 3 | 16)' 5997 sig = inspect.signature(func) 5998 self.assertEqual(str(sig), '(self, a=3, b=1, c=19)') 5999 6000 func.__text_signature__ = '(self, a=1,\nb=2,\n\n\n c=3)' 6001 sig = inspect.signature(func) 6002 self.assertEqual(str(sig), '(self, a=1, b=2, c=3)') 6003 6004 func.__text_signature__ = '(self, x=does_not_exist)' 6005 with self.assertRaises(ValueError): 6006 inspect.signature(func) 6007 func.__text_signature__ = '(self, x=sys, y=inspect)' 6008 with self.assertRaises(ValueError): 6009 inspect.signature(func) 6010 func.__text_signature__ = '(self, 123)' 6011 with self.assertRaises(ValueError): 6012 inspect.signature(func) 6013 6014 @support.requires_docstrings 6015 def test_base_class_have_text_signature(self): 6016 # see issue 43118 6017 from test.typinganndata.ann_module7 import BufferedReader 6018 class MyBufferedReader(BufferedReader): 6019 """buffer reader class.""" 6020 6021 text_signature = BufferedReader.__text_signature__ 6022 self.assertEqual(text_signature, '(raw, buffer_size=DEFAULT_BUFFER_SIZE)') 6023 sig = inspect.signature(MyBufferedReader) 6024 self.assertEqual(str(sig), '(raw, buffer_size=8192)') 6025 6026 6027class NTimesUnwrappable: 6028 def __init__(self, n): 6029 self.n = n 6030 self._next = None 6031 6032 @property 6033 def __wrapped__(self): 6034 if self.n <= 0: 6035 raise Exception("Unwrapped too many times") 6036 if self._next is None: 6037 self._next = NTimesUnwrappable(self.n - 1) 6038 return self._next 6039 6040class TestUnwrap(unittest.TestCase): 6041 6042 def test_unwrap_one(self): 6043 def func(a, b): 6044 return a + b 6045 wrapper = functools.lru_cache(maxsize=20)(func) 6046 self.assertIs(inspect.unwrap(wrapper), func) 6047 6048 def test_unwrap_several(self): 6049 def func(a, b): 6050 return a + b 6051 wrapper = func 6052 for __ in range(10): 6053 @functools.wraps(wrapper) 6054 def wrapper(): 6055 pass 6056 self.assertIsNot(wrapper.__wrapped__, func) 6057 self.assertIs(inspect.unwrap(wrapper), func) 6058 6059 def test_stop(self): 6060 def func1(a, b): 6061 return a + b 6062 @functools.wraps(func1) 6063 def func2(): 6064 pass 6065 @functools.wraps(func2) 6066 def wrapper(): 6067 pass 6068 func2.stop_here = 1 6069 unwrapped = inspect.unwrap(wrapper, 6070 stop=(lambda f: hasattr(f, "stop_here"))) 6071 self.assertIs(unwrapped, func2) 6072 6073 def test_cycle(self): 6074 def func1(): pass 6075 func1.__wrapped__ = func1 6076 with self.assertRaisesRegex(ValueError, 'wrapper loop'): 6077 inspect.unwrap(func1) 6078 6079 def func2(): pass 6080 func2.__wrapped__ = func1 6081 func1.__wrapped__ = func2 6082 with self.assertRaisesRegex(ValueError, 'wrapper loop'): 6083 inspect.unwrap(func1) 6084 with self.assertRaisesRegex(ValueError, 'wrapper loop'): 6085 inspect.unwrap(func2) 6086 6087 def test_unhashable(self): 6088 def func(): pass 6089 func.__wrapped__ = None 6090 class C: 6091 __hash__ = None 6092 __wrapped__ = func 6093 self.assertIsNone(inspect.unwrap(C())) 6094 6095 def test_recursion_limit(self): 6096 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1) 6097 with self.assertRaisesRegex(ValueError, 'wrapper loop'): 6098 inspect.unwrap(obj) 6099 6100 def test_wrapped_descriptor(self): 6101 self.assertIs(inspect.unwrap(NTimesUnwrappable), NTimesUnwrappable) 6102 self.assertIs(inspect.unwrap(staticmethod), staticmethod) 6103 self.assertIs(inspect.unwrap(classmethod), classmethod) 6104 self.assertIs(inspect.unwrap(staticmethod(classmethod)), classmethod) 6105 self.assertIs(inspect.unwrap(classmethod(staticmethod)), staticmethod) 6106 6107 6108class TestMain(unittest.TestCase): 6109 def test_only_source(self): 6110 module = importlib.import_module('unittest') 6111 rc, out, err = assert_python_ok('-m', 'inspect', 6112 'unittest') 6113 lines = out.decode().splitlines() 6114 # ignore the final newline 6115 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines()) 6116 self.assertEqual(err, b'') 6117 6118 def test_custom_getattr(self): 6119 def foo(): 6120 pass 6121 foo.__signature__ = 42 6122 with self.assertRaises(TypeError): 6123 inspect.signature(foo) 6124 6125 @unittest.skipIf(ThreadPoolExecutor is None, 6126 'threads required to test __qualname__ for source files') 6127 def test_qualname_source(self): 6128 rc, out, err = assert_python_ok('-m', 'inspect', 6129 'concurrent.futures:ThreadPoolExecutor') 6130 lines = out.decode().splitlines() 6131 # ignore the final newline 6132 self.assertEqual(lines[:-1], 6133 inspect.getsource(ThreadPoolExecutor).splitlines()) 6134 self.assertEqual(err, b'') 6135 6136 def test_builtins(self): 6137 _, out, err = assert_python_failure('-m', 'inspect', 6138 'sys') 6139 lines = err.decode().splitlines() 6140 self.assertEqual(lines, ["Can't get info for builtin modules."]) 6141 6142 def test_details(self): 6143 module = importlib.import_module('unittest') 6144 args = support.optim_args_from_interpreter_flags() 6145 rc, out, err = assert_python_ok(*args, '-m', 'inspect', 6146 'unittest', '--details') 6147 output = out.decode() 6148 # Just a quick sanity check on the output 6149 self.assertIn(module.__spec__.name, output) 6150 self.assertIn(module.__name__, output) 6151 self.assertIn(module.__spec__.origin, output) 6152 self.assertIn(module.__file__, output) 6153 self.assertIn(module.__spec__.cached, output) 6154 self.assertIn(module.__cached__, output) 6155 self.assertEqual(err, b'') 6156 6157 6158class TestReload(unittest.TestCase): 6159 6160 src_before = textwrap.dedent("""\ 6161def foo(): 6162 print("Bla") 6163 """) 6164 6165 src_after = textwrap.dedent("""\ 6166def foo(): 6167 print("Oh no!") 6168 """) 6169 6170 def assertInspectEqual(self, path, source): 6171 inspected_src = inspect.getsource(source) 6172 with open(path, encoding='utf-8') as src: 6173 self.assertEqual( 6174 src.read().splitlines(True), 6175 inspected_src.splitlines(True) 6176 ) 6177 6178 def test_getsource_reload(self): 6179 # see issue 1218234 6180 with ready_to_import('reload_bug', self.src_before) as (name, path): 6181 module = importlib.import_module(name) 6182 self.assertInspectEqual(path, module) 6183 with open(path, 'w', encoding='utf-8') as src: 6184 src.write(self.src_after) 6185 self.assertInspectEqual(path, module) 6186 6187 6188class TestRepl(unittest.TestCase): 6189 6190 def spawn_repl(self, *args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kw): 6191 """Run the Python REPL with the given arguments. 6192 6193 kw is extra keyword args to pass to subprocess.Popen. Returns a Popen 6194 object. 6195 """ 6196 6197 # To run the REPL without using a terminal, spawn python with the command 6198 # line option '-i' and the process name set to '<stdin>'. 6199 # The directory of argv[0] must match the directory of the Python 6200 # executable for the Popen() call to python to succeed as the directory 6201 # path may be used by Py_GetPath() to build the default module search 6202 # path. 6203 stdin_fname = os.path.join(os.path.dirname(sys.executable), "<stdin>") 6204 cmd_line = [stdin_fname, '-E', '-i'] 6205 cmd_line.extend(args) 6206 6207 # Set TERM=vt100, for the rationale see the comments in spawn_python() of 6208 # test.support.script_helper. 6209 env = kw.setdefault('env', dict(os.environ)) 6210 env['TERM'] = 'vt100' 6211 return subprocess.Popen(cmd_line, 6212 executable=sys.executable, 6213 text=True, 6214 stdin=subprocess.PIPE, 6215 stdout=stdout, stderr=stderr, 6216 **kw) 6217 6218 def run_on_interactive_mode(self, source): 6219 """Spawn a new Python interpreter, pass the given 6220 input source code from the stdin and return the 6221 result back. If the interpreter exits non-zero, it 6222 raises a ValueError.""" 6223 6224 process = self.spawn_repl() 6225 process.stdin.write(source) 6226 output = kill_python(process) 6227 6228 if process.returncode != 0: 6229 raise ValueError("Process didn't exit properly.") 6230 return output 6231 6232 @unittest.skipIf(not has_subprocess_support, "test requires subprocess") 6233 def test_getsource(self): 6234 output = self.run_on_interactive_mode(textwrap.dedent("""\ 6235 def f(): 6236 print(0) 6237 return 1 + 2 6238 6239 import inspect 6240 print(f"The source is: <<<{inspect.getsource(f)}>>>") 6241 """)) 6242 6243 expected = "The source is: <<<def f():\n print(0)\n return 1 + 2\n>>>" 6244 self.assertIn(expected, output) 6245 6246 6247 6248 6249if __name__ == "__main__": 6250 unittest.main() 6251