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

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

Issue 20334: make inspect Signature hashable
Left Patch Set: Created 5 years, 7 months ago
Right Patch Set: Created 4 years, 11 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/inspect.py ('k') | no next file » | 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 builtins
2 import collections
3 import datetime
4 import functools
5 import importlib
6 import inspect
7 import io
8 import linecache
9 import os
10 from os.path import normcase
11 import _pickle
12 import pickle
1 import re 13 import re
14 import shutil
2 import sys 15 import sys
3 import types 16 import types
17 import unicodedata
4 import unittest 18 import unittest
5 import inspect 19 import unittest.mock
6 import linecache 20
7 import datetime
8 import collections
9 import os
10 import shutil
11 import functools
12 import importlib
13 from os.path import normcase
14 try: 21 try:
15 from concurrent.futures import ThreadPoolExecutor 22 from concurrent.futures import ThreadPoolExecutor
16 except ImportError: 23 except ImportError:
17 ThreadPoolExecutor = None 24 ThreadPoolExecutor = None
18 import _testcapi 25
19 26 from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
20 from test.support import run_unittest, TESTFN, DirsOnSysPath 27 from test.support import MISSING_C_DOCSTRINGS, cpython_only
21 from test.support import MISSING_C_DOCSTRINGS
22 from test.script_helper import assert_python_ok, assert_python_failure 28 from test.script_helper import assert_python_ok, assert_python_failure
23 from test import inspect_fodder as mod 29 from test import inspect_fodder as mod
24 from test import inspect_fodder2 as mod2 30 from test import inspect_fodder2 as mod2
25 31
26 # C module for test_findsource_binary
27 import unicodedata
28 32
29 # Functions tested in this suite: 33 # Functions tested in this suite:
30 # ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode, 34 # ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
31 # isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers, 35 # isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
32 # getdoc, getfile, getmodule, getsourcefile, getcomments, getsource, 36 # getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
33 # getclasstree, getargspec, getargvalues, formatargspec, formatargvalues, 37 # getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
34 # currentframe, stack, trace, isdatadescriptor 38 # currentframe, stack, trace, isdatadescriptor
35 39
36 # NOTE: There are some additional tests relating to interaction with 40 # NOTE: There are some additional tests relating to interaction with
37 # zipimport in the test_zipimport_support test module. 41 # zipimport in the test_zipimport_support test module.
(...skipping 25 matching lines...) Expand all
63 67
64 for other in self.predicates - set([predicate]): 68 for other in self.predicates - set([predicate]):
65 if predicate == inspect.isgeneratorfunction and\ 69 if predicate == inspect.isgeneratorfunction and\
66 other == inspect.isfunction: 70 other == inspect.isfunction:
67 continue 71 continue
68 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp)) 72 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
69 73
70 def generator_function_example(self): 74 def generator_function_example(self):
71 for i in range(2): 75 for i in range(2):
72 yield i 76 yield i
77
73 78
74 class TestPredicates(IsTestBase): 79 class TestPredicates(IsTestBase):
75 def test_sixteen(self): 80 def test_sixteen(self):
76 count = len([x for x in dir(inspect) if x.startswith('is')]) 81 count = len([x for x in dir(inspect) if x.startswith('is')])
77 # This test is here for remember you to update Doc/library/inspect.rst 82 # This test is here for remember you to update Doc/library/inspect.rst
78 # which claims there are 16 such functions 83 # which claims there are 16 such functions
79 expected = 16 84 expected = 16
80 err_msg = "There are %d (not %d) is* functions" % (count, expected) 85 err_msg = "There are %d (not %d) is* functions" % (count, expected)
81 self.assertEqual(count, expected, err_msg) 86 self.assertEqual(count, expected, err_msg)
82 87
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 def test_stack(self): 175 def test_stack(self):
171 self.assertTrue(len(mod.st) >= 5) 176 self.assertTrue(len(mod.st) >= 5)
172 self.assertEqual(revise(*mod.st[0][1:]), 177 self.assertEqual(revise(*mod.st[0][1:]),
173 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0)) 178 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
174 self.assertEqual(revise(*mod.st[1][1:]), 179 self.assertEqual(revise(*mod.st[1][1:]),
175 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0)) 180 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
176 self.assertEqual(revise(*mod.st[2][1:]), 181 self.assertEqual(revise(*mod.st[2][1:]),
177 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0)) 182 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
178 self.assertEqual(revise(*mod.st[3][1:]), 183 self.assertEqual(revise(*mod.st[3][1:]),
179 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0)) 184 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
185 # Test named tuple fields
186 record = mod.st[0]
187 self.assertIs(record.frame, mod.fr)
188 self.assertEqual(record.lineno, 16)
189 self.assertEqual(record.filename, mod.__file__)
190 self.assertEqual(record.function, 'eggs')
191 self.assertIn('inspect.stack()', record.code_context[0])
192 self.assertEqual(record.index, 0)
180 193
181 def test_trace(self): 194 def test_trace(self):
182 self.assertEqual(len(git.tr), 3) 195 self.assertEqual(len(git.tr), 3)
183 self.assertEqual(revise(*git.tr[0][1:]), 196 self.assertEqual(revise(*git.tr[0][1:]),
184 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0)) 197 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
185 self.assertEqual(revise(*git.tr[1][1:]), 198 self.assertEqual(revise(*git.tr[1][1:]),
186 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0)) 199 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
187 self.assertEqual(revise(*git.tr[2][1:]), 200 self.assertEqual(revise(*git.tr[2][1:]),
188 (modfile, 18, 'eggs', [' q = y / 0\n'], 0)) 201 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
189 202
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 self.assertEqual(inspect.getsourcefile(co), None) 323 self.assertEqual(inspect.getsourcefile(co), None)
311 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename) 324 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
312 try: 325 try:
313 self.assertEqual(normcase(inspect.getsourcefile(co)), fn) 326 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
314 finally: 327 finally:
315 del linecache.cache[co.co_filename] 328 del linecache.cache[co.co_filename]
316 329
317 def test_getfile(self): 330 def test_getfile(self):
318 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__) 331 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
319 332
333 def test_getfile_class_without_module(self):
334 class CM(type):
335 @property
336 def __module__(cls):
337 raise AttributeError
338 class C(metaclass=CM):
339 pass
340 with self.assertRaises(TypeError):
341 inspect.getfile(C)
342
320 def test_getmodule_recursion(self): 343 def test_getmodule_recursion(self):
321 from types import ModuleType 344 from types import ModuleType
322 name = '__inspect_dummy' 345 name = '__inspect_dummy'
323 m = sys.modules[name] = ModuleType(name) 346 m = sys.modules[name] = ModuleType(name)
324 m.__file__ = "<string>" # hopefully not a real filename... 347 m.__file__ = "<string>" # hopefully not a real filename...
325 m.__loader__ = "dummy" # pretend the filename is understood by a loader 348 m.__loader__ = "dummy" # pretend the filename is understood by a loader
326 exec("def x(): pass", m.__dict__) 349 exec("def x(): pass", m.__dict__)
327 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>') 350 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
328 del sys.modules[name] 351 del sys.modules[name]
329 inspect.getmodule(compile('a=10','','single')) 352 inspect.getmodule(compile('a=10','','single'))
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 kwonlydefaults_e={'arg2':1}, 582 kwonlydefaults_e={'arg2':1},
560 formatted='(*arg1, arg2=1)') 583 formatted='(*arg1, arg2=1)')
561 584
562 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'], 585 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
563 ann_e={'arg1' : list}, 586 ann_e={'arg1' : list},
564 formatted='(arg1: list)') 587 formatted='(arg1: list)')
565 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [], 588 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
566 kwonlyargs_e=['arg'], 589 kwonlyargs_e=['arg'],
567 formatted='(*, arg)') 590 formatted='(*, arg)')
568 591
592 def test_argspec_api_ignores_wrapped(self):
593 # Issue 20684: low level introspection API must ignore __wrapped__
594 @functools.wraps(mod.spam)
595 def ham(x, y):
596 pass
597 # Basic check
598 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
599 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
600 self.assertFullArgSpecEquals(functools.partial(ham),
601 ['x', 'y'], formatted='(x, y)')
602 # Other variants
603 def check_method(f):
604 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
605 formatted='(self, x, y)')
606 class C:
607 @functools.wraps(mod.spam)
608 def ham(self, x, y):
609 pass
610 pham = functools.partialmethod(ham)
611 @functools.wraps(mod.spam)
612 def __call__(self, x, y):
613 pass
614 check_method(C())
615 check_method(C.ham)
616 check_method(C().ham)
617 check_method(C.pham)
618 check_method(C().pham)
619
620 class C_new:
621 @functools.wraps(mod.spam)
622 def __new__(self, x, y):
623 pass
624 check_method(C_new)
625
626 class C_init:
627 @functools.wraps(mod.spam)
628 def __init__(self, x, y):
629 pass
630 check_method(C_init)
631
632 def test_getfullargspec_signature_attr(self):
633 def test():
634 pass
635 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY )
636 test.__signature__ = inspect.Signature(parameters=(spam_param,))
637
638 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
639
640 def test_getfullargspec_signature_annos(self):
641 def test(a:'spam') -> 'ham': pass
642 spec = inspect.getfullargspec(test)
643 self.assertEqual(test.__annotations__, spec.annotations)
644
645 def test(): pass
646 spec = inspect.getfullargspec(test)
647 self.assertEqual(test.__annotations__, spec.annotations)
648
649 @unittest.skipIf(MISSING_C_DOCSTRINGS,
650 "Signature information for builtins requires docstrings")
651 def test_getfullargspec_builtin_methods(self):
652 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
653 args_e=['self', 'obj'], formatted='(self, o bj)')
654
655 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
656 args_e=['self', 'obj'], formatted='(self, o bj)')
657
658 self.assertFullArgSpecEquals(
659 os.stat,
660 args_e=['path'],
661 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
662 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
663 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
664
665 @cpython_only
666 @unittest.skipIf(MISSING_C_DOCSTRINGS,
667 "Signature information for builtins requires docstrings")
668 def test_getfullagrspec_builtin_func(self):
669 import _testcapi
670 builtin = _testcapi.docstring_with_signature_with_defaults
671 spec = inspect.getfullargspec(builtin)
672 self.assertEqual(spec.defaults[0], 'avocado')
673
674 @cpython_only
675 @unittest.skipIf(MISSING_C_DOCSTRINGS,
676 "Signature information for builtins requires docstrings")
677 def test_getfullagrspec_builtin_func_no_signature(self):
678 import _testcapi
679 builtin = _testcapi.docstring_no_signature
680 with self.assertRaises(TypeError):
681 inspect.getfullargspec(builtin)
569 682
570 def test_getargspec_method(self): 683 def test_getargspec_method(self):
571 class A(object): 684 class A(object):
572 def m(self): 685 def m(self):
573 pass 686 pass
574 self.assertArgSpecEquals(A.m, ['self']) 687 self.assertArgSpecEquals(A.m, ['self'])
575 688
576 def test_classify_newstyle(self): 689 def test_classify_newstyle(self):
577 class A(object): 690 class A(object):
578 691
579 def s(): pass 692 def s(): pass
580 s = staticmethod(s) 693 s = staticmethod(s)
581 694
582 def c(cls): pass 695 def c(cls): pass
583 c = classmethod(c) 696 c = classmethod(c)
584 697
585 def getp(self): pass 698 def getp(self): pass
586 p = property(getp) 699 p = property(getp)
587 700
588 def m(self): pass 701 def m(self): pass
589 702
590 def m1(self): pass 703 def m1(self): pass
591 704
592 datablob = '1' 705 datablob = '1'
593 706
594 dd = _BrokenDataDescriptor() 707 dd = _BrokenDataDescriptor()
595 md = _BrokenMethodDescriptor() 708 md = _BrokenMethodDescriptor()
596 709
597 attrs = attrs_wo_objs(A) 710 attrs = attrs_wo_objs(A)
711
712 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
713 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
714
598 self.assertIn(('s', 'static method', A), attrs, 'missing static method') 715 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
599 self.assertIn(('c', 'class method', A), attrs, 'missing class method') 716 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
600 self.assertIn(('p', 'property', A), attrs, 'missing property') 717 self.assertIn(('p', 'property', A), attrs, 'missing property')
601 self.assertIn(('m', 'method', A), attrs, 718 self.assertIn(('m', 'method', A), attrs,
602 'missing plain method: %r' % attrs) 719 'missing plain method: %r' % attrs)
603 self.assertIn(('m1', 'method', A), attrs, 'missing plain method') 720 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
604 self.assertIn(('datablob', 'data', A), attrs, 'missing data') 721 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
605 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor') 722 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
606 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor') 723 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
607 724
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after
1093 # - for unbound methods: multiple values for keyword 'a' 1210 # - for unbound methods: multiple values for keyword 'a'
1094 #self.assertEqualException(f, '1, c=3, a=2') 1211 #self.assertEqualException(f, '1, c=3, a=2')
1095 # issue11256: 1212 # issue11256:
1096 f3 = self.makeCallable('**c') 1213 f3 = self.makeCallable('**c')
1097 self.assertEqualException(f3, '1, 2') 1214 self.assertEqualException(f3, '1, 2')
1098 self.assertEqualException(f3, '1, 2, a=1, b=2') 1215 self.assertEqualException(f3, '1, 2, a=1, b=2')
1099 f4 = self.makeCallable('*, a, b=0') 1216 f4 = self.makeCallable('*, a, b=0')
1100 self.assertEqualException(f3, '1, 2') 1217 self.assertEqualException(f3, '1, 2')
1101 self.assertEqualException(f3, '1, 2, a=1, b=2') 1218 self.assertEqualException(f3, '1, 2, a=1, b=2')
1102 1219
1220 # issue #20816: getcallargs() fails to iterate over non-existent
1221 # kwonlydefaults and raises a wrong TypeError
1222 def f5(*, a): pass
1223 with self.assertRaisesRegex(TypeError,
1224 'missing 1 required keyword-only'):
1225 inspect.getcallargs(f5)
1226
1227
1228 # issue20817:
1229 def f6(a, b, c):
1230 pass
1231 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1232 inspect.getcallargs(f6)
1233
1103 class TestGetcallargsMethods(TestGetcallargsFunctions): 1234 class TestGetcallargsMethods(TestGetcallargsFunctions):
1104 1235
1105 def setUp(self): 1236 def setUp(self):
1106 class Foo(object): 1237 class Foo(object):
1107 pass 1238 pass
1108 self.cls = Foo 1239 self.cls = Foo
1109 self.inst = Foo() 1240 self.inst = Foo()
1110 1241
1111 def makeCallable(self, signature): 1242 def makeCallable(self, signature):
1112 assert 'self' not in signature 1243 assert 'self' not in signature
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
1484 pass 1615 pass
1485 self.assertEqual(inspect.getgeneratorlocals(one), {}) 1616 self.assertEqual(inspect.getgeneratorlocals(one), {})
1486 1617
1487 def test_getgeneratorlocals_error(self): 1618 def test_getgeneratorlocals_error(self):
1488 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1) 1619 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1489 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True) 1620 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1490 self.assertRaises(TypeError, inspect.getgeneratorlocals, set) 1621 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1491 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3)) 1622 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1492 1623
1493 1624
1625 class MySignature(inspect.Signature):
1626 # Top-level to make it picklable;
1627 # used in test_signature_object_pickle
1628 pass
1629
1630 class MyParameter(inspect.Parameter):
1631 # Top-level to make it picklable;
1632 # used in test_signature_object_pickle
1633 pass
1634
1635 @cpython_only
1636 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1637 "Signature information for builtins requires docstrings")
1638 def test_builtins_have_signatures(self):
1639 # This checks all builtin callables in CPython have signatures
1640 # A few have signatures Signature can't yet handle, so we skip those
1641 # since they will have to wait until PEP 457 adds the required
1642 # introspection support to the inspect module
1643 # Some others also haven't been converted yet for various other
1644 # reasons, so we also skip those for the time being, but design
1645 # the test to fail in order to indicate when it needs to be
1646 # updated.
1647 no_signature = set()
1648 # These need PEP 457 groups
1649 needs_groups = ["range", "slice", "dir", "getattr",
1650 "next", "iter", "vars"]
1651 no_signature |= needs_groups
1652 # These need PEP 457 groups or a signature change to accept None
1653 needs_semantic_update = ["round"]
1654 no_signature |= needs_semantic_update
1655 # These need *args support in Argument Clinic
1656 needs_varargs = ["min", "max", "print", "__build_class__"]
1657 no_signature |= needs_varargs
1658 # These simply weren't covered in the initial AC conversion
1659 # for builtin callables
1660 not_converted_yet = ["open", "__import__"]
1661 no_signature |= not_converted_yet
1662 # These builtin types are expected to provide introspection info
1663 types_with_signatures = set()
1664 # Check the signatures we expect to be there
1665 ns = vars(builtins)
1666 for name, obj in sorted(ns.items()):
1667 if not callable(obj):
1668 continue
1669 # The builtin types haven't been converted to AC yet
1670 if isinstance(obj, type) and (name not in types_with_signatures):
1671 # Note that this also skips all the exception types
1672 no_signature.append(name)
1673 if (name in no_signature):
1674 # Not yet converted
1675 continue
1676 with self.subTest(builtin=name):
1677 self.assertIsNotNone(inspect.signature(obj))
1678 # Check callables that haven't been converted don't claim a signature
1679 # This ensures this test will start failing as more signatures are
1680 # added, so the affected items can be moved into the scope of the
1681 # regression test above
1682 for name in no_signature:
1683 with self.subTest(builtin=name):
1684 self.assertIsNone(ns[name].__text_signature__)
1685
1686
1494 class TestSignatureObject(unittest.TestCase): 1687 class TestSignatureObject(unittest.TestCase):
1495 @staticmethod 1688 @staticmethod
1496 def signature(func): 1689 def signature(func):
1497 sig = inspect.signature(func) 1690 sig = inspect.signature(func)
1498 return (tuple((param.name, 1691 return (tuple((param.name,
1499 (... if param.default is param.empty else param.default), 1692 (... if param.default is param.empty else param.default),
1500 (... if param.annotation is param.empty 1693 (... if param.annotation is param.empty
1501 else param.annotation), 1694 else param.annotation),
1502 str(param.kind).lower()) 1695 str(param.kind).lower())
1503 for param in sig.parameters.values()), 1696 for param in sig.parameters.values()),
1504 (... if sig.return_annotation is sig.empty 1697 (... if sig.return_annotation is sig.empty
1505 else sig.return_annotation)) 1698 else sig.return_annotation))
1506 1699
1507 def test_signature_object(self): 1700 def test_signature_object(self):
1508 S = inspect.Signature 1701 S = inspect.Signature
1509 P = inspect.Parameter 1702 P = inspect.Parameter
1510 1703
1511 self.assertEqual(str(S()), '()') 1704 self.assertEqual(str(S()), '()')
1512 1705
1513 def test(po, pk, *args, ko, **kwargs): 1706 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
1514 pass 1707 pass
1515 sig = inspect.signature(test) 1708 sig = inspect.signature(test)
1516 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY) 1709 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
1710 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
1517 pk = sig.parameters['pk'] 1711 pk = sig.parameters['pk']
1712 pkd = sig.parameters['pkd']
1518 args = sig.parameters['args'] 1713 args = sig.parameters['args']
1519 ko = sig.parameters['ko'] 1714 ko = sig.parameters['ko']
1520 kwargs = sig.parameters['kwargs'] 1715 kwargs = sig.parameters['kwargs']
1521 1716
1522 S((po, pk, args, ko, kwargs)) 1717 S((po, pk, args, ko, kwargs))
1523 1718
1524 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 1719 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
1525 S((pk, po, args, ko, kwargs)) 1720 S((pk, po, args, ko, kwargs))
1526 1721
1527 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 1722 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
1528 S((po, args, pk, ko, kwargs)) 1723 S((po, args, pk, ko, kwargs))
1529 1724
1530 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 1725 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
1531 S((args, po, pk, ko, kwargs)) 1726 S((args, po, pk, ko, kwargs))
1532 1727
1533 with self.assertRaisesRegex(ValueError, 'wrong parameter order'): 1728 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
1534 S((po, pk, args, kwargs, ko)) 1729 S((po, pk, args, kwargs, ko))
1535 1730
1536 kwargs2 = kwargs.replace(name='args') 1731 kwargs2 = kwargs.replace(name='args')
1537 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'): 1732 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
1538 S((po, pk, args, kwargs2, ko)) 1733 S((po, pk, args, kwargs2, ko))
1734
1735 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1736 S((pod, po))
1737
1738 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1739 S((po, pkd, pk))
1740
1741 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1742 S((pkd, pk))
1743
1744 self.assertTrue(repr(sig).startswith('<Signature'))
1745 self.assertTrue('"(po, pk' in repr(sig))
1746
1747 def test_signature_object_pickle(self):
1748 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1749 foo_partial = functools.partial(foo, a=1)
1750
1751 sig = inspect.signature(foo_partial)
1752
1753 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1754 with self.subTest(pickle_ver=ver, subclass=False):
1755 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1756 self.assertEqual(sig, sig_pickled)
1757
1758 # Test that basic sub-classing works
1759 sig = inspect.signature(foo)
1760 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1761 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1762 mysig = MySignature().replace(parameters=myparams.values(),
1763 return_annotation=sig.return_annotation)
1764 self.assertTrue(isinstance(mysig, MySignature))
1765 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1766
1767 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1768 with self.subTest(pickle_ver=ver, subclass=True):
1769 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1770 self.assertEqual(mysig, sig_pickled)
1771 self.assertTrue(isinstance(sig_pickled, MySignature))
1772 self.assertTrue(isinstance(sig_pickled.parameters['z'],
1773 MyParameter))
1539 1774
1540 def test_signature_immutability(self): 1775 def test_signature_immutability(self):
1541 def test(a): 1776 def test(a):
1542 pass 1777 pass
1543 sig = inspect.signature(test) 1778 sig = inspect.signature(test)
1544 1779
1545 with self.assertRaises(AttributeError): 1780 with self.assertRaises(AttributeError):
1546 sig.foo = 'bar' 1781 sig.foo = 'bar'
1547 1782
1548 with self.assertRaises(TypeError): 1783 with self.assertRaises(TypeError):
(...skipping 25 matching lines...) Expand all
1574 pass 1809 pass
1575 self.assertEqual(self.signature(test), 1810 self.assertEqual(self.signature(test),
1576 ((('a', ..., ..., "positional_or_keyword"), 1811 ((('a', ..., ..., "positional_or_keyword"),
1577 ('b', 10, 'foo', "positional_or_keyword"), 1812 ('b', 10, 'foo', "positional_or_keyword"),
1578 ('args', ..., 'bar', "var_positional"), 1813 ('args', ..., 'bar', "var_positional"),
1579 ('spam', ..., 'baz', "keyword_only"), 1814 ('spam', ..., 'baz', "keyword_only"),
1580 ('ham', 123, ..., "keyword_only"), 1815 ('ham', 123, ..., "keyword_only"),
1581 ('kwargs', ..., int, "var_keyword")), 1816 ('kwargs', ..., int, "var_keyword")),
1582 ...)) 1817 ...))
1583 1818
1584 def test_signature_on_unsupported_builtins(self): 1819 @cpython_only
1585 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
1586 inspect.signature(type)
1587 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
1588 # support for 'wrapper_descriptor'
1589 inspect.signature(type.__call__)
1590 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
1591 # support for 'method-wrapper'
1592 inspect.signature(min.__call__)
1593
1594 @unittest.skipIf(MISSING_C_DOCSTRINGS, 1820 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1595 "Signature information for builtins requires docstrings") 1821 "Signature information for builtins requires docstrings")
1596 def test_signature_on_builtins(self): 1822 def test_signature_on_builtins(self):
1597 # min doesn't have a signature (yet) 1823 import _testcapi
1598 self.assertEqual(inspect.signature(min), None) 1824
1599 1825 def test_unbound_method(o):
1600 signature = inspect.signature(_testcapi.docstring_with_signature_with_de faults) 1826 """Use this to test unbound methods (things that should have a self) """
1601 self.assertTrue(isinstance(signature, inspect.Signature)) 1827 signature = inspect.signature(o)
1828 self.assertTrue(isinstance(signature, inspect.Signature))
1829 self.assertEqual(list(signature.parameters.values())[0].name, 'self' )
1830 return signature
1831
1832 def test_callable(o):
1833 """Use this to test bound methods or normal callables (things that d on't expect self)"""
1834 signature = inspect.signature(o)
1835 self.assertTrue(isinstance(signature, inspect.Signature))
1836 if signature.parameters:
1837 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1838 return signature
1839
1840 signature = test_callable(_testcapi.docstring_with_signature_with_defaul ts)
1602 def p(name): return signature.parameters[name].default 1841 def p(name): return signature.parameters[name].default
1603 self.assertEqual(p('s'), 'avocado') 1842 self.assertEqual(p('s'), 'avocado')
1604 self.assertEqual(p('b'), b'bytes') 1843 self.assertEqual(p('b'), b'bytes')
1605 self.assertEqual(p('d'), 3.14) 1844 self.assertEqual(p('d'), 3.14)
1606 self.assertEqual(p('i'), 35) 1845 self.assertEqual(p('i'), 35)
1607 self.assertEqual(p('n'), None) 1846 self.assertEqual(p('n'), None)
1608 self.assertEqual(p('t'), True) 1847 self.assertEqual(p('t'), True)
1609 self.assertEqual(p('f'), False) 1848 self.assertEqual(p('f'), False)
1610 self.assertEqual(p('local'), 3) 1849 self.assertEqual(p('local'), 3)
1611 self.assertEqual(p('sys'), sys.maxsize) 1850 self.assertEqual(p('sys'), sys.maxsize)
1612 self.assertEqual(p('exp'), sys.maxsize - 1) 1851 self.assertEqual(p('exp'), sys.maxsize - 1)
1613 1852
1853 test_callable(object)
1854
1855 # normal method
1856 # (PyMethodDescr_Type, "method_descriptor")
1857 test_unbound_method(_pickle.Pickler.dump)
1858 d = _pickle.Pickler(io.StringIO())
1859 test_callable(d.dump)
1860
1861 # static method
1862 test_callable(str.maketrans)
1863 test_callable('abc'.maketrans)
1864
1865 # class method
1866 test_callable(dict.fromkeys)
1867 test_callable({}.fromkeys)
1868
1869 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1870 test_unbound_method(type.__call__)
1871 test_unbound_method(int.__add__)
1872 test_callable((3).__add__)
1873
1874 # _PyMethodWrapper_Type
1875 # support for 'method-wrapper'
1876 test_callable(min.__call__)
1877
1878 # This doesn't work now.
1879 # (We don't have a valid signature for "type" in 3.4)
1880 with self.assertRaisesRegex(ValueError, "no signature found"):
1881 class ThisWorksNow:
1882 __call__ = type
1883 test_callable(ThisWorksNow())
1884
1885 # Regression test for issue #20786
1886 test_unbound_method(dict.__delitem__)
1887 test_unbound_method(property.__delete__)
1888
1889
1890 @cpython_only
1891 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1892 "Signature information for builtins requires docstrings")
1893 def test_signature_on_decorated_builtins(self):
1894 import _testcapi
1895 func = _testcapi.docstring_with_signature_with_defaults
1896
1897 def decorator(func):
1898 @functools.wraps(func)
1899 def wrapper(*args, **kwargs) -> int:
1900 return func(*args, **kwargs)
1901 return wrapper
1902
1903 decorated_func = decorator(func)
1904
1905 self.assertEqual(inspect.signature(func),
1906 inspect.signature(decorated_func))
1907
1908 @cpython_only
1909 def test_signature_on_builtins_no_signature(self):
1910 import _testcapi
1911 with self.assertRaisesRegex(ValueError, 'no signature found for builtin' ):
1912 inspect.signature(_testcapi.docstring_no_signature)
1913
1614 def test_signature_on_non_function(self): 1914 def test_signature_on_non_function(self):
1615 with self.assertRaisesRegex(TypeError, 'is not a callable object'): 1915 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
1616 inspect.signature(42) 1916 inspect.signature(42)
1617 1917
1618 with self.assertRaisesRegex(TypeError, 'is not a Python function'): 1918 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1619 inspect.Signature.from_function(42) 1919 inspect.Signature.from_function(42)
1620 1920
1921 def test_signature_from_builtin_errors(self):
1922 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1923 inspect.Signature.from_builtin(42)
1924
1925 def test_signature_from_functionlike_object(self):
1926 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1927 pass
1928
1929 class funclike:
1930 # Has to be callable, and have correct
1931 # __code__, __annotations__, __defaults__, __name__,
1932 # and __kwdefaults__ attributes
1933
1934 def __init__(self, func):
1935 self.__name__ = func.__name__
1936 self.__code__ = func.__code__
1937 self.__annotations__ = func.__annotations__
1938 self.__defaults__ = func.__defaults__
1939 self.__kwdefaults__ = func.__kwdefaults__
1940 self.func = func
1941
1942 def __call__(self, *args, **kwargs):
1943 return self.func(*args, **kwargs)
1944
1945 sig_func = inspect.Signature.from_function(func)
1946
1947 sig_funclike = inspect.Signature.from_function(funclike(func))
1948 self.assertEqual(sig_funclike, sig_func)
1949
1950 sig_funclike = inspect.signature(funclike(func))
1951 self.assertEqual(sig_funclike, sig_func)
1952
1953 # If object is not a duck type of function, then
1954 # signature will try to get a signature for its '__call__'
1955 # method
1956 fl = funclike(func)
1957 del fl.__defaults__
1958 self.assertEqual(self.signature(fl),
1959 ((('args', ..., ..., "var_positional"),
1960 ('kwargs', ..., ..., "var_keyword")),
1961 ...))
1962
1963 # Test with cython-like builtins:
1964 _orig_isdesc = inspect.ismethoddescriptor
1965 def _isdesc(obj):
1966 if hasattr(obj, '_builtinmock'):
1967 return True
1968 return _orig_isdesc(obj)
1969
1970 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
1971 builtin_func = funclike(func)
1972 # Make sure that our mock setup is working
1973 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
1974 builtin_func._builtinmock = True
1975 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
1976 self.assertEqual(inspect.signature(builtin_func), sig_func)
1977
1978 def test_signature_functionlike_class(self):
1979 # We only want to duck type function-like objects,
1980 # not classes.
1981
1982 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1983 pass
1984
1985 class funclike:
1986 def __init__(self, marker):
1987 pass
1988
1989 __name__ = func.__name__
1990 __code__ = func.__code__
1991 __annotations__ = func.__annotations__
1992 __defaults__ = func.__defaults__
1993 __kwdefaults__ = func.__kwdefaults__
1994
1995 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1996 inspect.Signature.from_function(funclike)
1997
1998 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1999
1621 def test_signature_on_method(self): 2000 def test_signature_on_method(self):
1622 class Test: 2001 class Test:
1623 def foo(self, arg1, arg2=1) -> int: 2002 def __init__(*args):
1624 pass 2003 pass
1625 2004 def m1(self, arg1, arg2=1) -> int:
1626 meth = Test().foo 2005 pass
1627 2006 def m2(*args):
1628 self.assertEqual(self.signature(meth), 2007 pass
2008 def __call__(*, a):
2009 pass
2010
2011 self.assertEqual(self.signature(Test().m1),
1629 ((('arg1', ..., ..., "positional_or_keyword"), 2012 ((('arg1', ..., ..., "positional_or_keyword"),
1630 ('arg2', 1, ..., "positional_or_keyword")), 2013 ('arg2', 1, ..., "positional_or_keyword")),
1631 int)) 2014 int))
2015
2016 self.assertEqual(self.signature(Test().m2),
2017 ((('args', ..., ..., "var_positional"),),
2018 ...))
2019
2020 self.assertEqual(self.signature(Test),
2021 ((('args', ..., ..., "var_positional"),),
2022 ...))
2023
2024 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2025 self.signature(Test())
1632 2026
1633 def test_signature_on_classmethod(self): 2027 def test_signature_on_classmethod(self):
1634 class Test: 2028 class Test:
1635 @classmethod 2029 @classmethod
1636 def foo(cls, arg1, *, arg2=1): 2030 def foo(cls, arg1, *, arg2=1):
1637 pass 2031 pass
1638 2032
1639 meth = Test().foo 2033 meth = Test().foo
1640 self.assertEqual(self.signature(meth), 2034 self.assertEqual(self.signature(meth),
1641 ((('arg1', ..., ..., "positional_or_keyword"), 2035 ((('arg1', ..., ..., "positional_or_keyword"),
(...skipping 20 matching lines...) Expand all
1662 2056
1663 meth = Test.foo 2057 meth = Test.foo
1664 self.assertEqual(self.signature(meth), 2058 self.assertEqual(self.signature(meth),
1665 ((('cls', ..., ..., "positional_or_keyword"), 2059 ((('cls', ..., ..., "positional_or_keyword"),
1666 ('arg', ..., ..., "keyword_only")), 2060 ('arg', ..., ..., "keyword_only")),
1667 ...)) 2061 ...))
1668 2062
1669 def test_signature_on_partial(self): 2063 def test_signature_on_partial(self):
1670 from functools import partial 2064 from functools import partial
1671 2065
2066 Parameter = inspect.Parameter
2067
1672 def test(): 2068 def test():
1673 pass 2069 pass
1674 2070
1675 self.assertEqual(self.signature(partial(test)), ((), ...)) 2071 self.assertEqual(self.signature(partial(test)), ((), ...))
1676 2072
1677 with self.assertRaisesRegex(ValueError, "has incorrect arguments"): 2073 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
1678 inspect.signature(partial(test, 1)) 2074 inspect.signature(partial(test, 1))
1679 2075
1680 with self.assertRaisesRegex(ValueError, "has incorrect arguments"): 2076 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
1681 inspect.signature(partial(test, a=1)) 2077 inspect.signature(partial(test, a=1))
(...skipping 15 matching lines...) Expand all
1697 ...)) 2093 ...))
1698 2094
1699 self.assertEqual(self.signature(partial(test, 1, c=2)), 2095 self.assertEqual(self.signature(partial(test, 1, c=2)),
1700 ((('b', ..., ..., "positional_or_keyword"), 2096 ((('b', ..., ..., "positional_or_keyword"),
1701 ('c', 2, ..., "keyword_only"), 2097 ('c', 2, ..., "keyword_only"),
1702 ('d', ..., ..., "keyword_only")), 2098 ('d', ..., ..., "keyword_only")),
1703 ...)) 2099 ...))
1704 2100
1705 self.assertEqual(self.signature(partial(test, b=1, c=2)), 2101 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1706 ((('a', ..., ..., "positional_or_keyword"), 2102 ((('a', ..., ..., "positional_or_keyword"),
1707 ('b', 1, ..., "positional_or_keyword"), 2103 ('b', 1, ..., "keyword_only"),
1708 ('c', 2, ..., "keyword_only"), 2104 ('c', 2, ..., "keyword_only"),
1709 ('d', ..., ..., "keyword_only")), 2105 ('d', ..., ..., "keyword_only")),
1710 ...)) 2106 ...))
1711 2107
1712 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)), 2108 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
1713 ((('b', 1, ..., "positional_or_keyword"), 2109 ((('b', 1, ..., "keyword_only"),
1714 ('c', 2, ..., "keyword_only"), 2110 ('c', 2, ..., "keyword_only"),
1715 ('d', ..., ..., "keyword_only"),), 2111 ('d', ..., ..., "keyword_only")),
2112 ...))
2113
2114 self.assertEqual(self.signature(partial(test, a=1)),
2115 ((('a', 1, ..., "keyword_only"),
2116 ('b', ..., ..., "keyword_only"),
2117 ('c', ..., ..., "keyword_only"),
2118 ('d', ..., ..., "keyword_only")),
1716 ...)) 2119 ...))
1717 2120
1718 def test(a, *args, b, **kwargs): 2121 def test(a, *args, b, **kwargs):
1719 pass 2122 pass
1720 2123
1721 self.assertEqual(self.signature(partial(test, 1)), 2124 self.assertEqual(self.signature(partial(test, 1)),
1722 ((('args', ..., ..., "var_positional"), 2125 ((('args', ..., ..., "var_positional"),
1723 ('b', ..., ..., "keyword_only"), 2126 ('b', ..., ..., "keyword_only"),
1724 ('kwargs', ..., ..., "var_keyword")), 2127 ('kwargs', ..., ..., "var_keyword")),
1725 ...)) 2128 ...))
1726 2129
2130 self.assertEqual(self.signature(partial(test, a=1)),
2131 ((('a', 1, ..., "keyword_only"),
2132 ('b', ..., ..., "keyword_only"),
2133 ('kwargs', ..., ..., "var_keyword")),
2134 ...))
2135
1727 self.assertEqual(self.signature(partial(test, 1, 2, 3)), 2136 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
1728 ((('args', ..., ..., "var_positional"), 2137 ((('args', ..., ..., "var_positional"),
1729 ('b', ..., ..., "keyword_only"), 2138 ('b', ..., ..., "keyword_only"),
1730 ('kwargs', ..., ..., "var_keyword")), 2139 ('kwargs', ..., ..., "var_keyword")),
1731 ...)) 2140 ...))
1732
1733 2141
1734 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)), 2142 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
1735 ((('args', ..., ..., "var_positional"), 2143 ((('args', ..., ..., "var_positional"),
1736 ('b', ..., ..., "keyword_only"), 2144 ('b', ..., ..., "keyword_only"),
1737 ('kwargs', ..., ..., "var_keyword")), 2145 ('kwargs', ..., ..., "var_keyword")),
1738 ...)) 2146 ...))
1739 2147
1740 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)), 2148 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
1741 ((('args', ..., ..., "var_positional"), 2149 ((('args', ..., ..., "var_positional"),
1742 ('b', 0, ..., "keyword_only"), 2150 ('b', 0, ..., "keyword_only"),
(...skipping 27 matching lines...) Expand all
1770 self.assertEqual(self.signature(partial(partial(test, 1), 2)), 2178 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
1771 ((('c', ..., int, "positional_or_keyword"),), 2179 ((('c', ..., int, "positional_or_keyword"),),
1772 42)) 2180 42))
1773 2181
1774 psig = inspect.signature(partial(partial(test, 1), 2)) 2182 psig = inspect.signature(partial(partial(test, 1), 2))
1775 2183
1776 def foo(a): 2184 def foo(a):
1777 return a 2185 return a
1778 _foo = partial(partial(foo, a=10), a=20) 2186 _foo = partial(partial(foo, a=10), a=20)
1779 self.assertEqual(self.signature(_foo), 2187 self.assertEqual(self.signature(_foo),
1780 ((('a', 20, ..., "positional_or_keyword"),), 2188 ((('a', 20, ..., "keyword_only"),),
1781 ...)) 2189 ...))
1782 # check that we don't have any side-effects in signature(), 2190 # check that we don't have any side-effects in signature(),
1783 # and the partial object is still functioning 2191 # and the partial object is still functioning
1784 self.assertEqual(_foo(), 20) 2192 self.assertEqual(_foo(), 20)
1785 2193
1786 def foo(a, b, c): 2194 def foo(a, b, c):
1787 return a, b, c 2195 return a, b, c
1788 _foo = partial(partial(foo, 1, b=20), b=30) 2196 _foo = partial(partial(foo, 1, b=20), b=30)
2197
1789 self.assertEqual(self.signature(_foo), 2198 self.assertEqual(self.signature(_foo),
1790 ((('b', 30, ..., "positional_or_keyword"), 2199 ((('b', 30, ..., "keyword_only"),
1791 ('c', ..., ..., "positional_or_keyword")), 2200 ('c', ..., ..., "keyword_only")),
1792 ...)) 2201 ...))
1793 self.assertEqual(_foo(c=10), (1, 30, 10)) 2202 self.assertEqual(_foo(c=10), (1, 30, 10))
1794 _foo = partial(_foo, 2) # now 'b' has two values -
1795 # positional and keyword
1796 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
1797 inspect.signature(_foo)
1798 2203
1799 def foo(a, b, c, *, d): 2204 def foo(a, b, c, *, d):
1800 return a, b, c, d 2205 return a, b, c, d
1801 _foo = partial(partial(foo, d=20, c=20), b=10, d=30) 2206 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
1802 self.assertEqual(self.signature(_foo), 2207 self.assertEqual(self.signature(_foo),
1803 ((('a', ..., ..., "positional_or_keyword"), 2208 ((('a', ..., ..., "positional_or_keyword"),
1804 ('b', 10, ..., "positional_or_keyword"), 2209 ('b', 10, ..., "keyword_only"),
1805 ('c', 20, ..., "positional_or_keyword"), 2210 ('c', 20, ..., "keyword_only"),
1806 ('d', 30, ..., "keyword_only")), 2211 ('d', 30, ..., "keyword_only"),
2212 ),
1807 ...)) 2213 ...))
1808 ba = inspect.signature(_foo).bind(a=200, b=11) 2214 ba = inspect.signature(_foo).bind(a=200, b=11)
1809 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30)) 2215 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
1810 2216
1811 def foo(a=1, b=2, c=3): 2217 def foo(a=1, b=2, c=3):
1812 return a, b, c 2218 return a, b, c
1813 _foo = partial(foo, a=10, c=13) 2219 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
1814 ba = inspect.signature(_foo).bind(11) 2220
2221 ba = inspect.signature(_foo).bind(a=11)
1815 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13)) 2222 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
2223
1816 ba = inspect.signature(_foo).bind(11, 12) 2224 ba = inspect.signature(_foo).bind(11, 12)
1817 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13)) 2225 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2226
1818 ba = inspect.signature(_foo).bind(11, b=12) 2227 ba = inspect.signature(_foo).bind(11, b=12)
1819 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13)) 2228 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
2229
1820 ba = inspect.signature(_foo).bind(b=12) 2230 ba = inspect.signature(_foo).bind(b=12)
1821 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13)) 2231 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
1822 _foo = partial(_foo, b=10) 2232
1823 ba = inspect.signature(_foo).bind(12, 14) 2233 _foo = partial(_foo, b=10, c=20)
1824 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13)) 2234 ba = inspect.signature(_foo).bind(12)
2235 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2236
2237
2238 def foo(a, b, c, d, **kwargs):
2239 pass
2240 sig = inspect.signature(foo)
2241 params = sig.parameters.copy()
2242 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2243 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2244 foo.__signature__ = inspect.Signature(params.values())
2245 sig = inspect.signature(foo)
2246 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2247
2248 self.assertEqual(self.signature(partial(foo, 1)),
2249 ((('b', ..., ..., 'positional_only'),
2250 ('c', ..., ..., 'positional_or_keyword'),
2251 ('d', ..., ..., 'positional_or_keyword'),
2252 ('kwargs', ..., ..., 'var_keyword')),
2253 ...))
2254
2255 self.assertEqual(self.signature(partial(foo, 1, 2)),
2256 ((('c', ..., ..., 'positional_or_keyword'),
2257 ('d', ..., ..., 'positional_or_keyword'),
2258 ('kwargs', ..., ..., 'var_keyword')),
2259 ...))
2260
2261 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2262 ((('d', ..., ..., 'positional_or_keyword'),
2263 ('kwargs', ..., ..., 'var_keyword')),
2264 ...))
2265
2266 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2267 ((('c', 3, ..., 'keyword_only'),
2268 ('d', ..., ..., 'keyword_only'),
2269 ('kwargs', ..., ..., 'var_keyword')),
2270 ...))
2271
2272 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2273 ((('b', ..., ..., 'positional_only'),
2274 ('c', 3, ..., 'keyword_only'),
2275 ('d', ..., ..., 'keyword_only'),
2276 ('kwargs', ..., ..., 'var_keyword')),
2277 ...))
2278
2279 def test_signature_on_partialmethod(self):
2280 from functools import partialmethod
2281
2282 class Spam:
2283 def test():
2284 pass
2285 ham = partialmethod(test)
2286
2287 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2288 inspect.signature(Spam.ham)
2289
2290 class Spam:
2291 def test(it, a, *, c) -> 'spam':
2292 pass
2293 ham = partialmethod(test, c=1)
2294
2295 self.assertEqual(self.signature(Spam.ham),
2296 ((('it', ..., ..., 'positional_or_keyword'),
2297 ('a', ..., ..., 'positional_or_keyword'),
2298 ('c', 1, ..., 'keyword_only')),
2299 'spam'))
2300
2301 self.assertEqual(self.signature(Spam().ham),
2302 ((('a', ..., ..., 'positional_or_keyword'),
2303 ('c', 1, ..., 'keyword_only')),
2304 'spam'))
2305
2306 def test_signature_on_fake_partialmethod(self):
2307 def foo(a): pass
2308 foo._partialmethod = 'spam'
2309 self.assertEqual(str(inspect.signature(foo)), '(a)')
1825 2310
1826 def test_signature_on_decorated(self): 2311 def test_signature_on_decorated(self):
1827 import functools 2312 import functools
1828 2313
1829 def decorator(func): 2314 def decorator(func):
1830 @functools.wraps(func) 2315 @functools.wraps(func)
1831 def wrapper(*args, **kwargs) -> int: 2316 def wrapper(*args, **kwargs) -> int:
1832 return func(*args, **kwargs) 2317 return func(*args, **kwargs)
1833 return wrapper 2318 return wrapper
1834 2319
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1957 def __init__(self, b): 2442 def __init__(self, b):
1958 pass 2443 pass
1959 2444
1960 self.assertEqual(self.signature(CM), 2445 self.assertEqual(self.signature(CM),
1961 ((('name', ..., ..., "positional_or_keyword"), 2446 ((('name', ..., ..., "positional_or_keyword"),
1962 ('bases', ..., ..., "positional_or_keyword"), 2447 ('bases', ..., ..., "positional_or_keyword"),
1963 ('dct', ..., ..., "positional_or_keyword"), 2448 ('dct', ..., ..., "positional_or_keyword"),
1964 ('bar', 2, ..., "keyword_only")), 2449 ('bar', 2, ..., "keyword_only")),
1965 ...)) 2450 ...))
1966 2451
2452 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2453 "Signature information for builtins requires docstrings")
2454 def test_signature_on_class_without_init(self):
2455 # Test classes without user-defined __init__ or __new__
2456 class C: pass
2457 self.assertEqual(str(inspect.signature(C)), '()')
2458 class D(C): pass
2459 self.assertEqual(str(inspect.signature(D)), '()')
2460
2461 # Test meta-classes without user-defined __init__ or __new__
2462 class C(type): pass
2463 class D(C): pass
2464 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2465 self.assertEqual(inspect.signature(C), None)
2466 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2467 self.assertEqual(inspect.signature(D), None)
2468
2469 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2470 "Signature information for builtins requires docstrings")
2471 def test_signature_on_builtin_class(self):
2472 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2473 '(file, protocol=None, fix_imports=True)')
2474
2475 class P(_pickle.Pickler): pass
2476 class EmptyTrait: pass
2477 class P2(EmptyTrait, P): pass
2478 self.assertEqual(str(inspect.signature(P)),
2479 '(file, protocol=None, fix_imports=True)')
2480 self.assertEqual(str(inspect.signature(P2)),
2481 '(file, protocol=None, fix_imports=True)')
2482
2483 class P3(P2):
2484 def __init__(self, spam):
2485 pass
2486 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2487
2488 class MetaP(type):
2489 def __call__(cls, foo, bar):
2490 pass
2491 class P4(P2, metaclass=MetaP):
2492 pass
2493 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2494
1967 def test_signature_on_callable_objects(self): 2495 def test_signature_on_callable_objects(self):
1968 class Foo: 2496 class Foo:
1969 def __call__(self, a): 2497 def __call__(self, a):
1970 pass 2498 pass
1971 2499
1972 self.assertEqual(self.signature(Foo()), 2500 self.assertEqual(self.signature(Foo()),
1973 ((('a', ..., ..., "positional_or_keyword"),), 2501 ((('a', ..., ..., "positional_or_keyword"),),
1974 ...)) 2502 ...))
1975 2503
1976 class Spam: 2504 class Spam:
1977 pass 2505 pass
1978 with self.assertRaisesRegex(TypeError, "is not a callable object"): 2506 with self.assertRaisesRegex(TypeError, "is not a callable object"):
1979 inspect.signature(Spam()) 2507 inspect.signature(Spam())
1980 2508
1981 class Bar(Spam, Foo): 2509 class Bar(Spam, Foo):
1982 pass 2510 pass
1983 2511
1984 self.assertEqual(self.signature(Bar()), 2512 self.assertEqual(self.signature(Bar()),
1985 ((('a', ..., ..., "positional_or_keyword"),), 2513 ((('a', ..., ..., "positional_or_keyword"),),
1986 ...)) 2514 ...))
1987 2515
1988 class ToFail:
1989 __call__ = type
1990 with self.assertRaisesRegex(ValueError, "not supported by signature"):
1991 inspect.signature(ToFail())
1992
1993
1994 class Wrapped: 2516 class Wrapped:
1995 pass 2517 pass
1996 Wrapped.__wrapped__ = lambda a: None 2518 Wrapped.__wrapped__ = lambda a: None
1997 self.assertEqual(self.signature(Wrapped), 2519 self.assertEqual(self.signature(Wrapped),
1998 ((('a', ..., ..., "positional_or_keyword"),), 2520 ((('a', ..., ..., "positional_or_keyword"),),
1999 ...)) 2521 ...))
2000 # wrapper loop: 2522 # wrapper loop:
2001 Wrapped.__wrapped__ = Wrapped 2523 Wrapped.__wrapped__ = Wrapped
2002 with self.assertRaisesRegex(ValueError, 'wrapper loop'): 2524 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2003 self.signature(Wrapped) 2525 self.signature(Wrapped)
2004 2526
2005 def test_signature_on_lambdas(self): 2527 def test_signature_on_lambdas(self):
2006 self.assertEqual(self.signature((lambda a=10: a)), 2528 self.assertEqual(self.signature((lambda a=10: a)),
2007 ((('a', 10, ..., "positional_or_keyword"),), 2529 ((('a', 10, ..., "positional_or_keyword"),),
2008 ...)) 2530 ...))
2009 2531
2010 def test_signature_equality(self): 2532 def test_signature_equality(self):
2011 def foo(a, *, b:int) -> float: pass 2533 def foo(a, *, b:int) -> float: pass
2012 self.assertNotEqual(inspect.signature(foo), 42) 2534 self.assertNotEqual(inspect.signature(foo), 42)
2013 2535
2014 def bar(a, *, b:int) -> float: pass 2536 def bar(a, *, b:int) -> float: pass
2015 self.assertEqual(inspect.signature(foo), inspect.signature(bar)) 2537 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2538 self.assertEqual(
2539 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
2016 2540
2017 def bar(a, *, b:int) -> int: pass 2541 def bar(a, *, b:int) -> int: pass
2018 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) 2542 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2543 self.assertNotEqual(
2544 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
2019 2545
2020 def bar(a, *, b:int): pass 2546 def bar(a, *, b:int): pass
2021 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) 2547 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2548 self.assertNotEqual(
2549 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
2022 2550
2023 def bar(a, *, b:int=42) -> float: pass 2551 def bar(a, *, b:int=42) -> float: pass
2024 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) 2552 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2553 self.assertNotEqual(
2554 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
2025 2555
2026 def bar(a, *, c) -> float: pass 2556 def bar(a, *, c) -> float: pass
2027 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) 2557 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2558 self.assertNotEqual(
2559 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
2028 2560
2029 def bar(a, b:int) -> float: pass 2561 def bar(a, b:int) -> float: pass
2030 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) 2562 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2563 self.assertNotEqual(
2564 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
2031 def spam(b:int, a) -> float: pass 2565 def spam(b:int, a) -> float: pass
2032 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar)) 2566 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2567 self.assertNotEqual(
2568 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
2033 2569
2034 def foo(*, a, b, c): pass 2570 def foo(*, a, b, c): pass
2035 def bar(*, c, b, a): pass 2571 def bar(*, c, b, a): pass
2036 self.assertEqual(inspect.signature(foo), inspect.signature(bar)) 2572 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2573 self.assertEqual(
2574 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
2037 2575
2038 def foo(*, a=1, b, c): pass 2576 def foo(*, a=1, b, c): pass
2039 def bar(*, c, b, a=1): pass 2577 def bar(*, c, b, a=1): pass
2040 self.assertEqual(inspect.signature(foo), inspect.signature(bar)) 2578 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2579 self.assertEqual(
2580 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
2041 2581
2042 def foo(pos, *, a=1, b, c): pass 2582 def foo(pos, *, a=1, b, c): pass
2043 def bar(pos, *, c, b, a=1): pass 2583 def bar(pos, *, c, b, a=1): pass
2044 self.assertEqual(inspect.signature(foo), inspect.signature(bar)) 2584 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2585 self.assertEqual(
2586 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
2045 2587
2046 def foo(pos, *, a, b, c): pass 2588 def foo(pos, *, a, b, c): pass
2047 def bar(pos, *, c, b, a=1): pass 2589 def bar(pos, *, c, b, a=1): pass
2048 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) 2590 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2591 self.assertNotEqual(
2592 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
2049 2593
2050 def foo(pos, *args, a=42, b, c, **kwargs:int): pass 2594 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2051 def bar(pos, *args, c, b, a=42, **kwargs:int): pass 2595 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2052 self.assertEqual(inspect.signature(foo), inspect.signature(bar)) 2596 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2597 self.assertEqual(
2598 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
2053 2599
2054 def test_signature_hashable(self): 2600 def test_signature_hashable(self):
2055 S = inspect.Signature 2601 S = inspect.Signature
2056 P = inspect.Parameter 2602 P = inspect.Parameter
2057 2603
2058 def foo(a): pass 2604 def foo(a): pass
2059 auto_sig = inspect.signature(foo) 2605 foo_sig = inspect.signature(foo)
2060 2606
2061 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)]) 2607 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2062 2608
2063 self.assertEqual(hash(auto_sig), hash(manual_sig)) 2609 self.assertEqual(hash(foo_sig), hash(manual_sig))
2064 self.assertNotEqual(hash(auto_sig), 2610 self.assertNotEqual(hash(foo_sig),
2065 hash(manual_sig.replace(return_annotation='spam'))) 2611 hash(manual_sig.replace(return_annotation='spam')))
2612
2613 def bar(a) -> 1: pass
2614 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2615
2616 def foo(a={}): pass
2617 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2618 hash(inspect.signature(foo))
2619
2620 def foo(a) -> {}: pass
2621 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2622 hash(inspect.signature(foo))
2066 2623
2067 def test_signature_str(self): 2624 def test_signature_str(self):
2068 def foo(a:int=1, *, b, c=None, **kwargs) -> 42: 2625 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2069 pass 2626 pass
2070 self.assertEqual(str(inspect.signature(foo)), 2627 self.assertEqual(str(inspect.signature(foo)),
2071 '(a:int=1, *, b, c=None, **kwargs) -> 42') 2628 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2072 2629
2073 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42: 2630 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2074 pass 2631 pass
2075 self.assertEqual(str(inspect.signature(foo)), 2632 self.assertEqual(str(inspect.signature(foo)),
2076 '(a:int=1, *args, b, c=None, **kwargs) -> 42') 2633 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2077 2634
2078 def foo(): 2635 def foo():
2079 pass 2636 pass
2080 self.assertEqual(str(inspect.signature(foo)), '()') 2637 self.assertEqual(str(inspect.signature(foo)), '()')
2081 2638
2082 def test_signature_str_positional_only(self): 2639 def test_signature_str_positional_only(self):
2083 P = inspect.Parameter 2640 P = inspect.Parameter
2641 S = inspect.Signature
2084 2642
2085 def test(a_po, *, b, **kwargs): 2643 def test(a_po, *, b, **kwargs):
2086 return a_po, kwargs 2644 return a_po, kwargs
2087 2645
2088 sig = inspect.signature(test) 2646 sig = inspect.signature(test)
2089 new_params = list(sig.parameters.values()) 2647 new_params = list(sig.parameters.values())
2090 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY) 2648 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2091 test.__signature__ = sig.replace(parameters=new_params) 2649 test.__signature__ = sig.replace(parameters=new_params)
2092 2650
2093 self.assertEqual(str(inspect.signature(test)), 2651 self.assertEqual(str(inspect.signature(test)),
2094 '(<a_po>, *, b, **kwargs)') 2652 '(a_po, /, *, b, **kwargs)')
2095 2653
2096 sig = inspect.signature(test) 2654 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2097 new_params = list(sig.parameters.values()) 2655 '(foo, /)')
2098 new_params[0] = new_params[0].replace(name=None) 2656
2099 test.__signature__ = sig.replace(parameters=new_params) 2657 self.assertEqual(str(S(parameters=[
2100 self.assertEqual(str(inspect.signature(test)), 2658 P('foo', P.POSITIONAL_ONLY),
2101 '(<0>, *, b, **kwargs)') 2659 P('bar', P.VAR_KEYWORD)])),
2660 '(foo, /, **bar)')
2661
2662 self.assertEqual(str(S(parameters=[
2663 P('foo', P.POSITIONAL_ONLY),
2664 P('bar', P.VAR_POSITIONAL)])),
2665 '(foo, /, *bar)')
2102 2666
2103 def test_signature_replace_anno(self): 2667 def test_signature_replace_anno(self):
2104 def test() -> 42: 2668 def test() -> 42:
2105 pass 2669 pass
2106 2670
2107 sig = inspect.signature(test) 2671 sig = inspect.signature(test)
2108 sig = sig.replace(return_annotation=None) 2672 sig = sig.replace(return_annotation=None)
2109 self.assertIs(sig.return_annotation, None) 2673 self.assertIs(sig.return_annotation, None)
2110 sig = sig.replace(return_annotation=sig.empty) 2674 sig = sig.replace(return_annotation=sig.empty)
2111 self.assertIs(sig.return_annotation, sig.empty) 2675 self.assertIs(sig.return_annotation, sig.empty)
2112 sig = sig.replace(return_annotation=42) 2676 sig = sig.replace(return_annotation=42)
2113 self.assertEqual(sig.return_annotation, 42) 2677 self.assertEqual(sig.return_annotation, 42)
2114 self.assertEqual(sig, inspect.signature(test)) 2678 self.assertEqual(sig, inspect.signature(test))
2115 2679
2680 def test_signature_on_mangled_parameters(self):
2681 class Spam:
2682 def foo(self, __p1:1=2, *, __p2:2=3):
2683 pass
2684 class Ham(Spam):
2685 pass
2686
2687 self.assertEqual(self.signature(Spam.foo),
2688 ((('self', ..., ..., "positional_or_keyword"),
2689 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2690 ('_Spam__p2', 3, 2, "keyword_only")),
2691 ...))
2692
2693 self.assertEqual(self.signature(Spam.foo),
2694 self.signature(Ham.foo))
2695
2696 def test_signature_from_callable_python_obj(self):
2697 class MySignature(inspect.Signature): pass
2698 def foo(a, *, b:1): pass
2699 foo_sig = MySignature.from_callable(foo)
2700 self.assertTrue(isinstance(foo_sig, MySignature))
2701
2702 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2703 "Signature information for builtins requires docstrings")
2704 def test_signature_from_callable_builtin_obj(self):
2705 class MySignature(inspect.Signature): pass
2706 sig = MySignature.from_callable(_pickle.Pickler)
2707 self.assertTrue(isinstance(sig, MySignature))
2708
2116 2709
2117 class TestParameterObject(unittest.TestCase): 2710 class TestParameterObject(unittest.TestCase):
2118 def test_signature_parameter_kinds(self): 2711 def test_signature_parameter_kinds(self):
2119 P = inspect.Parameter 2712 P = inspect.Parameter
2120 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \ 2713 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2121 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD) 2714 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2122 2715
2123 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY') 2716 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2124 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY)) 2717 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2125 2718
2126 def test_signature_parameter_object(self): 2719 def test_signature_parameter_object(self):
2127 p = inspect.Parameter('foo', default=10, 2720 p = inspect.Parameter('foo', default=10,
2128 kind=inspect.Parameter.POSITIONAL_ONLY) 2721 kind=inspect.Parameter.POSITIONAL_ONLY)
2129 self.assertEqual(p.name, 'foo') 2722 self.assertEqual(p.name, 'foo')
2130 self.assertEqual(p.default, 10) 2723 self.assertEqual(p.default, 10)
2131 self.assertIs(p.annotation, p.empty) 2724 self.assertIs(p.annotation, p.empty)
2132 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY) 2725 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2133 2726
2134 with self.assertRaisesRegex(ValueError, 'invalid value'): 2727 with self.assertRaisesRegex(ValueError, 'invalid value'):
2135 inspect.Parameter('foo', default=10, kind='123') 2728 inspect.Parameter('foo', default=10, kind='123')
2136 2729
2137 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'): 2730 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
2138 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD) 2731 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2139 2732
2733 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2734 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2735
2140 with self.assertRaisesRegex(ValueError, 2736 with self.assertRaisesRegex(ValueError,
2141 'non-positional-only parameter'): 2737 'is not a valid parameter name'):
2142 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD) 2738 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2143 2739
2144 with self.assertRaisesRegex(ValueError, 'cannot have default values'): 2740 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
2145 inspect.Parameter('a', default=42, 2741 inspect.Parameter('a', default=42,
2146 kind=inspect.Parameter.VAR_KEYWORD) 2742 kind=inspect.Parameter.VAR_KEYWORD)
2147 2743
2148 with self.assertRaisesRegex(ValueError, 'cannot have default values'): 2744 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
2149 inspect.Parameter('a', default=42, 2745 inspect.Parameter('a', default=42,
2150 kind=inspect.Parameter.VAR_POSITIONAL) 2746 kind=inspect.Parameter.VAR_POSITIONAL)
2151 2747
2152 p = inspect.Parameter('a', default=42, 2748 p = inspect.Parameter('a', default=42,
2153 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD) 2749 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
2154 with self.assertRaisesRegex(ValueError, 'cannot have default values'): 2750 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
2155 p.replace(kind=inspect.Parameter.VAR_POSITIONAL) 2751 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2156 2752
2157 self.assertTrue(repr(p).startswith('<Parameter')) 2753 self.assertTrue(repr(p).startswith('<Parameter'))
2754 self.assertTrue('"a=42"' in repr(p))
2158 2755
2159 def test_signature_parameter_hashable(self): 2756 def test_signature_parameter_hashable(self):
2160 P = inspect.Parameter 2757 P = inspect.Parameter
2161 foo = P('foo', kind=P.POSITIONAL_ONLY) 2758 foo = P('foo', kind=P.POSITIONAL_ONLY)
2162 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY))) 2759 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
2163 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY, 2760 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
2164 default=42))) 2761 default=42)))
2165 self.assertNotEqual(hash(foo), 2762 self.assertNotEqual(hash(foo),
2166 hash(foo.replace(kind=P.VAR_POSITIONAL))) 2763 hash(foo.replace(kind=P.VAR_POSITIONAL)))
2167 2764
(...skipping 16 matching lines...) Expand all
2184 2781
2185 p2 = p.replace(annotation=1) 2782 p2 = p.replace(annotation=1)
2186 self.assertEqual(p2.annotation, 1) 2783 self.assertEqual(p2.annotation, 1)
2187 p2 = p2.replace(annotation=p2.empty) 2784 p2 = p2.replace(annotation=p2.empty)
2188 self.assertEqual(p, p2) 2785 self.assertEqual(p, p2)
2189 2786
2190 p2 = p2.replace(name='bar') 2787 p2 = p2.replace(name='bar')
2191 self.assertEqual(p2.name, 'bar') 2788 self.assertEqual(p2.name, 'bar')
2192 self.assertNotEqual(p2, p) 2789 self.assertNotEqual(p2, p)
2193 2790
2194 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'): 2791 with self.assertRaisesRegex(ValueError,
2792 'name is a required attribute'):
2195 p2 = p2.replace(name=p2.empty) 2793 p2 = p2.replace(name=p2.empty)
2196 2794
2197 p2 = p2.replace(name='foo', default=None) 2795 p2 = p2.replace(name='foo', default=None)
2198 self.assertIs(p2.default, None) 2796 self.assertIs(p2.default, None)
2199 self.assertNotEqual(p2, p) 2797 self.assertNotEqual(p2, p)
2200 2798
2201 p2 = p2.replace(name='foo', default=p2.empty) 2799 p2 = p2.replace(name='foo', default=p2.empty)
2202 self.assertIs(p2.default, p2.empty) 2800 self.assertIs(p2.default, p2.empty)
2203 2801
2204 2802
2205 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD) 2803 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2206 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD) 2804 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2207 self.assertNotEqual(p2, p) 2805 self.assertNotEqual(p2, p)
2208 2806
2209 with self.assertRaisesRegex(ValueError, 'invalid value for'): 2807 with self.assertRaisesRegex(ValueError, 'invalid value for'):
2210 p2 = p2.replace(kind=p2.empty) 2808 p2 = p2.replace(kind=p2.empty)
2211 2809
2212 p2 = p2.replace(kind=p2.KEYWORD_ONLY) 2810 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2213 self.assertEqual(p2, p) 2811 self.assertEqual(p2, p)
2214 2812
2215 def test_signature_parameter_positional_only(self): 2813 def test_signature_parameter_positional_only(self):
2216 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY) 2814 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2217 self.assertEqual(str(p), '<>') 2815 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2218
2219 p = p.replace(name='1')
2220 self.assertEqual(str(p), '<1>')
2221 2816
2222 def test_signature_parameter_immutability(self): 2817 def test_signature_parameter_immutability(self):
2223 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY) 2818 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
2224 2819
2225 with self.assertRaises(AttributeError): 2820 with self.assertRaises(AttributeError):
2226 p.foo = 'bar' 2821 p.foo = 'bar'
2227 2822
2228 with self.assertRaises(AttributeError): 2823 with self.assertRaises(AttributeError):
2229 p.kind = 123 2824 p.kind = 123
2230 2825
2231 2826
2232 class TestSignatureBind(unittest.TestCase): 2827 class TestSignatureBind(unittest.TestCase):
2233 @staticmethod 2828 @staticmethod
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
2411 sig = inspect.signature(test) 3006 sig = inspect.signature(test)
2412 new_params = collections.OrderedDict(tuple(sig.parameters.items())) 3007 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2413 for name in ('a_po', 'b_po', 'c_po'): 3008 for name in ('a_po', 'b_po', 'c_po'):
2414 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY) 3009 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2415 new_sig = sig.replace(parameters=new_params.values()) 3010 new_sig = sig.replace(parameters=new_params.values())
2416 test.__signature__ = new_sig 3011 test.__signature__ = new_sig
2417 3012
2418 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6), 3013 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2419 (1, 2, 4, 5, 6, {})) 3014 (1, 2, 4, 5, 6, {}))
2420 3015
3016 self.assertEqual(self.call(test, 1, 2),
3017 (1, 2, 3, 42, 50, {}))
3018
3019 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3020 (1, 2, 3, 4, 5, {}))
3021
3022 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3023 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3024
2421 with self.assertRaisesRegex(TypeError, "parameter is positional only"): 3025 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
2422 self.call(test, 1, 2, c_po=4) 3026 self.call(test, 1, 2, c_po=4)
2423 3027
2424 with self.assertRaisesRegex(TypeError, "parameter is positional only"): 3028 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
2425 self.call(test, a_po=1, b_po=2) 3029 self.call(test, a_po=1, b_po=2)
2426 3030
2427 def test_signature_bind_with_self_arg(self): 3031 def test_signature_bind_with_self_arg(self):
2428 # Issue #17071: one of the parameters is named "self 3032 # Issue #17071: one of the parameters is named "self
2429 def test(a, self, b): 3033 def test(a, self, b):
2430 pass 3034 pass
2431 sig = inspect.signature(test) 3035 sig = inspect.signature(test)
2432 ba = sig.bind(1, 2, 3) 3036 ba = sig.bind(1, 2, 3)
2433 self.assertEqual(ba.args, (1, 2, 3)) 3037 self.assertEqual(ba.args, (1, 2, 3))
2434 ba = sig.bind(1, self=2, b=3) 3038 ba = sig.bind(1, self=2, b=3)
2435 self.assertEqual(ba.args, (1, 2, 3)) 3039 self.assertEqual(ba.args, (1, 2, 3))
2436 3040
3041 def test_signature_bind_vararg_name(self):
3042 def test(a, *args):
3043 return a, args
3044 sig = inspect.signature(test)
3045
3046 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
3047 sig.bind(a=0, args=1)
3048
3049 def test(*args, **kwargs):
3050 return args, kwargs
3051 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3052
3053 sig = inspect.signature(test)
3054 ba = sig.bind(args=1)
3055 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3056
2437 3057
2438 class TestBoundArguments(unittest.TestCase): 3058 class TestBoundArguments(unittest.TestCase):
2439 def test_signature_bound_arguments_unhashable(self): 3059 def test_signature_bound_arguments_unhashable(self):
2440 def foo(a): pass 3060 def foo(a): pass
2441 ba = inspect.signature(foo).bind(1) 3061 ba = inspect.signature(foo).bind(1)
2442 3062
2443 with self.assertRaisesRegex(TypeError, 'unhashable type'): 3063 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2444 hash(ba) 3064 hash(ba)
2445 3065
2446 def test_signature_bound_arguments_equality(self): 3066 def test_signature_bound_arguments_equality(self):
2447 def foo(a): pass 3067 def foo(a): pass
2448 ba = inspect.signature(foo).bind(1) 3068 ba = inspect.signature(foo).bind(1)
2449 self.assertEqual(ba, ba) 3069 self.assertEqual(ba, ba)
2450 3070
2451 ba2 = inspect.signature(foo).bind(1) 3071 ba2 = inspect.signature(foo).bind(1)
2452 self.assertEqual(ba, ba2) 3072 self.assertEqual(ba, ba2)
2453 3073
2454 ba3 = inspect.signature(foo).bind(2) 3074 ba3 = inspect.signature(foo).bind(2)
2455 self.assertNotEqual(ba, ba3) 3075 self.assertNotEqual(ba, ba3)
2456 ba3.arguments['a'] = 1 3076 ba3.arguments['a'] = 1
2457 self.assertEqual(ba, ba3) 3077 self.assertEqual(ba, ba3)
2458 3078
2459 def bar(b): pass 3079 def bar(b): pass
2460 ba4 = inspect.signature(bar).bind(1) 3080 ba4 = inspect.signature(bar).bind(1)
2461 self.assertNotEqual(ba, ba4) 3081 self.assertNotEqual(ba, ba4)
3082
3083 def test_signature_bound_arguments_pickle(self):
3084 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3085 sig = inspect.signature(foo)
3086 ba = sig.bind(20, 30, z={})
3087
3088 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3089 with self.subTest(pickle_ver=ver):
3090 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3091 self.assertEqual(ba, ba_pickled)
3092
3093
3094 class TestSignaturePrivateHelpers(unittest.TestCase):
3095 def test_signature_get_bound_param(self):
3096 getter = inspect._signature_get_bound_param
3097
3098 self.assertEqual(getter('($self)'), 'self')
3099 self.assertEqual(getter('($self, obj)'), 'self')
3100 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3101
3102 def _strip_non_python_syntax(self, input,
3103 clean_signature, self_parameter, last_positional_only):
3104 computed_clean_signature, \
3105 computed_self_parameter, \
3106 computed_last_positional_only = \
3107 inspect._signature_strip_non_python_syntax(input)
3108 self.assertEqual(computed_clean_signature, clean_signature)
3109 self.assertEqual(computed_self_parameter, self_parameter)
3110 self.assertEqual(computed_last_positional_only, last_positional_only)
3111
3112 def test_signature_strip_non_python_syntax(self):
3113 self._strip_non_python_syntax(
3114 "($module, /, path, mode, *, dir_fd=None, " +
3115 "effective_ids=False,\n follow_symlinks=True)",
3116 "(module, path, mode, *, dir_fd=None, " +
3117 "effective_ids=False, follow_symlinks=True)",
3118 0,
3119 0)
3120
3121 self._strip_non_python_syntax(
3122 "($module, word, salt, /)",
3123 "(module, word, salt)",
3124 0,
3125 2)
3126
3127 self._strip_non_python_syntax(
3128 "(x, y=None, z=None, /)",
3129 "(x, y=None, z=None)",
3130 None,
3131 2)
3132
3133 self._strip_non_python_syntax(
3134 "(x, y=None, z=None)",
3135 "(x, y=None, z=None)",
3136 None,
3137 None)
3138
3139 self._strip_non_python_syntax(
3140 "(x,\n y=None,\n z = None )",
3141 "(x, y=None, z=None)",
3142 None,
3143 None)
3144
3145 self._strip_non_python_syntax(
3146 "",
3147 "",
3148 None,
3149 None)
3150
3151 self._strip_non_python_syntax(
3152 None,
3153 None,
3154 None,
3155 None)
2462 3156
2463 3157
2464 class TestUnwrap(unittest.TestCase): 3158 class TestUnwrap(unittest.TestCase):
2465 3159
2466 def test_unwrap_one(self): 3160 def test_unwrap_one(self):
2467 def func(a, b): 3161 def func(a, b):
2468 return a + b 3162 return a + b
2469 wrapper = functools.lru_cache(maxsize=20)(func) 3163 wrapper = functools.lru_cache(maxsize=20)(func)
2470 self.assertIs(inspect.unwrap(wrapper), func) 3164 self.assertIs(inspect.unwrap(wrapper), func)
2471 3165
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2518 3212
2519 class TestMain(unittest.TestCase): 3213 class TestMain(unittest.TestCase):
2520 def test_only_source(self): 3214 def test_only_source(self):
2521 module = importlib.import_module('unittest') 3215 module = importlib.import_module('unittest')
2522 rc, out, err = assert_python_ok('-m', 'inspect', 3216 rc, out, err = assert_python_ok('-m', 'inspect',
2523 'unittest') 3217 'unittest')
2524 lines = out.decode().splitlines() 3218 lines = out.decode().splitlines()
2525 # ignore the final newline 3219 # ignore the final newline
2526 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines()) 3220 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
2527 self.assertEqual(err, b'') 3221 self.assertEqual(err, b'')
3222
3223 def test_custom_getattr(self):
3224 def foo():
3225 pass
3226 foo.__signature__ = 42
3227 with self.assertRaises(TypeError):
3228 inspect.signature(foo)
2528 3229
2529 @unittest.skipIf(ThreadPoolExecutor is None, 3230 @unittest.skipIf(ThreadPoolExecutor is None,
2530 'threads required to test __qualname__ for source files') 3231 'threads required to test __qualname__ for source files')
2531 def test_qualname_source(self): 3232 def test_qualname_source(self):
2532 rc, out, err = assert_python_ok('-m', 'inspect', 3233 rc, out, err = assert_python_ok('-m', 'inspect',
2533 'concurrent.futures:ThreadPoolExecutor') 3234 'concurrent.futures:ThreadPoolExecutor')
2534 lines = out.decode().splitlines() 3235 lines = out.decode().splitlines()
2535 # ignore the final newline 3236 # ignore the final newline
2536 self.assertEqual(lines[:-1], 3237 self.assertEqual(lines[:-1],
2537 inspect.getsource(ThreadPoolExecutor).splitlines()) 3238 inspect.getsource(ThreadPoolExecutor).splitlines())
(...skipping 21 matching lines...) Expand all
2559 3260
2560 3261
2561 3262
2562 def test_main(): 3263 def test_main():
2563 run_unittest( 3264 run_unittest(
2564 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases, 3265 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
2565 TestInterpreterStack, TestClassesAndFunctions, TestPredicates, 3266 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
2566 TestGetcallargsFunctions, TestGetcallargsMethods, 3267 TestGetcallargsFunctions, TestGetcallargsMethods,
2567 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState, 3268 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
2568 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject, 3269 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
2569 TestBoundArguments, TestGetClosureVars, TestUnwrap, TestMain 3270 TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars,
3271 TestUnwrap, TestMain
2570 ) 3272 )
2571 3273
2572 if __name__ == "__main__": 3274 if __name__ == "__main__":
2573 test_main() 3275 test_main()
LEFTRIGHT

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