Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(80693)

Delta Between Two Patch Sets: Lib/test/test_inspect.py

Issue 16510: Using appropriate checks in tests
Left Patch Set: Created 6 years, 9 months ago
Right Patch Set: Created 5 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Lib/test/test_hmac.py ('k') | Lib/test/test_iter.py » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 import collections
2 import datetime
3 import functools
4 import importlib
5 import inspect
6 import io
7 import linecache
8 import os
9 from os.path import normcase
10 import _pickle
1 import re 11 import re
12 import shutil
2 import sys 13 import sys
3 import types 14 import types
15 import unicodedata
4 import unittest 16 import unittest
5 import inspect 17
6 import linecache 18 try:
7 import datetime 19 from concurrent.futures import ThreadPoolExecutor
8 import collections 20 except ImportError:
9 import os 21 ThreadPoolExecutor = None
10 import shutil 22
11 from os.path import normcase 23 from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
12 24 from test.support import MISSING_C_DOCSTRINGS
13 from test.support import run_unittest, TESTFN, DirsOnSysPath 25 from test.script_helper import assert_python_ok, assert_python_failure
14
15 from test import inspect_fodder as mod 26 from test import inspect_fodder as mod
16 from test import inspect_fodder2 as mod2 27 from test import inspect_fodder2 as mod2
17 28
18 # C module for test_findsource_binary
19 import unicodedata
20 29
21 # Functions tested in this suite: 30 # Functions tested in this suite:
22 # ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode, 31 # ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
23 # isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers, 32 # isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
24 # getdoc, getfile, getmodule, getsourcefile, getcomments, getsource, 33 # getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
25 # getclasstree, getargspec, getargvalues, formatargspec, formatargvalues, 34 # getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
26 # currentframe, stack, trace, isdatadescriptor 35 # currentframe, stack, trace, isdatadescriptor
27 36
28 # NOTE: There are some additional tests relating to interaction with 37 # NOTE: There are some additional tests relating to interaction with
29 # zipimport in the test_zipimport_support test module. 38 # zipimport in the test_zipimport_support test module.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 self.assertTrue(inspect.isclass(list)) 122 self.assertTrue(inspect.isclass(list))
114 123
115 class CustomGetattr(object): 124 class CustomGetattr(object):
116 def __getattr__(self, attr): 125 def __getattr__(self, attr):
117 return None 126 return None
118 self.assertFalse(inspect.isclass(CustomGetattr())) 127 self.assertFalse(inspect.isclass(CustomGetattr()))
119 128
120 def test_get_slot_members(self): 129 def test_get_slot_members(self):
121 class C(object): 130 class C(object):
122 __slots__ = ("a", "b") 131 __slots__ = ("a", "b")
123
124 x = C() 132 x = C()
125 x.a = 42 133 x.a = 42
126 members = dict(inspect.getmembers(x)) 134 members = dict(inspect.getmembers(x))
127 self.assertIn('a', members) 135 self.assertIn('a', members)
128 self.assertNotIn('b', members) 136 self.assertNotIn('b', members)
129 137
130 def test_isabstract(self): 138 def test_isabstract(self):
131 from abc import ABCMeta, abstractmethod 139 from abc import ABCMeta, abstractmethod
132 140
133 class AbstractClassExample(metaclass=ABCMeta): 141 class AbstractClassExample(metaclass=ABCMeta):
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 225
218 class TestRetrievingSourceCode(GetSourceBase): 226 class TestRetrievingSourceCode(GetSourceBase):
219 fodderModule = mod 227 fodderModule = mod
220 228
221 def test_getclasses(self): 229 def test_getclasses(self):
222 classes = inspect.getmembers(mod, inspect.isclass) 230 classes = inspect.getmembers(mod, inspect.isclass)
223 self.assertEqual(classes, 231 self.assertEqual(classes,
224 [('FesteringGob', mod.FesteringGob), 232 [('FesteringGob', mod.FesteringGob),
225 ('MalodorousPervert', mod.MalodorousPervert), 233 ('MalodorousPervert', mod.MalodorousPervert),
226 ('ParrotDroppings', mod.ParrotDroppings), 234 ('ParrotDroppings', mod.ParrotDroppings),
227 ('StupidGit', mod.StupidGit)]) 235 ('StupidGit', mod.StupidGit),
228 tree = inspect.getclasstree([cls[1] for cls in classes], 1) 236 ('Tit', mod.MalodorousPervert),
237 ])
238 tree = inspect.getclasstree([cls[1] for cls in classes])
239 self.assertEqual(tree,
240 [(object, ()),
241 [(mod.ParrotDroppings, (object,)),
242 [(mod.FesteringGob, (mod.MalodorousPervert,
243 mod.ParrotDroppings))
244 ],
245 (mod.StupidGit, (object,)),
246 [(mod.MalodorousPervert, (mod.StupidGit,)),
247 [(mod.FesteringGob, (mod.MalodorousPervert,
248 mod.ParrotDroppings))
249 ]
250 ]
251 ]
252 ])
253 tree = inspect.getclasstree([cls[1] for cls in classes], True)
229 self.assertEqual(tree, 254 self.assertEqual(tree,
230 [(object, ()), 255 [(object, ()),
231 [(mod.ParrotDroppings, (object,)), 256 [(mod.ParrotDroppings, (object,)),
232 (mod.StupidGit, (object,)), 257 (mod.StupidGit, (object,)),
233 [(mod.MalodorousPervert, (mod.StupidGit,)), 258 [(mod.MalodorousPervert, (mod.StupidGit,)),
234 [(mod.FesteringGob, (mod.MalodorousPervert, 259 [(mod.FesteringGob, (mod.MalodorousPervert,
235 mod.ParrotDroppings)) 260 mod.ParrotDroppings))
236 ] 261 ]
237 ] 262 ]
238 ] 263 ]
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 co = compile("None", fn, "exec") 310 co = compile("None", fn, "exec")
286 self.assertEqual(inspect.getsourcefile(co), None) 311 self.assertEqual(inspect.getsourcefile(co), None)
287 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename) 312 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
288 try: 313 try:
289 self.assertEqual(normcase(inspect.getsourcefile(co)), fn) 314 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
290 finally: 315 finally:
291 del linecache.cache[co.co_filename] 316 del linecache.cache[co.co_filename]
292 317
293 def test_getfile(self): 318 def test_getfile(self):
294 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__) 319 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
320
321 def test_getfile_class_without_module(self):
322 class CM(type):
323 @property
324 def __module__(cls):
325 raise AttributeError
326 class C(metaclass=CM):
327 pass
328 with self.assertRaises(TypeError):
329 inspect.getfile(C)
295 330
296 def test_getmodule_recursion(self): 331 def test_getmodule_recursion(self):
297 from types import ModuleType 332 from types import ModuleType
298 name = '__inspect_dummy' 333 name = '__inspect_dummy'
299 m = sys.modules[name] = ModuleType(name) 334 m = sys.modules[name] = ModuleType(name)
300 m.__file__ = "<string>" # hopefully not a real filename... 335 m.__file__ = "<string>" # hopefully not a real filename...
301 m.__loader__ = "dummy" # pretend the filename is understood by a loader 336 m.__loader__ = "dummy" # pretend the filename is understood by a loader
302 exec("def x(): pass", m.__dict__) 337 exec("def x(): pass", m.__dict__)
303 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>') 338 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
304 del sys.modules[name] 339 del sys.modules[name]
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 self.assertSourceEqual(mod2.func88, 88, 90) 429 self.assertSourceEqual(mod2.func88, 88, 90)
395 430
396 def test_method_in_dynamic_class(self): 431 def test_method_in_dynamic_class(self):
397 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97) 432 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
398 433
399 @unittest.skipIf( 434 @unittest.skipIf(
400 not hasattr(unicodedata, '__file__') or 435 not hasattr(unicodedata, '__file__') or
401 unicodedata.__file__[-4:] in (".pyc", ".pyo"), 436 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
402 "unicodedata is not an external binary module") 437 "unicodedata is not an external binary module")
403 def test_findsource_binary(self): 438 def test_findsource_binary(self):
404 self.assertRaises(IOError, inspect.getsource, unicodedata) 439 self.assertRaises(OSError, inspect.getsource, unicodedata)
405 self.assertRaises(IOError, inspect.findsource, unicodedata) 440 self.assertRaises(OSError, inspect.findsource, unicodedata)
406 441
407 def test_findsource_code_in_linecache(self): 442 def test_findsource_code_in_linecache(self):
408 lines = ["x=1"] 443 lines = ["x=1"]
409 co = compile(lines[0], "_dynamically_created_file", "exec") 444 co = compile(lines[0], "_dynamically_created_file", "exec")
410 self.assertRaises(IOError, inspect.findsource, co) 445 self.assertRaises(OSError, inspect.findsource, co)
411 self.assertRaises(IOError, inspect.getsource, co) 446 self.assertRaises(OSError, inspect.getsource, co)
412 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename) 447 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
413 try: 448 try:
414 self.assertEqual(inspect.findsource(co), (lines,0)) 449 self.assertEqual(inspect.findsource(co), (lines,0))
415 self.assertEqual(inspect.getsource(co), lines[0]) 450 self.assertEqual(inspect.getsource(co), lines[0])
416 finally: 451 finally:
417 del linecache.cache[co.co_filename] 452 del linecache.cache[co.co_filename]
453
454 def test_findsource_without_filename(self):
455 for fname in ['', '<string>']:
456 co = compile('x=1', fname, "exec")
457 self.assertRaises(IOError, inspect.findsource, co)
458 self.assertRaises(IOError, inspect.getsource, co)
418 459
419 class TestNoEOL(GetSourceBase): 460 class TestNoEOL(GetSourceBase):
420 def __init__(self, *args, **kwargs): 461 def __init__(self, *args, **kwargs):
421 self.tempdir = TESTFN + '_dir' 462 self.tempdir = TESTFN + '_dir'
422 os.mkdir(self.tempdir) 463 os.mkdir(self.tempdir)
423 with open(os.path.join(self.tempdir, 464 with open(os.path.join(self.tempdir,
424 'inspect_fodder3%spy' % os.extsep), 'w') as f: 465 'inspect_fodder3%spy' % os.extsep), 'w') as f:
425 f.write("class X:\n pass # No EOL") 466 f.write("class X:\n pass # No EOL")
426 with DirsOnSysPath(self.tempdir): 467 with DirsOnSysPath(self.tempdir):
427 import inspect_fodder3 as mod3 468 import inspect_fodder3 as mod3
428 self.fodderModule = mod3 469 self.fodderModule = mod3
429 GetSourceBase.__init__(self, *args, **kwargs) 470 GetSourceBase.__init__(self, *args, **kwargs)
430 471
431 def tearDown(self): 472 def tearDown(self):
432 shutil.rmtree(self.tempdir) 473 shutil.rmtree(self.tempdir)
433 474
434 def test_class(self): 475 def test_class(self):
435 self.assertSourceEqual(self.fodderModule.X, 1, 2) 476 self.assertSourceEqual(self.fodderModule.X, 1, 2)
436 477
437 478
438 class _BrokenDataDescriptor(object): 479 class _BrokenDataDescriptor(object):
439 """ 480 """
440 A broken data descriptor. See bug #1785. 481 A broken data descriptor. See bug #1785.
441 """ 482 """
442 def __get__(*args): 483 def __get__(*args):
443 raise AssertionError("should not __get__ data descriptors") 484 raise AttributeError("broken data descriptor")
444 485
445 def __set__(*args): 486 def __set__(*args):
446 raise RuntimeError 487 raise RuntimeError
447 488
448 def __getattr__(*args): 489 def __getattr__(*args):
449 raise AssertionError("should not __getattr__ data descriptors") 490 raise AttributeError("broken data descriptor")
450 491
451 492
452 class _BrokenMethodDescriptor(object): 493 class _BrokenMethodDescriptor(object):
453 """ 494 """
454 A broken method descriptor. See bug #1785. 495 A broken method descriptor. See bug #1785.
455 """ 496 """
456 def __get__(*args): 497 def __get__(*args):
457 raise AssertionError("should not __get__ method descriptors") 498 raise AttributeError("broken method descriptor")
458 499
459 def __getattr__(*args): 500 def __getattr__(*args):
460 raise AssertionError("should not __getattr__ method descriptors") 501 raise AttributeError("broken method descriptor")
461 502
462 503
463 # Helper for testing classify_class_attrs. 504 # Helper for testing classify_class_attrs.
464 def attrs_wo_objs(cls): 505 def attrs_wo_objs(cls):
465 return [t[:3] for t in inspect.classify_class_attrs(cls)] 506 return [t[:3] for t in inspect.classify_class_attrs(cls)]
466 507
467 508
468 class TestClassesAndFunctions(unittest.TestCase): 509 class TestClassesAndFunctions(unittest.TestCase):
469 def test_newstyle_mro(self): 510 def test_newstyle_mro(self):
470 # The same w/ new-class MRO. 511 # The same w/ new-class MRO.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 kwonlydefaults_e={'arg2':1}, 570 kwonlydefaults_e={'arg2':1},
530 formatted='(*arg1, arg2=1)') 571 formatted='(*arg1, arg2=1)')
531 572
532 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'], 573 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
533 ann_e={'arg1' : list}, 574 ann_e={'arg1' : list},
534 formatted='(arg1: list)') 575 formatted='(arg1: list)')
535 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [], 576 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
536 kwonlyargs_e=['arg'], 577 kwonlyargs_e=['arg'],
537 formatted='(*, arg)') 578 formatted='(*, arg)')
538 579
580 def test_getfullargspec_signature_attr(self):
581 def test():
582 pass
583 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY )
584 test.__signature__ = inspect.Signature(parameters=(spam_param,))
585
586 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
587
588 def test_getfullargspec_signature_annos(self):
589 def test(a:'spam') -> 'ham': pass
590 spec = inspect.getfullargspec(test)
591 self.assertEqual(test.__annotations__, spec.annotations)
592
593 def test(): pass
594 spec = inspect.getfullargspec(test)
595 self.assertEqual(test.__annotations__, spec.annotations)
596
597 @unittest.skipIf(MISSING_C_DOCSTRINGS,
598 "Signature information for builtins requires docstrings")
599 def test_getfullargspec_builtin_methods(self):
600 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
601 args_e=['self', 'obj'], formatted='(self, o bj)')
602
603 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
604 args_e=['self', 'obj'], formatted='(self, o bj)')
605
606 @cpython_only
607 @unittest.skipIf(MISSING_C_DOCSTRINGS,
608 "Signature information for builtins requires docstrings")
609 def test_getfullagrspec_builtin_func(self):
610 import _testcapi
611 builtin = _testcapi.docstring_with_signature_with_defaults
612 spec = inspect.getfullargspec(builtin)
613 self.assertEqual(spec.defaults[0], 'avocado')
614
615 @cpython_only
616 @unittest.skipIf(MISSING_C_DOCSTRINGS,
617 "Signature information for builtins requires docstrings")
618 def test_getfullagrspec_builtin_func_no_signature(self):
619 import _testcapi
620 builtin = _testcapi.docstring_no_signature
621 with self.assertRaises(TypeError):
622 inspect.getfullargspec(builtin)
539 623
540 def test_getargspec_method(self): 624 def test_getargspec_method(self):
541 class A(object): 625 class A(object):
542 def m(self): 626 def m(self):
543 pass 627 pass
544 self.assertArgSpecEquals(A.m, ['self']) 628 self.assertArgSpecEquals(A.m, ['self'])
545 629
546 def test_classify_newstyle(self): 630 def test_classify_newstyle(self):
547 class A(object): 631 class A(object):
548 632
549 def s(): pass 633 def s(): pass
550 s = staticmethod(s) 634 s = staticmethod(s)
551 635
552 def c(cls): pass 636 def c(cls): pass
553 c = classmethod(c) 637 c = classmethod(c)
554 638
555 def getp(self): pass 639 def getp(self): pass
556 p = property(getp) 640 p = property(getp)
557 641
558 def m(self): pass 642 def m(self): pass
559 643
560 def m1(self): pass 644 def m1(self): pass
561 645
562 datablob = '1' 646 datablob = '1'
563 647
564 dd = _BrokenDataDescriptor() 648 dd = _BrokenDataDescriptor()
565 md = _BrokenMethodDescriptor() 649 md = _BrokenMethodDescriptor()
566 650
567 attrs = attrs_wo_objs(A) 651 attrs = attrs_wo_objs(A)
652
653 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
654 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
655
568 self.assertIn(('s', 'static method', A), attrs, 'missing static method') 656 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
569 self.assertIn(('c', 'class method', A), attrs, 'missing class method') 657 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
570 self.assertIn(('p', 'property', A), attrs, 'missing property') 658 self.assertIn(('p', 'property', A), attrs, 'missing property')
571 self.assertIn(('m', 'method', A), attrs, 659 self.assertIn(('m', 'method', A), attrs,
572 'missing plain method: %r' % attrs) 660 'missing plain method: %r' % attrs)
573 self.assertIn(('m1', 'method', A), attrs, 'missing plain method') 661 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
574 self.assertIn(('datablob', 'data', A), attrs, 'missing data') 662 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
575 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor') 663 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
576 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor') 664 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
577 665
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor') 707 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
620 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor') 708 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
621 709
622 def test_classify_builtin_types(self): 710 def test_classify_builtin_types(self):
623 # Simple sanity check that all built-in types can have their 711 # Simple sanity check that all built-in types can have their
624 # attributes classified. 712 # attributes classified.
625 for name in dir(__builtins__): 713 for name in dir(__builtins__):
626 builtin = getattr(__builtins__, name) 714 builtin = getattr(__builtins__, name)
627 if isinstance(builtin, type): 715 if isinstance(builtin, type):
628 inspect.classify_class_attrs(builtin) 716 inspect.classify_class_attrs(builtin)
717
718 def test_classify_DynamicClassAttribute(self):
719 class Meta(type):
720 def __getattr__(self, name):
721 if name == 'ham':
722 return 'spam'
723 return super().__getattr__(name)
724 class VA(metaclass=Meta):
725 @types.DynamicClassAttribute
726 def ham(self):
727 return 'eggs'
728 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham' ])
729 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
730 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
731 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
732
733 def test_classify_metaclass_class_attribute(self):
734 class Meta(type):
735 fish = 'slap'
736 def __dir__(self):
737 return ['__class__', '__modules__', '__name__', 'fish']
738 class Class(metaclass=Meta):
739 pass
740 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
741 self.assertIn(should_find, inspect.classify_class_attrs(Class))
742
743 def test_classify_VirtualAttribute(self):
744 class Meta(type):
745 def __dir__(cls):
746 return ['__class__', '__module__', '__name__', 'BOOM']
747 def __getattr__(self, name):
748 if name =='BOOM':
749 return 42
750 return super().__getattr(name)
751 class Class(metaclass=Meta):
752 pass
753 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
754 self.assertIn(should_find, inspect.classify_class_attrs(Class))
755
756 def test_classify_VirtualAttribute_multi_classes(self):
757 class Meta1(type):
758 def __dir__(cls):
759 return ['__class__', '__module__', '__name__', 'one']
760 def __getattr__(self, name):
761 if name =='one':
762 return 1
763 return super().__getattr__(name)
764 class Meta2(type):
765 def __dir__(cls):
766 return ['__class__', '__module__', '__name__', 'two']
767 def __getattr__(self, name):
768 if name =='two':
769 return 2
770 return super().__getattr__(name)
771 class Meta3(Meta1, Meta2):
772 def __dir__(cls):
773 return list(sorted(set(['__class__', '__module__', '__name__', ' three'] +
774 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
775 def __getattr__(self, name):
776 if name =='three':
777 return 3
778 return super().__getattr__(name)
779 class Class1(metaclass=Meta1):
780 pass
781 class Class2(Class1, metaclass=Meta3):
782 pass
783
784 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
785 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
786 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
787 cca = inspect.classify_class_attrs(Class2)
788 for sf in (should_find1, should_find2, should_find3):
789 self.assertIn(sf, cca)
790
791 def test_classify_class_attrs_with_buggy_dir(self):
792 class M(type):
793 def __dir__(cls):
794 return ['__class__', '__name__', 'missing']
795 class C(metaclass=M):
796 pass
797 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
798 self.assertNotIn('missing', attrs)
629 799
630 def test_getmembers_descriptors(self): 800 def test_getmembers_descriptors(self):
631 class A(object): 801 class A(object):
632 dd = _BrokenDataDescriptor() 802 dd = _BrokenDataDescriptor()
633 md = _BrokenMethodDescriptor() 803 md = _BrokenMethodDescriptor()
634 804
635 def pred_wrapper(pred): 805 def pred_wrapper(pred):
636 # A quick'n'dirty way to discard standard attributes of new-style 806 # A quick'n'dirty way to discard standard attributes of new-style
637 # classes. 807 # classes.
638 class Empty(object): 808 class Empty(object):
(...skipping 23 matching lines...) Expand all
662 def test_getmembers_method(self): 832 def test_getmembers_method(self):
663 class B: 833 class B:
664 def f(self): 834 def f(self):
665 pass 835 pass
666 836
667 self.assertIn(('f', B.f), inspect.getmembers(B)) 837 self.assertIn(('f', B.f), inspect.getmembers(B))
668 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod)) 838 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
669 b = B() 839 b = B()
670 self.assertIn(('f', b.f), inspect.getmembers(b)) 840 self.assertIn(('f', b.f), inspect.getmembers(b))
671 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod)) 841 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
842
843 def test_getmembers_VirtualAttribute(self):
844 class M(type):
845 def __getattr__(cls, name):
846 if name == 'eggs':
847 return 'scrambled'
848 return super().__getattr__(name)
849 class A(metaclass=M):
850 @types.DynamicClassAttribute
851 def eggs(self):
852 return 'spam'
853 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
854 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
855
856 def test_getmembers_with_buggy_dir(self):
857 class M(type):
858 def __dir__(cls):
859 return ['__class__', '__name__', 'missing']
860 class C(metaclass=M):
861 pass
862 attrs = [a[0] for a in inspect.getmembers(C)]
863 self.assertNotIn('missing', attrs)
672 864
673 865
674 _global_ref = object() 866 _global_ref = object()
675 class TestGetClosureVars(unittest.TestCase): 867 class TestGetClosureVars(unittest.TestCase):
676 868
677 def test_name_resolution(self): 869 def test_name_resolution(self):
678 # Basic test of the 4 different resolution mechanisms 870 # Basic test of the 4 different resolution mechanisms
679 def f(nonlocal_ref): 871 def f(nonlocal_ref):
680 def g(local_ref): 872 def g(local_ref):
681 print(local_ref, nonlocal_ref, _global_ref, unbound_ref) 873 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 x = desc 1242 x = desc
1051 thing = Thing() 1243 thing = Thing()
1052 self.assertEqual(inspect.getattr_static(thing, 'x'), desc) 1244 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1053 1245
1054 def test_classAttribute(self): 1246 def test_classAttribute(self):
1055 class Thing(object): 1247 class Thing(object):
1056 x = object() 1248 x = object()
1057 1249
1058 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x) 1250 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1059 1251
1252 def test_classVirtualAttribute(self):
1253 class Thing(object):
1254 @types.DynamicClassAttribute
1255 def x(self):
1256 return self._x
1257 _x = object()
1258
1259 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'] )
1260
1060 def test_inherited_classattribute(self): 1261 def test_inherited_classattribute(self):
1061 class Thing(object): 1262 class Thing(object):
1062 x = object() 1263 x = object()
1063 class OtherThing(Thing): 1264 class OtherThing(Thing):
1064 pass 1265 pass
1065 1266
1066 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x) 1267 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1067 1268
1068 def test_slots(self): 1269 def test_slots(self):
1069 class Thing(object): 1270 class Thing(object):
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
1360 for param in sig.parameters.values()), 1561 for param in sig.parameters.values()),
1361 (... if sig.return_annotation is sig.empty 1562 (... if sig.return_annotation is sig.empty
1362 else sig.return_annotation)) 1563 else sig.return_annotation))
1363 1564
1364 def test_signature_object(self): 1565 def test_signature_object(self):
1365 S = inspect.Signature 1566 S = inspect.Signature
1366 P = inspect.Parameter 1567 P = inspect.Parameter
1367 1568
1368 self.assertEqual(str(S()), '()') 1569 self.assertEqual(str(S()), '()')
1369 1570
1370 def test(po, pk, *args, ko, **kwargs): 1571 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
1371 pass 1572 pass
1372 sig = inspect.signature(test) 1573 sig = inspect.signature(test)
1373 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY) 1574 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
1575 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
1374 pk = sig.parameters['pk'] 1576 pk = sig.parameters['pk']
1577 pkd = sig.parameters['pkd']
1375 args = sig.parameters['args'] 1578 args = sig.parameters['args']
1376 ko = sig.parameters['ko'] 1579 ko = sig.parameters['ko']
1377 kwargs = sig.parameters['kwargs'] 1580 kwargs = sig.parameters['kwargs']
1378 1581
1379 S((po, pk, args, ko, kwargs)) 1582 S((po, pk, args, ko, kwargs))
1380 1583
1381 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 1584 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
1382 S((pk, po, args, ko, kwargs)) 1585 S((pk, po, args, ko, kwargs))
1383 1586
1384 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 1587 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
1385 S((po, args, pk, ko, kwargs)) 1588 S((po, args, pk, ko, kwargs))
1386 1589
1387 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 1590 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
1388 S((args, po, pk, ko, kwargs)) 1591 S((args, po, pk, ko, kwargs))
1389 1592
1390 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 1593 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
1391 S((po, pk, args, kwargs, ko)) 1594 S((po, pk, args, kwargs, ko))
1392 1595
1393 kwargs2 = kwargs.replace(name='args') 1596 kwargs2 = kwargs.replace(name='args')
1394 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'): 1597 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
1395 S((po, pk, args, kwargs2, ko)) 1598 S((po, pk, args, kwargs2, ko))
1599
1600 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1601 S((pod, po))
1602
1603 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1604 S((po, pkd, pk))
1605
1606 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1607 S((pkd, pk))
1396 1608
1397 def test_signature_immutability(self): 1609 def test_signature_immutability(self):
1398 def test(a): 1610 def test(a):
1399 pass 1611 pass
1400 sig = inspect.signature(test) 1612 sig = inspect.signature(test)
1401 1613
1402 with self.assertRaises(AttributeError): 1614 with self.assertRaises(AttributeError):
1403 sig.foo = 'bar' 1615 sig.foo = 'bar'
1404 1616
1405 with self.assertRaises(TypeError): 1617 with self.assertRaises(TypeError):
(...skipping 25 matching lines...) Expand all
1431 pass 1643 pass
1432 self.assertEqual(self.signature(test), 1644 self.assertEqual(self.signature(test),
1433 ((('a', ..., ..., "positional_or_keyword"), 1645 ((('a', ..., ..., "positional_or_keyword"),
1434 ('b', 10, 'foo', "positional_or_keyword"), 1646 ('b', 10, 'foo', "positional_or_keyword"),
1435 ('args', ..., 'bar', "var_positional"), 1647 ('args', ..., 'bar', "var_positional"),
1436 ('spam', ..., 'baz', "keyword_only"), 1648 ('spam', ..., 'baz', "keyword_only"),
1437 ('ham', 123, ..., "keyword_only"), 1649 ('ham', 123, ..., "keyword_only"),
1438 ('kwargs', ..., int, "var_keyword")), 1650 ('kwargs', ..., int, "var_keyword")),
1439 ...)) 1651 ...))
1440 1652
1441 def test_signature_on_builtin_function(self): 1653 @cpython_only
1442 with self.assertRaisesRegex(ValueError, 'not supported by signature'): 1654 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1443 inspect.signature(type) 1655 "Signature information for builtins requires docstrings")
1444 with self.assertRaisesRegex(ValueError, 'not supported by signature'): 1656 def test_signature_on_builtins(self):
1445 # support for 'wrapper_descriptor' 1657 import _testcapi
1446 inspect.signature(type.__call__) 1658
1447 with self.assertRaisesRegex(ValueError, 'not supported by signature'): 1659 def test_unbound_method(o):
1448 # support for 'method-wrapper' 1660 """Use this to test unbound methods (things that should have a self) """
1449 inspect.signature(min.__call__) 1661 signature = inspect.signature(o)
1450 with self.assertRaisesRegex(ValueError, 1662 self.assertTrue(isinstance(signature, inspect.Signature))
1451 'no signature found for builtin function'): 1663 self.assertEqual(list(signature.parameters.values())[0].name, 'self' )
1452 # support for 'method-wrapper' 1664 return signature
1453 inspect.signature(min) 1665
1666 def test_callable(o):
1667 """Use this to test bound methods or normal callables (things that d on't expect self)"""
1668 signature = inspect.signature(o)
1669 self.assertTrue(isinstance(signature, inspect.Signature))
1670 if signature.parameters:
1671 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1672 return signature
1673
1674 signature = test_callable(_testcapi.docstring_with_signature_with_defaul ts)
1675 def p(name): return signature.parameters[name].default
1676 self.assertEqual(p('s'), 'avocado')
1677 self.assertEqual(p('b'), b'bytes')
1678 self.assertEqual(p('d'), 3.14)
1679 self.assertEqual(p('i'), 35)
1680 self.assertEqual(p('n'), None)
1681 self.assertEqual(p('t'), True)
1682 self.assertEqual(p('f'), False)
1683 self.assertEqual(p('local'), 3)
1684 self.assertEqual(p('sys'), sys.maxsize)
1685 self.assertEqual(p('exp'), sys.maxsize - 1)
1686
1687 test_callable(type)
1688 test_callable(object)
1689
1690 # normal method
1691 # (PyMethodDescr_Type, "method_descriptor")
1692 test_unbound_method(_pickle.Pickler.dump)
1693 d = _pickle.Pickler(io.StringIO())
1694 test_callable(d.dump)
1695
1696 # static method
1697 test_callable(str.maketrans)
1698 test_callable('abc'.maketrans)
1699
1700 # class method
1701 test_callable(dict.fromkeys)
1702 test_callable({}.fromkeys)
1703
1704 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1705 test_unbound_method(type.__call__)
1706 test_unbound_method(int.__add__)
1707 test_callable((3).__add__)
1708
1709 # _PyMethodWrapper_Type
1710 # support for 'method-wrapper'
1711 test_callable(min.__call__)
1712
1713 class ThisWorksNow:
1714 __call__ = type
1715 test_callable(ThisWorksNow())
1716
1717 @cpython_only
1718 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1719 "Signature information for builtins requires docstrings")
1720 def test_signature_on_decorated_builtins(self):
1721 import _testcapi
1722 func = _testcapi.docstring_with_signature_with_defaults
1723
1724 def decorator(func):
1725 @functools.wraps(func)
1726 def wrapper(*args, **kwargs) -> int:
1727 return func(*args, **kwargs)
1728 return wrapper
1729
1730 decorated_func = decorator(func)
1731
1732 self.assertEqual(inspect.signature(func),
1733 inspect.signature(decorated_func))
1734
1735 @cpython_only
1736 def test_signature_on_builtins_no_signature(self):
1737 import _testcapi
1738 with self.assertRaisesRegex(ValueError, 'no signature found for builtin' ):
1739 inspect.signature(_testcapi.docstring_no_signature)
1454 1740
1455 def test_signature_on_non_function(self): 1741 def test_signature_on_non_function(self):
1456 with self.assertRaisesRegex(TypeError, 'is not a callable object'): 1742 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
1457 inspect.signature(42) 1743 inspect.signature(42)
1458 1744
1459 with self.assertRaisesRegex(TypeError, 'is not a Python function'): 1745 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1460 inspect.Signature.from_function(42) 1746 inspect.Signature.from_function(42)
1461 1747
1748 def test_signature_from_builtin_errors(self):
1749 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1750 inspect.Signature.from_builtin(42)
1751
1752 def test_signature_from_functionlike_object(self):
1753 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1754 pass
1755
1756 class funclike:
1757 # Has to be callable, and have correct
1758 # __code__, __annotations__, __defaults__, __name__,
1759 # and __kwdefaults__ attributes
1760
1761 def __init__(self, func):
1762 self.__name__ = func.__name__
1763 self.__code__ = func.__code__
1764 self.__annotations__ = func.__annotations__
1765 self.__defaults__ = func.__defaults__
1766 self.__kwdefaults__ = func.__kwdefaults__
1767 self.func = func
1768
1769 def __call__(self, *args, **kwargs):
1770 return self.func(*args, **kwargs)
1771
1772 sig_func = inspect.Signature.from_function(func)
1773
1774 sig_funclike = inspect.Signature.from_function(funclike(func))
1775 self.assertEqual(sig_funclike, sig_func)
1776
1777 sig_funclike = inspect.signature(funclike(func))
1778 self.assertEqual(sig_funclike, sig_func)
1779
1780 # If object is not a duck type of function, then
1781 # signature will try to get a signature for its '__call__'
1782 # method
1783 fl = funclike(func)
1784 del fl.__defaults__
1785 self.assertEqual(self.signature(fl),
1786 ((('args', ..., ..., "var_positional"),
1787 ('kwargs', ..., ..., "var_keyword")),
1788 ...))
1789
1790 def test_signature_functionlike_class(self):
1791 # We only want to duck type function-like objects,
1792 # not classes.
1793
1794 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1795 pass
1796
1797 class funclike:
1798 def __init__(self, marker):
1799 pass
1800
1801 __name__ = func.__name__
1802 __code__ = func.__code__
1803 __annotations__ = func.__annotations__
1804 __defaults__ = func.__defaults__
1805 __kwdefaults__ = func.__kwdefaults__
1806
1807 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1808 inspect.Signature.from_function(funclike)
1809
1810 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1811
1462 def test_signature_on_method(self): 1812 def test_signature_on_method(self):
1463 class Test: 1813 class Test:
1464 def foo(self, arg1, arg2=1) -> int: 1814 def __init__(*args):
1465 pass 1815 pass
1466 1816 def m1(self, arg1, arg2=1) -> int:
1467 meth = Test().foo 1817 pass
1468 1818 def m2(*args):
1469 self.assertEqual(self.signature(meth), 1819 pass
1820 def __call__(*, a):
1821 pass
1822
1823 self.assertEqual(self.signature(Test().m1),
1470 ((('arg1', ..., ..., "positional_or_keyword"), 1824 ((('arg1', ..., ..., "positional_or_keyword"),
1471 ('arg2', 1, ..., "positional_or_keyword")), 1825 ('arg2', 1, ..., "positional_or_keyword")),
1472 int)) 1826 int))
1827
1828 self.assertEqual(self.signature(Test().m2),
1829 ((('args', ..., ..., "var_positional"),),
1830 ...))
1831
1832 self.assertEqual(self.signature(Test),
1833 ((('args', ..., ..., "var_positional"),),
1834 ...))
1835
1836 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
1837 self.signature(Test())
1473 1838
1474 def test_signature_on_classmethod(self): 1839 def test_signature_on_classmethod(self):
1475 class Test: 1840 class Test:
1476 @classmethod 1841 @classmethod
1477 def foo(cls, arg1, *, arg2=1): 1842 def foo(cls, arg1, *, arg2=1):
1478 pass 1843 pass
1479 1844
1480 meth = Test().foo 1845 meth = Test().foo
1481 self.assertEqual(self.signature(meth), 1846 self.assertEqual(self.signature(meth),
1482 ((('arg1', ..., ..., "positional_or_keyword"), 1847 ((('arg1', ..., ..., "positional_or_keyword"),
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
1657 ba = inspect.signature(_foo).bind(11, 12) 2022 ba = inspect.signature(_foo).bind(11, 12)
1658 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13)) 2023 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1659 ba = inspect.signature(_foo).bind(11, b=12) 2024 ba = inspect.signature(_foo).bind(11, b=12)
1660 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13)) 2025 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1661 ba = inspect.signature(_foo).bind(b=12) 2026 ba = inspect.signature(_foo).bind(b=12)
1662 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13)) 2027 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
1663 _foo = partial(_foo, b=10) 2028 _foo = partial(_foo, b=10)
1664 ba = inspect.signature(_foo).bind(12, 14) 2029 ba = inspect.signature(_foo).bind(12, 14)
1665 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13)) 2030 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
1666 2031
2032 def test_signature_on_partialmethod(self):
2033 from functools import partialmethod
2034
2035 class Spam:
2036 def test():
2037 pass
2038 ham = partialmethod(test)
2039
2040 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2041 inspect.signature(Spam.ham)
2042
2043 class Spam:
2044 def test(it, a, *, c) -> 'spam':
2045 pass
2046 ham = partialmethod(test, c=1)
2047
2048 self.assertEqual(self.signature(Spam.ham),
2049 ((('it', ..., ..., 'positional_or_keyword'),
2050 ('a', ..., ..., 'positional_or_keyword'),
2051 ('c', 1, ..., 'keyword_only')),
2052 'spam'))
2053
2054 self.assertEqual(self.signature(Spam().ham),
2055 ((('a', ..., ..., 'positional_or_keyword'),
2056 ('c', 1, ..., 'keyword_only')),
2057 'spam'))
2058
2059 def test_signature_on_fake_partialmethod(self):
2060 def foo(a): pass
2061 foo._partialmethod = 'spam'
2062 self.assertEqual(str(inspect.signature(foo)), '(a)')
2063
1667 def test_signature_on_decorated(self): 2064 def test_signature_on_decorated(self):
1668 import functools 2065 import functools
1669 2066
1670 def decorator(func): 2067 def decorator(func):
1671 @functools.wraps(func) 2068 @functools.wraps(func)
1672 def wrapper(*args, **kwargs) -> int: 2069 def wrapper(*args, **kwargs) -> int:
1673 return func(*args, **kwargs) 2070 return func(*args, **kwargs)
1674 return wrapper 2071 return wrapper
1675 2072
1676 class Foo: 2073 class Foo:
(...skipping 28 matching lines...) Expand all
1705 pass 2102 pass
1706 2103
1707 self.assertEqual(self.signature(Foo.__call__), 2104 self.assertEqual(self.signature(Foo.__call__),
1708 ((('a', ..., ..., "positional_or_keyword"), 2105 ((('a', ..., ..., "positional_or_keyword"),
1709 ('b', ..., ..., "positional_or_keyword")), 2106 ('b', ..., ..., "positional_or_keyword")),
1710 ...)) 2107 ...))
1711 2108
1712 self.assertEqual(self.signature(Foo().__call__), 2109 self.assertEqual(self.signature(Foo().__call__),
1713 ((('b', ..., ..., "positional_or_keyword"),), 2110 ((('b', ..., ..., "positional_or_keyword"),),
1714 ...)) 2111 ...))
2112
2113 # Test we handle __signature__ partway down the wrapper stack
2114 def wrapped_foo_call():
2115 pass
2116 wrapped_foo_call.__wrapped__ = Foo.__call__
2117
2118 self.assertEqual(self.signature(wrapped_foo_call),
2119 ((('a', ..., ..., "positional_or_keyword"),
2120 ('b', ..., ..., "positional_or_keyword")),
2121 ...))
2122
1715 2123
1716 def test_signature_on_class(self): 2124 def test_signature_on_class(self):
1717 class C: 2125 class C:
1718 def __init__(self, a): 2126 def __init__(self, a):
1719 pass 2127 pass
1720 2128
1721 self.assertEqual(self.signature(C), 2129 self.assertEqual(self.signature(C),
1722 ((('a', ..., ..., "positional_or_keyword"),), 2130 ((('a', ..., ..., "positional_or_keyword"),),
1723 ...)) 2131 ...))
1724 2132
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1787 def __init__(self, b): 2195 def __init__(self, b):
1788 pass 2196 pass
1789 2197
1790 self.assertEqual(self.signature(CM), 2198 self.assertEqual(self.signature(CM),
1791 ((('name', ..., ..., "positional_or_keyword"), 2199 ((('name', ..., ..., "positional_or_keyword"),
1792 ('bases', ..., ..., "positional_or_keyword"), 2200 ('bases', ..., ..., "positional_or_keyword"),
1793 ('dct', ..., ..., "positional_or_keyword"), 2201 ('dct', ..., ..., "positional_or_keyword"),
1794 ('bar', 2, ..., "keyword_only")), 2202 ('bar', 2, ..., "keyword_only")),
1795 ...)) 2203 ...))
1796 2204
2205 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2206 "Signature information for builtins requires docstrings")
2207 def test_signature_on_class_without_init(self):
2208 # Test classes without user-defined __init__ or __new__
2209 class C: pass
2210 self.assertEqual(str(inspect.signature(C)), '()')
2211 class D(C): pass
2212 self.assertEqual(str(inspect.signature(D)), '()')
2213
2214 # Test meta-classes without user-defined __init__ or __new__
2215 class C(type): pass
2216 self.assertEqual(str(inspect.signature(C)),
2217 '(object_or_name, bases, dict)')
2218 class D(C): pass
2219 self.assertEqual(str(inspect.signature(D)),
2220 '(object_or_name, bases, dict)')
2221
2222 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2223 "Signature information for builtins requires docstrings")
2224 def test_signature_on_builtin_class(self):
2225 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2226 '(file, protocol=None, fix_imports=True)')
2227
2228 class P(_pickle.Pickler): pass
2229 class EmptyTrait: pass
2230 class P2(EmptyTrait, P): pass
2231 self.assertEqual(str(inspect.signature(P)),
2232 '(file, protocol=None, fix_imports=True)')
2233 self.assertEqual(str(inspect.signature(P2)),
2234 '(file, protocol=None, fix_imports=True)')
2235
2236 class P3(P2):
2237 def __init__(self, spam):
2238 pass
2239 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2240
2241 class MetaP(type):
2242 def __call__(cls, foo, bar):
2243 pass
2244 class P4(P2, metaclass=MetaP):
2245 pass
2246 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2247
1797 def test_signature_on_callable_objects(self): 2248 def test_signature_on_callable_objects(self):
1798 class Foo: 2249 class Foo:
1799 def __call__(self, a): 2250 def __call__(self, a):
1800 pass 2251 pass
1801 2252
1802 self.assertEqual(self.signature(Foo()), 2253 self.assertEqual(self.signature(Foo()),
1803 ((('a', ..., ..., "positional_or_keyword"),), 2254 ((('a', ..., ..., "positional_or_keyword"),),
1804 ...)) 2255 ...))
1805 2256
1806 class Spam: 2257 class Spam:
1807 pass 2258 pass
1808 with self.assertRaisesRegex(TypeError, "is not a callable object"): 2259 with self.assertRaisesRegex(TypeError, "is not a callable object"):
1809 inspect.signature(Spam()) 2260 inspect.signature(Spam())
1810 2261
1811 class Bar(Spam, Foo): 2262 class Bar(Spam, Foo):
1812 pass 2263 pass
1813 2264
1814 self.assertEqual(self.signature(Bar()), 2265 self.assertEqual(self.signature(Bar()),
1815 ((('a', ..., ..., "positional_or_keyword"),), 2266 ((('a', ..., ..., "positional_or_keyword"),),
1816 ...)) 2267 ...))
1817 2268
1818 class ToFail:
1819 __call__ = type
1820 with self.assertRaisesRegex(ValueError, "not supported by signature"):
1821 inspect.signature(ToFail())
1822
1823
1824 class Wrapped: 2269 class Wrapped:
1825 pass 2270 pass
1826 Wrapped.__wrapped__ = lambda a: None 2271 Wrapped.__wrapped__ = lambda a: None
1827 self.assertEqual(self.signature(Wrapped), 2272 self.assertEqual(self.signature(Wrapped),
1828 ((('a', ..., ..., "positional_or_keyword"),), 2273 ((('a', ..., ..., "positional_or_keyword"),),
1829 ...)) 2274 ...))
2275 # wrapper loop:
2276 Wrapped.__wrapped__ = Wrapped
2277 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2278 self.signature(Wrapped)
1830 2279
1831 def test_signature_on_lambdas(self): 2280 def test_signature_on_lambdas(self):
1832 self.assertEqual(self.signature((lambda a=10: a)), 2281 self.assertEqual(self.signature((lambda a=10: a)),
1833 ((('a', 10, ..., "positional_or_keyword"),), 2282 ((('a', 10, ..., "positional_or_keyword"),),
1834 ...)) 2283 ...))
1835 2284
1836 def test_signature_equality(self): 2285 def test_signature_equality(self):
1837 def foo(a, *, b:int) -> float: pass 2286 def foo(a, *, b:int) -> float: pass
1838 self.assertNotEqual(inspect.signature(foo), 42) 2287 self.assertNotEqual(inspect.signature(foo), 42)
1839 2288
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1893 pass 2342 pass
1894 self.assertEqual(str(inspect.signature(foo)), 2343 self.assertEqual(str(inspect.signature(foo)),
1895 '(a:int=1, *args, b, c=None, **kwargs) -> 42') 2344 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
1896 2345
1897 def foo(): 2346 def foo():
1898 pass 2347 pass
1899 self.assertEqual(str(inspect.signature(foo)), '()') 2348 self.assertEqual(str(inspect.signature(foo)), '()')
1900 2349
1901 def test_signature_str_positional_only(self): 2350 def test_signature_str_positional_only(self):
1902 P = inspect.Parameter 2351 P = inspect.Parameter
2352 S = inspect.Signature
1903 2353
1904 def test(a_po, *, b, **kwargs): 2354 def test(a_po, *, b, **kwargs):
1905 return a_po, kwargs 2355 return a_po, kwargs
1906 2356
1907 sig = inspect.signature(test) 2357 sig = inspect.signature(test)
1908 new_params = list(sig.parameters.values()) 2358 new_params = list(sig.parameters.values())
1909 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY) 2359 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
1910 test.__signature__ = sig.replace(parameters=new_params) 2360 test.__signature__ = sig.replace(parameters=new_params)
1911 2361
1912 self.assertEqual(str(inspect.signature(test)), 2362 self.assertEqual(str(inspect.signature(test)),
1913 '(<a_po>, *, b, **kwargs)') 2363 '(a_po, /, *, b, **kwargs)')
1914 2364
1915 sig = inspect.signature(test) 2365 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
1916 new_params = list(sig.parameters.values()) 2366 '(foo, /)')
1917 new_params[0] = new_params[0].replace(name=None) 2367
1918 test.__signature__ = sig.replace(parameters=new_params) 2368 self.assertEqual(str(S(parameters=[
1919 self.assertEqual(str(inspect.signature(test)), 2369 P('foo', P.POSITIONAL_ONLY),
1920 '(<0>, *, b, **kwargs)') 2370 P('bar', P.VAR_KEYWORD)])),
2371 '(foo, /, **bar)')
2372
2373 self.assertEqual(str(S(parameters=[
2374 P('foo', P.POSITIONAL_ONLY),
2375 P('bar', P.VAR_POSITIONAL)])),
2376 '(foo, /, *bar)')
1921 2377
1922 def test_signature_replace_anno(self): 2378 def test_signature_replace_anno(self):
1923 def test() -> 42: 2379 def test() -> 42:
1924 pass 2380 pass
1925 2381
1926 sig = inspect.signature(test) 2382 sig = inspect.signature(test)
1927 sig = sig.replace(return_annotation=None) 2383 sig = sig.replace(return_annotation=None)
1928 self.assertIsNone(sig.return_annotation) 2384 self.assertIsNone(sig.return_annotation)
1929 sig = sig.replace(return_annotation=sig.empty) 2385 sig = sig.replace(return_annotation=sig.empty)
1930 self.assertIs(sig.return_annotation, sig.empty) 2386 self.assertIs(sig.return_annotation, sig.empty)
(...skipping 18 matching lines...) Expand all
1949 self.assertEqual(p.default, 10) 2405 self.assertEqual(p.default, 10)
1950 self.assertIs(p.annotation, p.empty) 2406 self.assertIs(p.annotation, p.empty)
1951 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY) 2407 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
1952 2408
1953 with self.assertRaisesRegex(ValueError, 'invalid value'): 2409 with self.assertRaisesRegex(ValueError, 'invalid value'):
1954 inspect.Parameter('foo', default=10, kind='123') 2410 inspect.Parameter('foo', default=10, kind='123')
1955 2411
1956 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'): 2412 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
1957 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD) 2413 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
1958 2414
2415 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2416 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2417
1959 with self.assertRaisesRegex(ValueError, 2418 with self.assertRaisesRegex(ValueError,
1960 'non-positional-only parameter'): 2419 'is not a valid parameter name'):
1961 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD) 2420 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
1962 2421
1963 with self.assertRaisesRegex(ValueError, 'cannot have default values'): 2422 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
1964 inspect.Parameter('a', default=42, 2423 inspect.Parameter('a', default=42,
1965 kind=inspect.Parameter.VAR_KEYWORD) 2424 kind=inspect.Parameter.VAR_KEYWORD)
1966 2425
1967 with self.assertRaisesRegex(ValueError, 'cannot have default values'): 2426 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
1968 inspect.Parameter('a', default=42, 2427 inspect.Parameter('a', default=42,
1969 kind=inspect.Parameter.VAR_POSITIONAL) 2428 kind=inspect.Parameter.VAR_POSITIONAL)
1970 2429
1971 p = inspect.Parameter('a', default=42, 2430 p = inspect.Parameter('a', default=42,
(...skipping 29 matching lines...) Expand all
2001 2460
2002 p2 = p.replace(annotation=1) 2461 p2 = p.replace(annotation=1)
2003 self.assertEqual(p2.annotation, 1) 2462 self.assertEqual(p2.annotation, 1)
2004 p2 = p2.replace(annotation=p2.empty) 2463 p2 = p2.replace(annotation=p2.empty)
2005 self.assertEqual(p, p2) 2464 self.assertEqual(p, p2)
2006 2465
2007 p2 = p2.replace(name='bar') 2466 p2 = p2.replace(name='bar')
2008 self.assertEqual(p2.name, 'bar') 2467 self.assertEqual(p2.name, 'bar')
2009 self.assertNotEqual(p2, p) 2468 self.assertNotEqual(p2, p)
2010 2469
2011 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'): 2470 with self.assertRaisesRegex(ValueError,
2471 'name is a required attribute'):
2012 p2 = p2.replace(name=p2.empty) 2472 p2 = p2.replace(name=p2.empty)
2013 2473
2014 p2 = p2.replace(name='foo', default=None) 2474 p2 = p2.replace(name='foo', default=None)
2015 self.assertIsNone(p2.default) 2475 self.assertIsNone(p2.default)
2016 self.assertNotEqual(p2, p) 2476 self.assertNotEqual(p2, p)
2017 2477
2018 p2 = p2.replace(name='foo', default=p2.empty) 2478 p2 = p2.replace(name='foo', default=p2.empty)
2019 self.assertIs(p2.default, p2.empty) 2479 self.assertIs(p2.default, p2.empty)
2020 2480
2021 2481
2022 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD) 2482 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2023 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD) 2483 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2024 self.assertNotEqual(p2, p) 2484 self.assertNotEqual(p2, p)
2025 2485
2026 with self.assertRaisesRegex(ValueError, 'invalid value for'): 2486 with self.assertRaisesRegex(ValueError, 'invalid value for'):
2027 p2 = p2.replace(kind=p2.empty) 2487 p2 = p2.replace(kind=p2.empty)
2028 2488
2029 p2 = p2.replace(kind=p2.KEYWORD_ONLY) 2489 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2030 self.assertEqual(p2, p) 2490 self.assertEqual(p2, p)
2031 2491
2032 def test_signature_parameter_positional_only(self): 2492 def test_signature_parameter_positional_only(self):
2033 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY) 2493 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2034 self.assertEqual(str(p), '<>') 2494 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2035
2036 p = p.replace(name='1')
2037 self.assertEqual(str(p), '<1>')
2038 2495
2039 def test_signature_parameter_immutability(self): 2496 def test_signature_parameter_immutability(self):
2040 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY) 2497 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
2041 2498
2042 with self.assertRaises(AttributeError): 2499 with self.assertRaises(AttributeError):
2043 p.foo = 'bar' 2500 p.foo = 'bar'
2044 2501
2045 with self.assertRaises(AttributeError): 2502 with self.assertRaises(AttributeError):
2046 p.kind = 123 2503 p.kind = 123
2047 2504
2048 2505
2049 class TestSignatureBind(unittest.TestCase): 2506 class TestSignatureBind(unittest.TestCase):
2050 @staticmethod 2507 @staticmethod
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
2228 sig = inspect.signature(test) 2685 sig = inspect.signature(test)
2229 new_params = collections.OrderedDict(tuple(sig.parameters.items())) 2686 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2230 for name in ('a_po', 'b_po', 'c_po'): 2687 for name in ('a_po', 'b_po', 'c_po'):
2231 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY) 2688 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2232 new_sig = sig.replace(parameters=new_params.values()) 2689 new_sig = sig.replace(parameters=new_params.values())
2233 test.__signature__ = new_sig 2690 test.__signature__ = new_sig
2234 2691
2235 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6), 2692 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2236 (1, 2, 4, 5, 6, {})) 2693 (1, 2, 4, 5, 6, {}))
2237 2694
2695 self.assertEqual(self.call(test, 1, 2),
2696 (1, 2, 3, 42, 50, {}))
2697
2698 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
2699 (1, 2, 3, 4, 5, {}))
2700
2701 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
2702 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
2703
2238 with self.assertRaisesRegex(TypeError, "parameter is positional only"): 2704 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
2239 self.call(test, 1, 2, c_po=4) 2705 self.call(test, 1, 2, c_po=4)
2240 2706
2241 with self.assertRaisesRegex(TypeError, "parameter is positional only"): 2707 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
2242 self.call(test, a_po=1, b_po=2) 2708 self.call(test, a_po=1, b_po=2)
2709
2710 def test_signature_bind_with_self_arg(self):
2711 # Issue #17071: one of the parameters is named "self
2712 def test(a, self, b):
2713 pass
2714 sig = inspect.signature(test)
2715 ba = sig.bind(1, 2, 3)
2716 self.assertEqual(ba.args, (1, 2, 3))
2717 ba = sig.bind(1, self=2, b=3)
2718 self.assertEqual(ba.args, (1, 2, 3))
2719
2720 def test_signature_bind_vararg_name(self):
2721 def test(a, *args):
2722 return a, args
2723 sig = inspect.signature(test)
2724
2725 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
2726 sig.bind(a=0, args=1)
2727
2728 def test(*args, **kwargs):
2729 return args, kwargs
2730 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
2731
2732 sig = inspect.signature(test)
2733 ba = sig.bind(args=1)
2734 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
2243 2735
2244 2736
2245 class TestBoundArguments(unittest.TestCase): 2737 class TestBoundArguments(unittest.TestCase):
2246 def test_signature_bound_arguments_unhashable(self): 2738 def test_signature_bound_arguments_unhashable(self):
2247 def foo(a): pass 2739 def foo(a): pass
2248 ba = inspect.signature(foo).bind(1) 2740 ba = inspect.signature(foo).bind(1)
2249 2741
2250 with self.assertRaisesRegex(TypeError, 'unhashable type'): 2742 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2251 hash(ba) 2743 hash(ba)
2252 2744
2253 def test_signature_bound_arguments_equality(self): 2745 def test_signature_bound_arguments_equality(self):
2254 def foo(a): pass 2746 def foo(a): pass
2255 ba = inspect.signature(foo).bind(1) 2747 ba = inspect.signature(foo).bind(1)
2256 self.assertEqual(ba, ba) 2748 self.assertEqual(ba, ba)
2257 2749
2258 ba2 = inspect.signature(foo).bind(1) 2750 ba2 = inspect.signature(foo).bind(1)
2259 self.assertEqual(ba, ba2) 2751 self.assertEqual(ba, ba2)
2260 2752
2261 ba3 = inspect.signature(foo).bind(2) 2753 ba3 = inspect.signature(foo).bind(2)
2262 self.assertNotEqual(ba, ba3) 2754 self.assertNotEqual(ba, ba3)
2263 ba3.arguments['a'] = 1 2755 ba3.arguments['a'] = 1
2264 self.assertEqual(ba, ba3) 2756 self.assertEqual(ba, ba3)
2265 2757
2266 def bar(b): pass 2758 def bar(b): pass
2267 ba4 = inspect.signature(bar).bind(1) 2759 ba4 = inspect.signature(bar).bind(1)
2268 self.assertNotEqual(ba, ba4) 2760 self.assertNotEqual(ba, ba4)
2761
2762
2763 class TestSignaturePrivateHelpers(unittest.TestCase):
2764 def test_signature_get_bound_param(self):
2765 getter = inspect._signature_get_bound_param
2766
2767 self.assertEqual(getter('($self)'), 'self')
2768 self.assertEqual(getter('($self, obj)'), 'self')
2769 self.assertEqual(getter('($cls, /, obj)'), 'cls')
2770
2771
2772 class TestUnwrap(unittest.TestCase):
2773
2774 def test_unwrap_one(self):
2775 def func(a, b):
2776 return a + b
2777 wrapper = functools.lru_cache(maxsize=20)(func)
2778 self.assertIs(inspect.unwrap(wrapper), func)
2779
2780 def test_unwrap_several(self):
2781 def func(a, b):
2782 return a + b
2783 wrapper = func
2784 for __ in range(10):
2785 @functools.wraps(wrapper)
2786 def wrapper():
2787 pass
2788 self.assertIsNot(wrapper.__wrapped__, func)
2789 self.assertIs(inspect.unwrap(wrapper), func)
2790
2791 def test_stop(self):
2792 def func1(a, b):
2793 return a + b
2794 @functools.wraps(func1)
2795 def func2():
2796 pass
2797 @functools.wraps(func2)
2798 def wrapper():
2799 pass
2800 func2.stop_here = 1
2801 unwrapped = inspect.unwrap(wrapper,
2802 stop=(lambda f: hasattr(f, "stop_here")))
2803 self.assertIs(unwrapped, func2)
2804
2805 def test_cycle(self):
2806 def func1(): pass
2807 func1.__wrapped__ = func1
2808 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2809 inspect.unwrap(func1)
2810
2811 def func2(): pass
2812 func2.__wrapped__ = func1
2813 func1.__wrapped__ = func2
2814 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2815 inspect.unwrap(func1)
2816 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2817 inspect.unwrap(func2)
2818
2819 def test_unhashable(self):
2820 def func(): pass
2821 func.__wrapped__ = None
2822 class C:
2823 __hash__ = None
2824 __wrapped__ = func
2825 self.assertIsNone(inspect.unwrap(C()))
2826
2827 class TestMain(unittest.TestCase):
2828 def test_only_source(self):
2829 module = importlib.import_module('unittest')
2830 rc, out, err = assert_python_ok('-m', 'inspect',
2831 'unittest')
2832 lines = out.decode().splitlines()
2833 # ignore the final newline
2834 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
2835 self.assertEqual(err, b'')
2836
2837 @unittest.skipIf(ThreadPoolExecutor is None,
2838 'threads required to test __qualname__ for source files')
2839 def test_qualname_source(self):
2840 rc, out, err = assert_python_ok('-m', 'inspect',
2841 'concurrent.futures:ThreadPoolExecutor')
2842 lines = out.decode().splitlines()
2843 # ignore the final newline
2844 self.assertEqual(lines[:-1],
2845 inspect.getsource(ThreadPoolExecutor).splitlines())
2846 self.assertEqual(err, b'')
2847
2848 def test_builtins(self):
2849 module = importlib.import_module('unittest')
2850 _, out, err = assert_python_failure('-m', 'inspect',
2851 'sys')
2852 lines = err.decode().splitlines()
2853 self.assertEqual(lines, ["Can't get info for builtin modules."])
2854
2855 def test_details(self):
2856 module = importlib.import_module('unittest')
2857 rc, out, err = assert_python_ok('-m', 'inspect',
2858 'unittest', '--details')
2859 output = out.decode()
2860 # Just a quick sanity check on the output
2861 self.assertIn(module.__name__, output)
2862 self.assertIn(module.__file__, output)
2863 if not sys.flags.optimize:
2864 self.assertIn(module.__cached__, output)
2865 self.assertEqual(err, b'')
2866
2867
2269 2868
2270 2869
2271 def test_main(): 2870 def test_main():
2272 run_unittest( 2871 run_unittest(
2273 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases, 2872 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
2274 TestInterpreterStack, TestClassesAndFunctions, TestPredicates, 2873 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
2275 TestGetcallargsFunctions, TestGetcallargsMethods, 2874 TestGetcallargsFunctions, TestGetcallargsMethods,
2276 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState, 2875 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
2277 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject, 2876 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
2278 TestBoundArguments, TestGetClosureVars 2877 TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars,
2878 TestUnwrap, TestMain
2279 ) 2879 )
2280 2880
2281 if __name__ == "__main__": 2881 if __name__ == "__main__":
2282 test_main() 2882 test_main()
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+