ยปCore Development>Code coverage>Lib/test/test_inspect.py

Python code coverage for Lib/test/test_inspect.py

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