blob: 0ab65307cdd0954178a69dd35fbe66bbeb4e67b3 [file] [log] [blame]
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001import builtins
Guido van Rossum813b0e52007-05-21 18:11:34 +00002import collections
Larry Hastings5c661892014-01-24 06:17:25 -08003import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10004import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10005import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08006import inspect
7import io
8import linecache
9import os
Christian Heimesa3538eb2007-11-06 11:44:48 +000010from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080011import _pickle
Yury Selivanova5d63dd2014-03-27 11:31:43 -040012import pickle
Larry Hastings5c661892014-01-24 06:17:25 -080013import shutil
14import sys
15import types
Yury Selivanovef1e7502014-12-08 16:05:34 -050016import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080017import unicodedata
18import unittest
Yury Selivanova773de02014-02-21 18:30:53 -050019import unittest.mock
Yury Selivanov75445082015-05-11 22:57:16 -040020import warnings
Larry Hastings5c661892014-01-24 06:17:25 -080021
Brett Cannon634a8fc2013-10-02 10:25:42 -040022try:
23 from concurrent.futures import ThreadPoolExecutor
24except ImportError:
25 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000026
Hai Shic7decc22020-08-04 23:53:12 +080027from test.support import run_unittest, cpython_only
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +030028from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ
Hai Shic7decc22020-08-04 23:53:12 +080029from test.support.import_helper import DirsOnSysPath
30from test.support.os_helper import TESTFN
Berker Peksagce643912015-05-06 06:33:17 +030031from test.support.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000032from test import inspect_fodder as mod
33from test import inspect_fodder2 as mod2
Victor Stinner9def2842016-01-18 12:15:08 +010034from test import support
larryhastings74613a42021-04-29 21:16:28 -070035from test import inspect_stock_annotations
36from test import inspect_stringized_annotations
37from test import inspect_stringized_annotations_2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000038
Yury Selivanovef1e7502014-12-08 16:05:34 -050039from test.test_import import _ready_to_import
40
R. David Murray74b89242009-05-13 17:33:03 +000041
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000042# Functions tested in this suite:
43# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000044# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
45# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
Berker Peksagfa3922c2015-07-31 04:11:29 +030046# getclasstree, getargvalues, formatargspec, formatargvalues,
Christian Heimes7131fd92008-02-19 14:21:46 +000047# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000048
Nick Coghlanf088e5e2008-12-14 11:50:48 +000049# NOTE: There are some additional tests relating to interaction with
50# zipimport in the test_zipimport_support test module.
51
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000052modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000053if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000054 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000055
Christian Heimesa3538eb2007-11-06 11:44:48 +000056# Normalize file names: on Windows, the case of file names of compiled
57# modules depends on the path used to start the python executable.
58modfile = normcase(modfile)
59
60def revise(filename, *args):
61 return (normcase(filename),) + args
62
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000063git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000064
larryhastingsf36ba122018-01-28 11:13:09 -080065
66def signatures_with_lexicographic_keyword_only_parameters():
67 """
68 Yields a whole bunch of functions with only keyword-only parameters,
69 where those parameters are always in lexicographically sorted order.
70 """
71 parameters = ['a', 'bar', 'c', 'delta', 'ephraim', 'magical', 'yoyo', 'z']
72 for i in range(1, 2**len(parameters)):
73 p = []
74 bit = 1
75 for j in range(len(parameters)):
76 if i & (bit << j):
77 p.append(parameters[j])
78 fn_text = "def foo(*, " + ", ".join(p) + "): pass"
79 symbols = {}
80 exec(fn_text, symbols, symbols)
81 yield symbols['foo']
82
83
84def unsorted_keyword_only_parameters_fn(*, throw, out, the, baby, with_,
85 the_, bathwater):
86 pass
87
88unsorted_keyword_only_parameters = 'throw out the baby with_ the_ bathwater'.split()
89
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000090class IsTestBase(unittest.TestCase):
91 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
92 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000093 inspect.ismodule, inspect.istraceback,
Yury Selivanov75445082015-05-11 22:57:16 -040094 inspect.isgenerator, inspect.isgeneratorfunction,
Yury Selivanoveb636452016-09-08 22:01:51 -070095 inspect.iscoroutine, inspect.iscoroutinefunction,
96 inspect.isasyncgen, inspect.isasyncgenfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000097
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000098 def istest(self, predicate, exp):
99 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000100 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000101
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000102 for other in self.predicates - set([predicate]):
Yury Selivanov75445082015-05-11 22:57:16 -0400103 if (predicate == inspect.isgeneratorfunction or \
Yury Selivanoveb636452016-09-08 22:01:51 -0700104 predicate == inspect.isasyncgenfunction or \
Yury Selivanov75445082015-05-11 22:57:16 -0400105 predicate == inspect.iscoroutinefunction) and \
Christian Heimes7131fd92008-02-19 14:21:46 +0000106 other == inspect.isfunction:
107 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000108 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000109
Christian Heimes7131fd92008-02-19 14:21:46 +0000110def generator_function_example(self):
111 for i in range(2):
112 yield i
113
Yury Selivanoveb636452016-09-08 22:01:51 -0700114async def async_generator_function_example(self):
115 async for i in range(2):
116 yield i
117
Yury Selivanov75445082015-05-11 22:57:16 -0400118async def coroutine_function_example(self):
119 return 'spam'
120
121@types.coroutine
122def gen_coroutine_function_example(self):
123 yield
124 return 'spam'
125
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000126class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +0000127
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000128 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200129 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000130 self.istest(inspect.isbuiltin, 'sys.exit')
131 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +0000132 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200133 try:
134 1/0
135 except:
136 tb = sys.exc_info()[2]
137 self.istest(inspect.isframe, 'tb.tb_frame')
138 self.istest(inspect.istraceback, 'tb')
139 if hasattr(types, 'GetSetDescriptorType'):
140 self.istest(inspect.isgetsetdescriptor,
141 'type(tb.tb_frame).f_locals')
142 else:
143 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
144 finally:
145 # Clear traceback and all the frames and local variables hanging to it.
146 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000147 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000148 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000149 self.istest(inspect.ismethod, 'git.argue')
Jeroen Demeyerfcef60f2019-04-02 16:03:42 +0200150 self.istest(inspect.ismethod, 'mod.custom_method')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000151 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000152 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000153 self.istest(inspect.isgenerator, '(x for x in range(2))')
154 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanoveb636452016-09-08 22:01:51 -0700155 self.istest(inspect.isasyncgen,
156 'async_generator_function_example(1)')
157 self.istest(inspect.isasyncgenfunction,
158 'async_generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400159
160 with warnings.catch_warnings():
161 warnings.simplefilter("ignore")
162 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
163 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
164
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000165 if hasattr(types, 'MemberDescriptorType'):
166 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
167 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000168 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000169
Yury Selivanov75445082015-05-11 22:57:16 -0400170 def test_iscoroutine(self):
Pablo Galindo7cd25432018-10-26 12:19:14 +0100171 async_gen_coro = async_generator_function_example(1)
Yury Selivanov75445082015-05-11 22:57:16 -0400172 gen_coro = gen_coroutine_function_example(1)
173 coro = coroutine_function_example(1)
174
Yury Selivanov5376ba92015-06-22 12:19:30 -0400175 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400176 inspect.iscoroutinefunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100177 self.assertFalse(
178 inspect.iscoroutinefunction(
179 functools.partial(functools.partial(
180 gen_coroutine_function_example))))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400181 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400182
183 self.assertTrue(
184 inspect.isgeneratorfunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100185 self.assertTrue(
186 inspect.isgeneratorfunction(
187 functools.partial(functools.partial(
188 gen_coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400189 self.assertTrue(inspect.isgenerator(gen_coro))
190
191 self.assertTrue(
192 inspect.iscoroutinefunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100193 self.assertTrue(
194 inspect.iscoroutinefunction(
195 functools.partial(functools.partial(
196 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400197 self.assertTrue(inspect.iscoroutine(coro))
198
199 self.assertFalse(
200 inspect.isgeneratorfunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100201 self.assertFalse(
202 inspect.isgeneratorfunction(
203 functools.partial(functools.partial(
204 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400205 self.assertFalse(inspect.isgenerator(coro))
206
Pablo Galindo7cd25432018-10-26 12:19:14 +0100207 self.assertTrue(
208 inspect.isasyncgenfunction(async_generator_function_example))
209 self.assertTrue(
210 inspect.isasyncgenfunction(
211 functools.partial(functools.partial(
212 async_generator_function_example))))
213 self.assertTrue(inspect.isasyncgen(async_gen_coro))
214
215 coro.close(); gen_coro.close(); # silence warnings
Yury Selivanov75445082015-05-11 22:57:16 -0400216
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400217 def test_isawaitable(self):
218 def gen(): yield
219 self.assertFalse(inspect.isawaitable(gen()))
220
221 coro = coroutine_function_example(1)
222 gen_coro = gen_coroutine_function_example(1)
223
224 self.assertTrue(inspect.isawaitable(coro))
225 self.assertTrue(inspect.isawaitable(gen_coro))
226
227 class Future:
228 def __await__():
229 pass
230 self.assertTrue(inspect.isawaitable(Future()))
231 self.assertFalse(inspect.isawaitable(Future))
232
233 class NotFuture: pass
234 not_fut = NotFuture()
235 not_fut.__await__ = lambda: None
236 self.assertFalse(inspect.isawaitable(not_fut))
237
238 coro.close(); gen_coro.close() # silence warnings
239
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000240 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000241 self.assertTrue(inspect.isroutine(mod.spam))
242 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000243
Benjamin Petersonc4656002009-01-17 22:41:18 +0000244 def test_isclass(self):
245 self.istest(inspect.isclass, 'mod.StupidGit')
246 self.assertTrue(inspect.isclass(list))
247
248 class CustomGetattr(object):
249 def __getattr__(self, attr):
250 return None
251 self.assertFalse(inspect.isclass(CustomGetattr()))
252
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000253 def test_get_slot_members(self):
254 class C(object):
255 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000256 x = C()
257 x.a = 42
258 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000259 self.assertIn('a', members)
260 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000261
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000262 def test_isabstract(self):
263 from abc import ABCMeta, abstractmethod
264
265 class AbstractClassExample(metaclass=ABCMeta):
266
267 @abstractmethod
268 def foo(self):
269 pass
270
271 class ClassExample(AbstractClassExample):
272 def foo(self):
273 pass
274
275 a = ClassExample()
276
277 # Test general behaviour.
278 self.assertTrue(inspect.isabstract(AbstractClassExample))
279 self.assertFalse(inspect.isabstract(ClassExample))
280 self.assertFalse(inspect.isabstract(a))
281 self.assertFalse(inspect.isabstract(int))
282 self.assertFalse(inspect.isabstract(5))
283
Natefcfe80e2017-04-24 10:06:15 -0700284 def test_isabstract_during_init_subclass(self):
285 from abc import ABCMeta, abstractmethod
286 isabstract_checks = []
287 class AbstractChecker(metaclass=ABCMeta):
288 def __init_subclass__(cls):
289 isabstract_checks.append(inspect.isabstract(cls))
290 class AbstractClassExample(AbstractChecker):
291 @abstractmethod
292 def foo(self):
293 pass
294 class ClassExample(AbstractClassExample):
295 def foo(self):
296 pass
297 self.assertEqual(isabstract_checks, [True, False])
298
299 isabstract_checks.clear()
300 class AbstractChild(AbstractClassExample):
301 pass
302 class AbstractGrandchild(AbstractChild):
303 pass
304 class ConcreteGrandchild(ClassExample):
305 pass
306 self.assertEqual(isabstract_checks, [True, True, False])
307
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000308
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000309class TestInterpreterStack(IsTestBase):
310 def __init__(self, *args, **kwargs):
311 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000312
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000313 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000314
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000315 def test_abuse_done(self):
316 self.istest(inspect.istraceback, 'git.ex[2]')
317 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000318
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000319 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000320 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000321 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000322 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000323 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000324 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000325 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000326 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000327 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000328 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400329 # Test named tuple fields
330 record = mod.st[0]
331 self.assertIs(record.frame, mod.fr)
332 self.assertEqual(record.lineno, 16)
333 self.assertEqual(record.filename, mod.__file__)
334 self.assertEqual(record.function, 'eggs')
335 self.assertIn('inspect.stack()', record.code_context[0])
336 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000337
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000338 def test_trace(self):
339 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000340 self.assertEqual(revise(*git.tr[0][1:]),
341 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
342 self.assertEqual(revise(*git.tr[1][1:]),
343 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
344 self.assertEqual(revise(*git.tr[2][1:]),
345 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000346
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000347 def test_frame(self):
348 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
349 self.assertEqual(args, ['x', 'y'])
350 self.assertEqual(varargs, None)
351 self.assertEqual(varkw, None)
352 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
353 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
354 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000355
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000356 def test_previous_frame(self):
357 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000358 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000359 self.assertEqual(varargs, 'g')
360 self.assertEqual(varkw, 'h')
361 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000362 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000363
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000364class GetSourceBase(unittest.TestCase):
365 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000366 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000367
Yury Selivanov6738b112015-05-16 10:10:21 -0400368 def setUp(self):
Inada Naokifb786922021-04-06 11:18:41 +0900369 with open(inspect.getsourcefile(self.fodderModule), encoding="utf-8") as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000370 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000371
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000372 def sourcerange(self, top, bottom):
373 lines = self.source.split("\n")
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700374 return "\n".join(lines[top-1:bottom]) + ("\n" if bottom else "")
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000375
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000376 def assertSourceEqual(self, obj, top, bottom):
377 self.assertEqual(inspect.getsource(obj),
378 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000379
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700380class SlotUser:
381 'Docstrings for __slots__'
382 __slots__ = {'power': 'measured in kilowatts',
383 'distance': 'measured in kilometers'}
384
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000385class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000386 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000387
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000388 def test_getclasses(self):
389 classes = inspect.getmembers(mod, inspect.isclass)
390 self.assertEqual(classes,
391 [('FesteringGob', mod.FesteringGob),
392 ('MalodorousPervert', mod.MalodorousPervert),
393 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300394 ('StupidGit', mod.StupidGit),
395 ('Tit', mod.MalodorousPervert),
Irit Katriel6e1eec72020-12-04 16:45:38 +0000396 ('WhichComments', mod.WhichComments),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300397 ])
398 tree = inspect.getclasstree([cls[1] for cls in classes])
399 self.assertEqual(tree,
400 [(object, ()),
401 [(mod.ParrotDroppings, (object,)),
402 [(mod.FesteringGob, (mod.MalodorousPervert,
403 mod.ParrotDroppings))
404 ],
405 (mod.StupidGit, (object,)),
406 [(mod.MalodorousPervert, (mod.StupidGit,)),
407 [(mod.FesteringGob, (mod.MalodorousPervert,
408 mod.ParrotDroppings))
409 ]
Irit Katriel6e1eec72020-12-04 16:45:38 +0000410 ],
411 (mod.WhichComments, (object,),)
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300412 ]
413 ])
414 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000415 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000416 [(object, ()),
417 [(mod.ParrotDroppings, (object,)),
418 (mod.StupidGit, (object,)),
419 [(mod.MalodorousPervert, (mod.StupidGit,)),
420 [(mod.FesteringGob, (mod.MalodorousPervert,
421 mod.ParrotDroppings))
422 ]
Irit Katriel6e1eec72020-12-04 16:45:38 +0000423 ],
424 (mod.WhichComments, (object,),)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000425 ]
426 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000427
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000428 def test_getfunctions(self):
429 functions = inspect.getmembers(mod, inspect.isfunction)
430 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300431 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000432 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000433
R. David Murray378c0cf2010-02-24 01:46:21 +0000434 @unittest.skipIf(sys.flags.optimize >= 2,
435 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000436 def test_getdoc(self):
437 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
438 self.assertEqual(inspect.getdoc(mod.StupidGit),
439 'A longer,\n\nindented\n\ndocstring.')
440 self.assertEqual(inspect.getdoc(git.abuse),
441 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700442 self.assertEqual(inspect.getdoc(SlotUser.power),
443 'measured in kilowatts')
444 self.assertEqual(inspect.getdoc(SlotUser.distance),
445 'measured in kilometers')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000446
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300447 @unittest.skipIf(sys.flags.optimize >= 2,
448 "Docstrings are omitted with -O2 and above")
449 def test_getdoc_inherited(self):
Serhiy Storchaka08b47c32020-05-18 20:25:07 +0300450 self.assertEqual(inspect.getdoc(mod.FesteringGob),
451 'A longer,\n\nindented\n\ndocstring.')
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300452 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
453 'Another\n\ndocstring\n\ncontaining\n\ntabs')
454 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
455 'Another\n\ndocstring\n\ncontaining\n\ntabs')
456 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
457 'The automatic gainsaying.')
458
459 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
460 def test_finddoc(self):
461 finddoc = inspect._finddoc
Serhiy Storchaka08b47c32020-05-18 20:25:07 +0300462 self.assertEqual(finddoc(int), int.__doc__)
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300463 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
464 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
465 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
466 self.assertEqual(finddoc(int.real), int.real.__doc__)
467
Georg Brandl0c77a822008-06-10 16:37:50 +0000468 def test_cleandoc(self):
469 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
470 'An\nindented\ndocstring.')
471
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000472 def test_getcomments(self):
473 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
474 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530475 self.assertEqual(inspect.getcomments(mod2.cls160), '# line 159\n')
Marco Buttu3f2155f2017-03-17 09:50:23 +0100476 # If the object source file is not available, return None.
477 co = compile('x=1', '_non_existing_filename.py', 'exec')
478 self.assertIsNone(inspect.getcomments(co))
479 # If the object has been defined in C, return None.
480 self.assertIsNone(inspect.getcomments(list))
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000481
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000482 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000483 # Check actual module
484 self.assertEqual(inspect.getmodule(mod), mod)
485 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000486 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000487 # Check a method (no __module__ attribute, falls back to filename)
488 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
489 # Do it again (check the caching isn't broken)
490 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
491 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000492 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000493 # Check filename override
494 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000495
Berker Peksagff0e3b72017-01-02 06:57:43 +0300496 def test_getframeinfo_get_first_line(self):
497 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
498 self.assertEqual(frame_info.code_context[0], "# line 1\n")
499 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
500
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000501 def test_getsource(self):
502 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200503 self.assertSourceEqual(mod.StupidGit, 21, 51)
504 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000505
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000506 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000507 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
508 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000509 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100510 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000511 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000512 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200513 try:
514 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
515 finally:
516 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000517
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000518 def test_getfile(self):
519 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000520
Philipp Ad407d2a2019-06-08 14:05:46 +0200521 def test_getfile_builtin_module(self):
522 with self.assertRaises(TypeError) as e:
523 inspect.getfile(sys)
524 self.assertTrue(str(e.exception).startswith('<module'))
525
526 def test_getfile_builtin_class(self):
527 with self.assertRaises(TypeError) as e:
528 inspect.getfile(int)
529 self.assertTrue(str(e.exception).startswith('<class'))
530
531 def test_getfile_builtin_function_or_method(self):
532 with self.assertRaises(TypeError) as e_abs:
533 inspect.getfile(abs)
534 self.assertIn('expected, got', str(e_abs.exception))
535 with self.assertRaises(TypeError) as e_append:
536 inspect.getfile(list.append)
537 self.assertIn('expected, got', str(e_append.exception))
538
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500539 def test_getfile_class_without_module(self):
540 class CM(type):
541 @property
542 def __module__(cls):
543 raise AttributeError
544 class C(metaclass=CM):
545 pass
546 with self.assertRaises(TypeError):
547 inspect.getfile(C)
548
Thomas Kluyvere968bc732017-10-24 13:42:36 +0100549 def test_getfile_broken_repr(self):
550 class ErrorRepr:
551 def __repr__(self):
552 raise Exception('xyz')
553 er = ErrorRepr()
554 with self.assertRaises(TypeError):
555 inspect.getfile(er)
556
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000557 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000558 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000559 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000560 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000561 m.__file__ = "<string>" # hopefully not a real filename...
562 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000563 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000564 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000565 del sys.modules[name]
566 inspect.getmodule(compile('a=10','','single'))
567
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500568 def test_proceed_with_fake_filename(self):
569 '''doctest monkeypatches linecache to enable inspection'''
570 fn, source = '<test>', 'def x(): pass\n'
571 getlines = linecache.getlines
572 def monkey(filename, module_globals=None):
573 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300574 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500575 else:
576 return getlines(filename, module_globals)
577 linecache.getlines = monkey
578 try:
579 ns = {}
580 exec(compile(source, fn, 'single'), ns)
581 inspect.getsource(ns["x"])
582 finally:
583 linecache.getlines = getlines
584
Antoine Pitroua8723a02015-04-15 00:41:29 +0200585 def test_getsource_on_code_object(self):
586 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
587
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700588class TestGettingSourceOfToplevelFrames(GetSourceBase):
589 fodderModule = mod
590
591 def test_range_toplevel_frame(self):
592 self.maxDiff = None
593 self.assertSourceEqual(mod.currentframe, 1, None)
594
595 def test_range_traceback_toplevel_frame(self):
596 self.assertSourceEqual(mod.tb, 1, None)
597
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000598class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000599 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000600
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000601 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000602 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000603
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000604 def test_replacing_decorator(self):
605 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000606
Yury Selivanov081bbf62014-09-26 17:34:54 -0400607 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200608 self.assertSourceEqual(mod2.real, 130, 132)
609
610 def test_decorator_with_lambda(self):
611 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400612
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000613class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000614 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000615 def test_oneline_lambda(self):
616 # Test inspect.getsource with a one-line lambda function.
617 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000618
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000619 def test_threeline_lambda(self):
620 # Test inspect.getsource with a three-line lambda function,
621 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000622 self.assertSourceEqual(mod2.tll, 28, 30)
623
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000624 def test_twoline_indented_lambda(self):
625 # Test inspect.getsource with a two-line lambda function,
626 # where the second line _is_ indented.
627 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000628
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000629 def test_onelinefunc(self):
630 # Test inspect.getsource with a regular one-line function.
631 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000632
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000633 def test_manyargs(self):
634 # Test inspect.getsource with a regular function where
635 # the arguments are on two lines and _not_ indented and
636 # the body on the second line with the last arguments.
637 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000638
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000639 def test_twolinefunc(self):
640 # Test inspect.getsource with a regular function where
641 # the body is on two lines, following the argument list and
642 # continued on the next line by a \\.
643 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000644
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000645 def test_lambda_in_list(self):
646 # Test inspect.getsource with a one-line lambda function
647 # defined in a list, indented.
648 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000649
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000650 def test_anonymous(self):
651 # Test inspect.getsource with a lambda function defined
652 # as argument to another function.
653 self.assertSourceEqual(mod2.anonymous, 55, 55)
654
Irit Katriel6e1eec72020-12-04 16:45:38 +0000655class TestBlockComments(GetSourceBase):
656 fodderModule = mod
657
658 def test_toplevel_class(self):
659 self.assertSourceEqual(mod.WhichComments, 96, 114)
660
661 def test_class_method(self):
662 self.assertSourceEqual(mod.WhichComments.f, 99, 104)
663
664 def test_class_async_method(self):
665 self.assertSourceEqual(mod.WhichComments.asyncf, 109, 112)
666
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000667class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000668 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000669
670 def test_with_comment(self):
671 self.assertSourceEqual(mod2.with_comment, 58, 59)
672
673 def test_multiline_sig(self):
674 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
675
Armin Rigodd5c0232005-09-25 11:45:45 +0000676 def test_nested_class(self):
677 self.assertSourceEqual(mod2.func69().func71, 71, 72)
678
679 def test_one_liner_followed_by_non_name(self):
680 self.assertSourceEqual(mod2.func77, 77, 77)
681
682 def test_one_liner_dedent_non_name(self):
683 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
684
685 def test_with_comment_instead_of_docstring(self):
686 self.assertSourceEqual(mod2.func88, 88, 90)
687
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000688 def test_method_in_dynamic_class(self):
689 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
690
R David Murray32562d72014-10-03 11:15:38 -0400691 # This should not skip for CPython, but might on a repackaged python where
692 # unicodedata is not an external module, or on pypy.
693 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
694 unicodedata.__file__.endswith('.py'),
695 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000696 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200697 self.assertRaises(OSError, inspect.getsource, unicodedata)
698 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000699
R. David Murraya1b37402010-06-17 02:04:29 +0000700 def test_findsource_code_in_linecache(self):
701 lines = ["x=1"]
702 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200703 self.assertRaises(OSError, inspect.findsource, co)
704 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000705 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200706 try:
707 self.assertEqual(inspect.findsource(co), (lines,0))
708 self.assertEqual(inspect.getsource(co), lines[0])
709 finally:
710 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000711
Ezio Melotti1b145922013-03-30 05:17:24 +0200712 def test_findsource_without_filename(self):
713 for fname in ['', '<string>']:
714 co = compile('x=1', fname, "exec")
715 self.assertRaises(IOError, inspect.findsource, co)
716 self.assertRaises(IOError, inspect.getsource, co)
717
Irit Katriel2e0760b2020-12-04 21:22:03 +0000718 def test_findsource_with_out_of_bounds_lineno(self):
719 mod_len = len(inspect.getsource(mod))
720 src = '\n' * 2* mod_len + "def f(): pass"
721 co = compile(src, mod.__file__, "exec")
722 g, l = {}, {}
723 eval(co, g, l)
724 func = l['f']
725 self.assertEqual(func.__code__.co_firstlineno, 1+2*mod_len)
726 with self.assertRaisesRegex(IOError, "lineno is out of bounds"):
727 inspect.findsource(func)
728
Antoine Pitroua8723a02015-04-15 00:41:29 +0200729 def test_getsource_on_method(self):
730 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
731
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300732 def test_nested_func(self):
733 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
734
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530735 def test_class_definition_in_multiline_string_definition(self):
736 self.assertSourceEqual(mod2.cls149, 149, 152)
737
738 def test_class_definition_in_multiline_comment(self):
739 self.assertSourceEqual(mod2.cls160, 160, 163)
740
741 def test_nested_class_definition_indented_string(self):
742 self.assertSourceEqual(mod2.cls173.cls175, 175, 176)
743
744 def test_nested_class_definition(self):
745 self.assertSourceEqual(mod2.cls183, 183, 188)
746 self.assertSourceEqual(mod2.cls183.cls185, 185, 188)
747
748 def test_class_decorator(self):
749 self.assertSourceEqual(mod2.cls196, 194, 201)
750 self.assertSourceEqual(mod2.cls196.cls200, 198, 201)
751
752 def test_class_inside_conditional(self):
753 self.assertSourceEqual(mod2.cls238, 238, 240)
754 self.assertSourceEqual(mod2.cls238.cls239, 239, 240)
755
756 def test_multiple_children_classes(self):
757 self.assertSourceEqual(mod2.cls203, 203, 209)
758 self.assertSourceEqual(mod2.cls203.cls204, 204, 206)
759 self.assertSourceEqual(mod2.cls203.cls204.cls205, 205, 206)
760 self.assertSourceEqual(mod2.cls203.cls207, 207, 209)
761 self.assertSourceEqual(mod2.cls203.cls207.cls205, 208, 209)
762
763 def test_nested_class_definition_inside_function(self):
764 self.assertSourceEqual(mod2.func212(), 213, 214)
765 self.assertSourceEqual(mod2.cls213, 218, 222)
766 self.assertSourceEqual(mod2.cls213().func219(), 220, 221)
767
768 def test_nested_class_definition_inside_async_function(self):
769 import asyncio
770 self.addCleanup(asyncio.set_event_loop_policy, None)
771 self.assertSourceEqual(asyncio.run(mod2.func225()), 226, 227)
772 self.assertSourceEqual(mod2.cls226, 231, 235)
773 self.assertSourceEqual(asyncio.run(mod2.cls226().func232()), 233, 234)
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300774
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000775class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400776 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000777 self.tempdir = TESTFN + '_dir'
778 os.mkdir(self.tempdir)
Inada Naokifb786922021-04-06 11:18:41 +0900779 with open(os.path.join(self.tempdir, 'inspect_fodder3%spy' % os.extsep),
780 'w', encoding='utf-8') as f:
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000781 f.write("class X:\n pass # No EOL")
782 with DirsOnSysPath(self.tempdir):
783 import inspect_fodder3 as mod3
784 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400785 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000786
787 def tearDown(self):
788 shutil.rmtree(self.tempdir)
789
790 def test_class(self):
791 self.assertSourceEqual(self.fodderModule.X, 1, 2)
792
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100793
794class _BrokenDataDescriptor(object):
795 """
796 A broken data descriptor. See bug #1785.
797 """
798 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700799 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100800
801 def __set__(*args):
802 raise RuntimeError
803
804 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700805 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100806
807
808class _BrokenMethodDescriptor(object):
809 """
810 A broken method descriptor. See bug #1785.
811 """
812 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700813 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100814
815 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700816 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100817
818
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000819# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000820def attrs_wo_objs(cls):
821 return [t[:3] for t in inspect.classify_class_attrs(cls)]
822
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100823
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000824class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000825 def test_newstyle_mro(self):
826 # The same w/ new-class MRO.
827 class A(object): pass
828 class B(A): pass
829 class C(A): pass
830 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000831
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000832 expected = (D, B, C, A, object)
833 got = inspect.getmro(D)
834 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000835
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500836 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
837 varkw_e=None, defaults_e=None, formatted=None):
Xtreak6d0b7472019-05-30 17:31:39 +0530838 with self.assertWarns(DeprecationWarning):
839 args, varargs, varkw, defaults = inspect.getargspec(routine)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500840 self.assertEqual(args, args_e)
841 self.assertEqual(varargs, varargs_e)
842 self.assertEqual(varkw, varkw_e)
843 self.assertEqual(defaults, defaults_e)
844 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530845 with self.assertWarns(DeprecationWarning):
846 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
847 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500848
Christian Heimes3795b532007-11-08 13:48:53 +0000849 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
850 varkw_e=None, defaults_e=None,
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100851 posonlyargs_e=[], kwonlyargs_e=[],
852 kwonlydefaults_e=None,
Christian Heimes3795b532007-11-08 13:48:53 +0000853 ann_e={}, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100854 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
855 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000856 self.assertEqual(args, args_e)
857 self.assertEqual(varargs, varargs_e)
858 self.assertEqual(varkw, varkw_e)
859 self.assertEqual(defaults, defaults_e)
860 self.assertEqual(kwonlyargs, kwonlyargs_e)
861 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
862 self.assertEqual(ann, ann_e)
863 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530864 with self.assertWarns(DeprecationWarning):
865 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
866 kwonlyargs, kwonlydefaults, ann),
867 formatted)
Christian Heimes3795b532007-11-08 13:48:53 +0000868
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500869 def test_getargspec(self):
870 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
871
Pablo Galindod5d2b452019-04-30 02:01:14 +0100872 self.assertArgSpecEquals(mod.spam,
873 ['a', 'b', 'c', 'd', 'e', 'f'],
874 'g', 'h', (3, 4, 5),
875 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500876
877 self.assertRaises(ValueError, self.assertArgSpecEquals,
878 mod2.keyworded, [])
879
880 self.assertRaises(ValueError, self.assertArgSpecEquals,
881 mod2.annotated, [])
882 self.assertRaises(ValueError, self.assertArgSpecEquals,
883 mod2.keyword_only_arg, [])
884
885
Christian Heimes3795b532007-11-08 13:48:53 +0000886 def test_getfullargspec(self):
887 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
888 kwonlyargs_e=['arg2'],
889 kwonlydefaults_e={'arg2':1},
890 formatted='(*arg1, arg2=1)')
891
892 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000893 ann_e={'arg1' : list},
Pablo Galindob0544ba2021-04-21 12:41:19 +0100894 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000895 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
896 kwonlyargs_e=['arg'],
897 formatted='(*, arg)')
898
Pablo Galindod5d2b452019-04-30 02:01:14 +0100899 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100900 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100901 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100902
903 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100904 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100905 varargs_e='args',
906 varkw_e='kwargs',
907 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100908 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100909
Pablo Galindod5d2b452019-04-30 02:01:14 +0100910 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100911 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100912 kwonlyargs_e=['e', 'f'],
913 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100914 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100915
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500916 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500917 # Issue 20684: low level introspection API must ignore __wrapped__
918 @functools.wraps(mod.spam)
919 def ham(x, y):
920 pass
921 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500922 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500923 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
924 self.assertFullArgSpecEquals(functools.partial(ham),
925 ['x', 'y'], formatted='(x, y)')
926 # Other variants
927 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500928 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
929 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500930 class C:
931 @functools.wraps(mod.spam)
932 def ham(self, x, y):
933 pass
934 pham = functools.partialmethod(ham)
935 @functools.wraps(mod.spam)
936 def __call__(self, x, y):
937 pass
938 check_method(C())
939 check_method(C.ham)
940 check_method(C().ham)
941 check_method(C.pham)
942 check_method(C().pham)
943
944 class C_new:
945 @functools.wraps(mod.spam)
946 def __new__(self, x, y):
947 pass
948 check_method(C_new)
949
950 class C_init:
951 @functools.wraps(mod.spam)
952 def __init__(self, x, y):
953 pass
954 check_method(C_init)
955
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500956 def test_getfullargspec_signature_attr(self):
957 def test():
958 pass
959 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
960 test.__signature__ = inspect.Signature(parameters=(spam_param,))
961
Pablo Galindod5d2b452019-04-30 02:01:14 +0100962 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500963
Yury Selivanov4cb93912014-01-29 11:54:12 -0500964 def test_getfullargspec_signature_annos(self):
965 def test(a:'spam') -> 'ham': pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100966 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500967 self.assertEqual(test.__annotations__, spec.annotations)
968
969 def test(): pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100970 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500971 self.assertEqual(test.__annotations__, spec.annotations)
972
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500973 @unittest.skipIf(MISSING_C_DOCSTRINGS,
974 "Signature information for builtins requires docstrings")
975 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100976 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
977 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500978
Pablo Galindod5d2b452019-04-30 02:01:14 +0100979 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
980 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500981
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500982 self.assertFullArgSpecEquals(
983 os.stat,
984 args_e=['path'],
985 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
986 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
987 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
988
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200989 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500990 @unittest.skipIf(MISSING_C_DOCSTRINGS,
991 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800992 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200993 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500994 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindoaee19f52019-05-16 21:08:15 +0100995 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500996 self.assertEqual(spec.defaults[0], 'avocado')
997
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200998 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500999 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1000 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +08001001 def test_getfullargspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001002 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001003 builtin = _testcapi.docstring_no_signature
Pablo Galindoaee19f52019-05-16 21:08:15 +01001004 with self.assertRaises(TypeError):
1005 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +00001006
larryhastingsf36ba122018-01-28 11:13:09 -08001007 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
1008 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindoaee19f52019-05-16 21:08:15 +01001009 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -08001010 l = list(signature.kwonlyargs)
1011 sorted_l = sorted(l)
1012 self.assertTrue(l)
1013 self.assertEqual(l, sorted_l)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001014 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -08001015 l = list(signature.kwonlyargs)
1016 self.assertEqual(l, unsorted_keyword_only_parameters)
1017
Yury Selivanov37dc2b22016-01-11 15:15:01 -05001018 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001019 class A(object):
1020 def m(self):
1021 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -05001022 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +00001023
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001024 def test_classify_newstyle(self):
1025 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +00001026
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001027 def s(): pass
1028 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +00001029
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001030 def c(cls): pass
1031 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +00001032
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001033 def getp(self): pass
1034 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +00001035
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001036 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001037
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001038 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001039
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001040 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +00001041
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001042 dd = _BrokenDataDescriptor()
1043 md = _BrokenMethodDescriptor()
1044
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001045 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001046
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001047 self.assertIn(('__new__', 'static method', object), attrs,
1048 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001049 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
1050
Benjamin Peterson577473f2010-01-19 00:09:57 +00001051 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1052 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1053 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001054 self.assertIn(('m', 'method', A), attrs,
1055 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001056 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1057 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001058 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1059 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001060
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001061 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001062
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001063 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001064
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001065 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001066 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1067 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1068 self.assertIn(('p', 'property', A), attrs, 'missing property')
1069 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1070 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1071 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001072 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1073 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001074
1075
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001076 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001077
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001078 def m(self): pass
1079 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001080
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001081 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001082 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1083 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1084 self.assertIn(('p', 'property', A), attrs, 'missing property')
1085 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
1086 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1087 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001088 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1089 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001090
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001091 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001092
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001093 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001094
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001095 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001096 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1097 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1098 self.assertIn(('p', 'property', A), attrs, 'missing property')
1099 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1100 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1101 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001102 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1103 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1104
1105 def test_classify_builtin_types(self):
1106 # Simple sanity check that all built-in types can have their
1107 # attributes classified.
1108 for name in dir(__builtins__):
1109 builtin = getattr(__builtins__, name)
1110 if isinstance(builtin, type):
1111 inspect.classify_class_attrs(builtin)
1112
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001113 attrs = attrs_wo_objs(bool)
1114 self.assertIn(('__new__', 'static method', bool), attrs,
1115 'missing __new__')
1116 self.assertIn(('from_bytes', 'class method', int), attrs,
1117 'missing class method')
1118 self.assertIn(('to_bytes', 'method', int), attrs,
1119 'missing plain method')
1120 self.assertIn(('__add__', 'method', int), attrs,
1121 'missing plain method')
1122 self.assertIn(('__and__', 'method', bool), attrs,
1123 'missing plain method')
1124
Ethan Furman63c141c2013-10-18 00:27:39 -07001125 def test_classify_DynamicClassAttribute(self):
1126 class Meta(type):
1127 def __getattr__(self, name):
1128 if name == 'ham':
1129 return 'spam'
1130 return super().__getattr__(name)
1131 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001132 @types.DynamicClassAttribute
1133 def ham(self):
1134 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001135 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1136 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001137 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001138 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1139
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001140 def test_classify_overrides_bool(self):
1141 class NoBool(object):
1142 def __eq__(self, other):
1143 return NoBool()
1144
1145 def __bool__(self):
1146 raise NotImplementedError(
1147 "This object does not specify a boolean value")
1148
1149 class HasNB(object):
1150 dd = NoBool()
1151
1152 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1153 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1154
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001155 def test_classify_metaclass_class_attribute(self):
1156 class Meta(type):
1157 fish = 'slap'
1158 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001159 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001160 class Class(metaclass=Meta):
1161 pass
1162 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1163 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1164
Ethan Furman63c141c2013-10-18 00:27:39 -07001165 def test_classify_VirtualAttribute(self):
1166 class Meta(type):
1167 def __dir__(cls):
1168 return ['__class__', '__module__', '__name__', 'BOOM']
1169 def __getattr__(self, name):
1170 if name =='BOOM':
1171 return 42
1172 return super().__getattr(name)
1173 class Class(metaclass=Meta):
1174 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001175 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001176 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1177
1178 def test_classify_VirtualAttribute_multi_classes(self):
1179 class Meta1(type):
1180 def __dir__(cls):
1181 return ['__class__', '__module__', '__name__', 'one']
1182 def __getattr__(self, name):
1183 if name =='one':
1184 return 1
1185 return super().__getattr__(name)
1186 class Meta2(type):
1187 def __dir__(cls):
1188 return ['__class__', '__module__', '__name__', 'two']
1189 def __getattr__(self, name):
1190 if name =='two':
1191 return 2
1192 return super().__getattr__(name)
1193 class Meta3(Meta1, Meta2):
1194 def __dir__(cls):
1195 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1196 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1197 def __getattr__(self, name):
1198 if name =='three':
1199 return 3
1200 return super().__getattr__(name)
1201 class Class1(metaclass=Meta1):
1202 pass
1203 class Class2(Class1, metaclass=Meta3):
1204 pass
1205
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001206 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1207 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1208 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001209 cca = inspect.classify_class_attrs(Class2)
1210 for sf in (should_find1, should_find2, should_find3):
1211 self.assertIn(sf, cca)
1212
1213 def test_classify_class_attrs_with_buggy_dir(self):
1214 class M(type):
1215 def __dir__(cls):
1216 return ['__class__', '__name__', 'missing']
1217 class C(metaclass=M):
1218 pass
1219 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1220 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001221
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001222 def test_getmembers_descriptors(self):
1223 class A(object):
1224 dd = _BrokenDataDescriptor()
1225 md = _BrokenMethodDescriptor()
1226
1227 def pred_wrapper(pred):
1228 # A quick'n'dirty way to discard standard attributes of new-style
1229 # classes.
1230 class Empty(object):
1231 pass
1232 def wrapped(x):
1233 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1234 return False
1235 return pred(x)
1236 return wrapped
1237
1238 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1239 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1240
1241 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1242 [('md', A.__dict__['md'])])
1243 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1244 [('dd', A.__dict__['dd'])])
1245
1246 class B(A):
1247 pass
1248
1249 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1250 [('md', A.__dict__['md'])])
1251 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1252 [('dd', A.__dict__['dd'])])
1253
Antoine Pitrou0c603812012-01-18 17:40:18 +01001254 def test_getmembers_method(self):
1255 class B:
1256 def f(self):
1257 pass
1258
1259 self.assertIn(('f', B.f), inspect.getmembers(B))
1260 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1261 b = B()
1262 self.assertIn(('f', b.f), inspect.getmembers(b))
1263 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1264
Ethan Furmane03ea372013-09-25 07:14:41 -07001265 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001266 class M(type):
1267 def __getattr__(cls, name):
1268 if name == 'eggs':
1269 return 'scrambled'
1270 return super().__getattr__(name)
1271 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001272 @types.DynamicClassAttribute
1273 def eggs(self):
1274 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001275 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1276 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1277
1278 def test_getmembers_with_buggy_dir(self):
1279 class M(type):
1280 def __dir__(cls):
1281 return ['__class__', '__name__', 'missing']
1282 class C(metaclass=M):
1283 pass
1284 attrs = [a[0] for a in inspect.getmembers(C)]
1285 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001286
larryhastings74613a42021-04-29 21:16:28 -07001287 def test_get_annotations_with_stock_annotations(self):
1288 def foo(a:int, b:str): pass
1289 self.assertEqual(inspect.get_annotations(foo), {'a': int, 'b': str})
1290
1291 foo.__annotations__ = {'a': 'foo', 'b':'str'}
1292 self.assertEqual(inspect.get_annotations(foo), {'a': 'foo', 'b': 'str'})
1293
1294 self.assertEqual(inspect.get_annotations(foo, eval_str=True, locals=locals()), {'a': foo, 'b': str})
1295 self.assertEqual(inspect.get_annotations(foo, eval_str=True, globals=locals()), {'a': foo, 'b': str})
1296
1297 isa = inspect_stock_annotations
1298 self.assertEqual(inspect.get_annotations(isa), {'a': int, 'b': str})
1299 self.assertEqual(inspect.get_annotations(isa.MyClass), {'a': int, 'b': str})
1300 self.assertEqual(inspect.get_annotations(isa.function), {'a': int, 'b': str, 'return': isa.MyClass})
1301 self.assertEqual(inspect.get_annotations(isa.function2), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1302 self.assertEqual(inspect.get_annotations(isa.function3), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1303 self.assertEqual(inspect.get_annotations(inspect), {}) # inspect module has no annotations
1304 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass), {})
1305 self.assertEqual(inspect.get_annotations(isa.unannotated_function), {})
1306
1307 self.assertEqual(inspect.get_annotations(isa, eval_str=True), {'a': int, 'b': str})
1308 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=True), {'a': int, 'b': str})
1309 self.assertEqual(inspect.get_annotations(isa.function, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1310 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=True), {'a': int, 'b': str, 'c': isa.MyClass, 'return': isa.MyClass})
1311 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=True), {'a': int, 'b': str, 'c': isa.MyClass})
1312 self.assertEqual(inspect.get_annotations(inspect, eval_str=True), {})
1313 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=True), {})
1314 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=True), {})
1315
1316 self.assertEqual(inspect.get_annotations(isa, eval_str=False), {'a': int, 'b': str})
1317 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=False), {'a': int, 'b': str})
1318 self.assertEqual(inspect.get_annotations(isa.function, eval_str=False), {'a': int, 'b': str, 'return': isa.MyClass})
1319 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=False), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1320 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=False), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1321 self.assertEqual(inspect.get_annotations(inspect, eval_str=False), {})
1322 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=False), {})
1323 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=False), {})
1324
1325 def times_three(fn):
1326 @functools.wraps(fn)
1327 def wrapper(a, b):
1328 return fn(a*3, b*3)
1329 return wrapper
1330
1331 wrapped = times_three(isa.function)
1332 self.assertEqual(wrapped(1, 'x'), isa.MyClass(3, 'xxx'))
1333 self.assertIsNot(wrapped.__globals__, isa.function.__globals__)
1334 self.assertEqual(inspect.get_annotations(wrapped), {'a': int, 'b': str, 'return': isa.MyClass})
1335 self.assertEqual(inspect.get_annotations(wrapped, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1336 self.assertEqual(inspect.get_annotations(wrapped, eval_str=False), {'a': int, 'b': str, 'return': isa.MyClass})
1337
1338 def test_get_annotations_with_stringized_annotations(self):
1339 isa = inspect_stringized_annotations
1340 self.assertEqual(inspect.get_annotations(isa), {'a': 'int', 'b': 'str'})
1341 self.assertEqual(inspect.get_annotations(isa.MyClass), {'a': 'int', 'b': 'str'})
1342 self.assertEqual(inspect.get_annotations(isa.function), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1343 self.assertEqual(inspect.get_annotations(isa.function2), {'a': 'int', 'b': "'str'", 'c': 'MyClass', 'return': 'MyClass'})
1344 self.assertEqual(inspect.get_annotations(isa.function3), {'a': "'int'", 'b': "'str'", 'c': "'MyClass'"})
1345 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass), {})
1346 self.assertEqual(inspect.get_annotations(isa.unannotated_function), {})
1347
1348 self.assertEqual(inspect.get_annotations(isa, eval_str=True), {'a': int, 'b': str})
1349 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=True), {'a': int, 'b': str})
1350 self.assertEqual(inspect.get_annotations(isa.function, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1351 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=True), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1352 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=True), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1353 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=True), {})
1354 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=True), {})
1355
1356 self.assertEqual(inspect.get_annotations(isa, eval_str=False), {'a': 'int', 'b': 'str'})
1357 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=False), {'a': 'int', 'b': 'str'})
1358 self.assertEqual(inspect.get_annotations(isa.function, eval_str=False), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1359 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=False), {'a': 'int', 'b': "'str'", 'c': 'MyClass', 'return': 'MyClass'})
1360 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=False), {'a': "'int'", 'b': "'str'", 'c': "'MyClass'"})
1361 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=False), {})
1362 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=False), {})
1363
1364 isa2 = inspect_stringized_annotations_2
1365 self.assertEqual(inspect.get_annotations(isa2), {})
1366 self.assertEqual(inspect.get_annotations(isa2, eval_str=True), {})
1367 self.assertEqual(inspect.get_annotations(isa2, eval_str=False), {})
1368
1369 def times_three(fn):
1370 @functools.wraps(fn)
1371 def wrapper(a, b):
1372 return fn(a*3, b*3)
1373 return wrapper
1374
1375 wrapped = times_three(isa.function)
1376 self.assertEqual(wrapped(1, 'x'), isa.MyClass(3, 'xxx'))
1377 self.assertIsNot(wrapped.__globals__, isa.function.__globals__)
1378 self.assertEqual(inspect.get_annotations(wrapped), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1379 self.assertEqual(inspect.get_annotations(wrapped, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1380 self.assertEqual(inspect.get_annotations(wrapped, eval_str=False), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1381
1382 # test that local namespace lookups work
1383 self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations), {'x': 'mytype'})
1384 self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations, eval_str=True), {'x': int})
1385
1386
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001387class TestIsDataDescriptor(unittest.TestCase):
1388
1389 def test_custom_descriptors(self):
1390 class NonDataDescriptor:
1391 def __get__(self, value, type=None): pass
1392 class DataDescriptor0:
1393 def __set__(self, name, value): pass
1394 class DataDescriptor1:
1395 def __delete__(self, name): pass
1396 class DataDescriptor2:
1397 __set__ = None
1398 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1399 'class with only __get__ not a data descriptor')
1400 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1401 'class with __set__ is a data descriptor')
1402 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1403 'class with __delete__ is a data descriptor')
1404 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1405 'class with __set__ = None is a data descriptor')
1406
1407 def test_slot(self):
1408 class Slotted:
1409 __slots__ = 'foo',
1410 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1411 'a slot is a data descriptor')
1412
1413 def test_property(self):
1414 class Propertied:
1415 @property
1416 def a_property(self):
1417 pass
1418 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1419 'a property is a data descriptor')
1420
1421 def test_functions(self):
1422 class Test(object):
1423 def instance_method(self): pass
1424 @classmethod
1425 def class_method(cls): pass
1426 @staticmethod
1427 def static_method(): pass
1428 def function():
1429 pass
1430 a_lambda = lambda: None
1431 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1432 'a instance method is not a data descriptor')
1433 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1434 'a class method is not a data descriptor')
1435 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1436 'a static method is not a data descriptor')
1437 self.assertFalse(inspect.isdatadescriptor(function),
1438 'a function is not a data descriptor')
1439 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1440 'a lambda is not a data descriptor')
1441
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001442
Nick Coghlan2f92e542012-06-23 19:39:55 +10001443_global_ref = object()
1444class TestGetClosureVars(unittest.TestCase):
1445
1446 def test_name_resolution(self):
1447 # Basic test of the 4 different resolution mechanisms
1448 def f(nonlocal_ref):
1449 def g(local_ref):
1450 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1451 return g
1452 _arg = object()
1453 nonlocal_vars = {"nonlocal_ref": _arg}
1454 global_vars = {"_global_ref": _global_ref}
1455 builtin_vars = {"print": print}
1456 unbound_names = {"unbound_ref"}
1457 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1458 builtin_vars, unbound_names)
1459 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1460
1461 def test_generator_closure(self):
1462 def f(nonlocal_ref):
1463 def g(local_ref):
1464 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1465 yield
1466 return g
1467 _arg = object()
1468 nonlocal_vars = {"nonlocal_ref": _arg}
1469 global_vars = {"_global_ref": _global_ref}
1470 builtin_vars = {"print": print}
1471 unbound_names = {"unbound_ref"}
1472 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1473 builtin_vars, unbound_names)
1474 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1475
1476 def test_method_closure(self):
1477 class C:
1478 def f(self, nonlocal_ref):
1479 def g(local_ref):
1480 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1481 return g
1482 _arg = object()
1483 nonlocal_vars = {"nonlocal_ref": _arg}
1484 global_vars = {"_global_ref": _global_ref}
1485 builtin_vars = {"print": print}
1486 unbound_names = {"unbound_ref"}
1487 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1488 builtin_vars, unbound_names)
1489 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1490
1491 def test_nonlocal_vars(self):
1492 # More complex tests of nonlocal resolution
1493 def _nonlocal_vars(f):
1494 return inspect.getclosurevars(f).nonlocals
1495
1496 def make_adder(x):
1497 def add(y):
1498 return x + y
1499 return add
1500
1501 def curry(func, arg1):
1502 return lambda arg2: func(arg1, arg2)
1503
1504 def less_than(a, b):
1505 return a < b
1506
1507 # The infamous Y combinator.
1508 def Y(le):
1509 def g(f):
1510 return le(lambda x: f(f)(x))
1511 Y.g_ref = g
1512 return g(g)
1513
1514 def check_y_combinator(func):
1515 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1516
1517 inc = make_adder(1)
1518 add_two = make_adder(2)
1519 greater_than_five = curry(less_than, 5)
1520
1521 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1522 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1523 self.assertEqual(_nonlocal_vars(greater_than_five),
1524 {'arg1': 5, 'func': less_than})
1525 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1526 {'x': 3})
1527 Y(check_y_combinator)
1528
1529 def test_getclosurevars_empty(self):
1530 def foo(): pass
1531 _empty = inspect.ClosureVars({}, {}, {}, set())
1532 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1533 self.assertEqual(inspect.getclosurevars(foo), _empty)
1534
1535 def test_getclosurevars_error(self):
1536 class T: pass
1537 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1538 self.assertRaises(TypeError, inspect.getclosurevars, list)
1539 self.assertRaises(TypeError, inspect.getclosurevars, {})
1540
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001541 def _private_globals(self):
1542 code = """def f(): print(path)"""
1543 ns = {}
1544 exec(code, ns)
1545 return ns["f"], ns
1546
1547 def test_builtins_fallback(self):
1548 f, ns = self._private_globals()
1549 ns.pop("__builtins__", None)
1550 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1551 self.assertEqual(inspect.getclosurevars(f), expected)
1552
1553 def test_builtins_as_dict(self):
1554 f, ns = self._private_globals()
1555 ns["__builtins__"] = {"path":1}
1556 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1557 self.assertEqual(inspect.getclosurevars(f), expected)
1558
1559 def test_builtins_as_module(self):
1560 f, ns = self._private_globals()
1561 ns["__builtins__"] = os
1562 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1563 self.assertEqual(inspect.getclosurevars(f), expected)
1564
Nick Coghlan2f92e542012-06-23 19:39:55 +10001565
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001566class TestGetcallargsFunctions(unittest.TestCase):
1567
1568 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1569 locs = dict(locs or {}, func=func)
1570 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001571 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1572 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001573 self.assertEqual(r1, r2)
1574
1575 def assertEqualException(self, func, call_param_string, locs=None):
1576 locs = dict(locs or {}, func=func)
1577 try:
1578 eval('func(%s)' % call_param_string, None, locs)
1579 except Exception as e:
1580 ex1 = e
1581 else:
1582 self.fail('Exception not raised')
1583 try:
Pablo Galindoaee19f52019-05-16 21:08:15 +01001584 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1585 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001586 except Exception as e:
1587 ex2 = e
1588 else:
1589 self.fail('Exception not raised')
1590 self.assertIs(type(ex1), type(ex2))
1591 self.assertEqual(str(ex1), str(ex2))
1592 del ex1, ex2
1593
1594 def makeCallable(self, signature):
1595 """Create a function that returns its locals()"""
1596 code = "lambda %s: locals()"
1597 return eval(code % signature)
1598
1599 def test_plain(self):
1600 f = self.makeCallable('a, b=1')
1601 self.assertEqualCallArgs(f, '2')
1602 self.assertEqualCallArgs(f, '2, 3')
1603 self.assertEqualCallArgs(f, 'a=2')
1604 self.assertEqualCallArgs(f, 'b=3, a=2')
1605 self.assertEqualCallArgs(f, '2, b=3')
1606 # expand *iterable / **mapping
1607 self.assertEqualCallArgs(f, '*(2,)')
1608 self.assertEqualCallArgs(f, '*[2]')
1609 self.assertEqualCallArgs(f, '*(2, 3)')
1610 self.assertEqualCallArgs(f, '*[2, 3]')
1611 self.assertEqualCallArgs(f, '**{"a":2}')
1612 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1613 self.assertEqualCallArgs(f, '2, **{"b":3}')
1614 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1615 # expand UserList / UserDict
1616 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1617 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1618 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1619 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1620 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1621
1622 def test_varargs(self):
1623 f = self.makeCallable('a, b=1, *c')
1624 self.assertEqualCallArgs(f, '2')
1625 self.assertEqualCallArgs(f, '2, 3')
1626 self.assertEqualCallArgs(f, '2, 3, 4')
1627 self.assertEqualCallArgs(f, '*(2,3,4)')
1628 self.assertEqualCallArgs(f, '2, *[3,4]')
1629 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1630
1631 def test_varkw(self):
1632 f = self.makeCallable('a, b=1, **c')
1633 self.assertEqualCallArgs(f, 'a=2')
1634 self.assertEqualCallArgs(f, '2, b=3, c=4')
1635 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1636 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1637 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1638 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1639 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1640 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1641 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1642
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001643 def test_varkw_only(self):
1644 # issue11256:
1645 f = self.makeCallable('**c')
1646 self.assertEqualCallArgs(f, '')
1647 self.assertEqualCallArgs(f, 'a=1')
1648 self.assertEqualCallArgs(f, 'a=1, b=2')
1649 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1650 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1651 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1652
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001653 def test_keyword_only(self):
1654 f = self.makeCallable('a=3, *, c, d=2')
1655 self.assertEqualCallArgs(f, 'c=3')
1656 self.assertEqualCallArgs(f, 'c=3, a=3')
1657 self.assertEqualCallArgs(f, 'a=2, c=4')
1658 self.assertEqualCallArgs(f, '4, c=4')
1659 self.assertEqualException(f, '')
1660 self.assertEqualException(f, '3')
1661 self.assertEqualException(f, 'a=3')
1662 self.assertEqualException(f, 'd=4')
1663
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001664 f = self.makeCallable('*, c, d=2')
1665 self.assertEqualCallArgs(f, 'c=3')
1666 self.assertEqualCallArgs(f, 'c=3, d=4')
1667 self.assertEqualCallArgs(f, 'd=4, c=3')
1668
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001669 def test_multiple_features(self):
1670 f = self.makeCallable('a, b=2, *f, **g')
1671 self.assertEqualCallArgs(f, '2, 3, 7')
1672 self.assertEqualCallArgs(f, '2, 3, x=8')
1673 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1674 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1675 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1676 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1677 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1678 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1679 '(4,[5,6])]), **collections.UserDict('
1680 'y=9, z=10)')
1681
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001682 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1683 self.assertEqualCallArgs(f, '2, 3, x=8')
1684 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1685 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1686 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1687 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1688 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1689 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1690 '(4,[5,6])]), q=0, **collections.UserDict('
1691 'y=9, z=10)')
1692
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001693 def test_errors(self):
1694 f0 = self.makeCallable('')
1695 f1 = self.makeCallable('a, b')
1696 f2 = self.makeCallable('a, b=1')
1697 # f0 takes no arguments
1698 self.assertEqualException(f0, '1')
1699 self.assertEqualException(f0, 'x=1')
1700 self.assertEqualException(f0, '1,x=1')
1701 # f1 takes exactly 2 arguments
1702 self.assertEqualException(f1, '')
1703 self.assertEqualException(f1, '1')
1704 self.assertEqualException(f1, 'a=2')
1705 self.assertEqualException(f1, 'b=3')
1706 # f2 takes at least 1 argument
1707 self.assertEqualException(f2, '')
1708 self.assertEqualException(f2, 'b=3')
1709 for f in f1, f2:
1710 # f1/f2 takes exactly/at most 2 arguments
1711 self.assertEqualException(f, '2, 3, 4')
1712 self.assertEqualException(f, '1, 2, 3, a=1')
1713 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001714 # XXX: success of this one depends on dict order
1715 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001716 # f got an unexpected keyword argument
1717 self.assertEqualException(f, 'c=2')
1718 self.assertEqualException(f, '2, c=3')
1719 self.assertEqualException(f, '2, 3, c=4')
1720 self.assertEqualException(f, '2, c=4, b=3')
1721 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1722 # f got multiple values for keyword argument
1723 self.assertEqualException(f, '1, a=2')
1724 self.assertEqualException(f, '1, **{"a":2}')
1725 self.assertEqualException(f, '1, 2, b=3')
1726 # XXX: Python inconsistency
1727 # - for functions and bound methods: unexpected keyword 'c'
1728 # - for unbound methods: multiple values for keyword 'a'
1729 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001730 # issue11256:
1731 f3 = self.makeCallable('**c')
1732 self.assertEqualException(f3, '1, 2')
1733 self.assertEqualException(f3, '1, 2, a=1, b=2')
1734 f4 = self.makeCallable('*, a, b=0')
1735 self.assertEqualException(f3, '1, 2')
1736 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001737
Yury Selivanov875df202014-03-27 18:23:03 -04001738 # issue #20816: getcallargs() fails to iterate over non-existent
1739 # kwonlydefaults and raises a wrong TypeError
1740 def f5(*, a): pass
1741 with self.assertRaisesRegex(TypeError,
1742 'missing 1 required keyword-only'):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001743 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001744
1745
Yury Selivanovdccfa132014-03-27 18:42:52 -04001746 # issue20817:
1747 def f6(a, b, c):
1748 pass
1749 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001750 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001751
Dong-hee Naa9cab432018-05-30 00:04:08 +09001752 # bpo-33197
1753 with self.assertRaisesRegex(ValueError,
1754 'variadic keyword parameters cannot'
1755 ' have default values'):
1756 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1757 default=42)
1758 with self.assertRaisesRegex(ValueError,
1759 "value 5 is not a valid Parameter.kind"):
1760 inspect.Parameter("bar", kind=5, default=42)
1761
1762 with self.assertRaisesRegex(TypeError,
1763 'name must be a str, not a int'):
1764 inspect.Parameter(123, kind=4)
1765
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001766class TestGetcallargsMethods(TestGetcallargsFunctions):
1767
1768 def setUp(self):
1769 class Foo(object):
1770 pass
1771 self.cls = Foo
1772 self.inst = Foo()
1773
1774 def makeCallable(self, signature):
1775 assert 'self' not in signature
1776 mk = super(TestGetcallargsMethods, self).makeCallable
1777 self.cls.method = mk('self, ' + signature)
1778 return self.inst.method
1779
1780class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1781
1782 def makeCallable(self, signature):
1783 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1784 return self.cls.method
1785
1786 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1787 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1788 *self._getAssertEqualParams(func, call_params_string, locs))
1789
1790 def assertEqualException(self, func, call_params_string, locs=None):
1791 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1792 *self._getAssertEqualParams(func, call_params_string, locs))
1793
1794 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1795 assert 'inst' not in call_params_string
1796 locs = dict(locs or {}, inst=self.inst)
1797 return (func, 'inst,' + call_params_string, locs)
1798
Michael Foord95fc51d2010-11-20 15:07:30 +00001799
1800class TestGetattrStatic(unittest.TestCase):
1801
1802 def test_basic(self):
1803 class Thing(object):
1804 x = object()
1805
1806 thing = Thing()
1807 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1808 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1809 with self.assertRaises(AttributeError):
1810 inspect.getattr_static(thing, 'y')
1811
1812 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1813
1814 def test_inherited(self):
1815 class Thing(object):
1816 x = object()
1817 class OtherThing(Thing):
1818 pass
1819
1820 something = OtherThing()
1821 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1822
1823 def test_instance_attr(self):
1824 class Thing(object):
1825 x = 2
1826 def __init__(self, x):
1827 self.x = x
1828 thing = Thing(3)
1829 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1830 del thing.x
1831 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1832
1833 def test_property(self):
1834 class Thing(object):
1835 @property
1836 def x(self):
1837 raise AttributeError("I'm pretending not to exist")
1838 thing = Thing()
1839 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1840
Ezio Melotti75cbd732011-04-28 00:59:29 +03001841 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001842 class descriptor(object):
1843 def __get__(*_):
1844 raise AttributeError("I'm pretending not to exist")
1845 desc = descriptor()
1846 class Thing(object):
1847 x = desc
1848 thing = Thing()
1849 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1850
1851 def test_classAttribute(self):
1852 class Thing(object):
1853 x = object()
1854
1855 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1856
Ethan Furmane03ea372013-09-25 07:14:41 -07001857 def test_classVirtualAttribute(self):
1858 class Thing(object):
1859 @types.DynamicClassAttribute
1860 def x(self):
1861 return self._x
1862 _x = object()
1863
1864 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1865
Michael Foord95fc51d2010-11-20 15:07:30 +00001866 def test_inherited_classattribute(self):
1867 class Thing(object):
1868 x = object()
1869 class OtherThing(Thing):
1870 pass
1871
1872 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1873
1874 def test_slots(self):
1875 class Thing(object):
1876 y = 'bar'
1877 __slots__ = ['x']
1878 def __init__(self):
1879 self.x = 'foo'
1880 thing = Thing()
1881 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1882 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1883
1884 del thing.x
1885 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1886
1887 def test_metaclass(self):
1888 class meta(type):
1889 attr = 'foo'
1890 class Thing(object, metaclass=meta):
1891 pass
1892 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1893
1894 class sub(meta):
1895 pass
1896 class OtherThing(object, metaclass=sub):
1897 x = 3
1898 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1899
1900 class OtherOtherThing(OtherThing):
1901 pass
1902 # this test is odd, but it was added as it exposed a bug
1903 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1904
1905 def test_no_dict_no_slots(self):
1906 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1907 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1908
1909 def test_no_dict_no_slots_instance_member(self):
1910 # returns descriptor
Inada Naokifb786922021-04-06 11:18:41 +09001911 with open(__file__, encoding='utf-8') as handle:
Michael Foord95fc51d2010-11-20 15:07:30 +00001912 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1913
1914 def test_inherited_slots(self):
1915 # returns descriptor
1916 class Thing(object):
1917 __slots__ = ['x']
1918 def __init__(self):
1919 self.x = 'foo'
1920
1921 class OtherThing(Thing):
1922 pass
1923 # it would be nice if this worked...
1924 # we get the descriptor instead of the instance attribute
1925 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1926
1927 def test_descriptor(self):
1928 class descriptor(object):
1929 def __get__(self, instance, owner):
1930 return 3
1931 class Foo(object):
1932 d = descriptor()
1933
1934 foo = Foo()
1935
1936 # for a non data descriptor we return the instance attribute
1937 foo.__dict__['d'] = 1
1938 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1939
Mike53f7a7c2017-12-14 14:04:53 +03001940 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001941 # descriptor
1942 descriptor.__set__ = lambda s, i, v: None
1943 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1944
1945
1946 def test_metaclass_with_descriptor(self):
1947 class descriptor(object):
1948 def __get__(self, instance, owner):
1949 return 3
1950 class meta(type):
1951 d = descriptor()
1952 class Thing(object, metaclass=meta):
1953 pass
1954 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1955
1956
Michael Foordcc7ebb82010-11-20 16:20:16 +00001957 def test_class_as_property(self):
1958 class Base(object):
1959 foo = 3
1960
1961 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001962 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001963 @property
1964 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001965 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001966 return object
1967
Michael Foord35184ed2010-11-20 16:58:30 +00001968 instance = Something()
1969 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1970 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001971 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1972
Michael Foorde5162652010-11-20 16:40:44 +00001973 def test_mro_as_property(self):
1974 class Meta(type):
1975 @property
1976 def __mro__(self):
1977 return (object,)
1978
1979 class Base(object):
1980 foo = 3
1981
1982 class Something(Base, metaclass=Meta):
1983 pass
1984
1985 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1986 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1987
Michael Foorddcebe0f2011-03-15 19:20:44 -04001988 def test_dict_as_property(self):
1989 test = self
1990 test.called = False
1991
1992 class Foo(dict):
1993 a = 3
1994 @property
1995 def __dict__(self):
1996 test.called = True
1997 return {}
1998
1999 foo = Foo()
2000 foo.a = 4
2001 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
2002 self.assertFalse(test.called)
2003
2004 def test_custom_object_dict(self):
2005 test = self
2006 test.called = False
2007
2008 class Custom(dict):
2009 def get(self, key, default=None):
2010 test.called = True
2011 super().get(key, default)
2012
2013 class Foo(object):
2014 a = 3
2015 foo = Foo()
2016 foo.__dict__ = Custom()
2017 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
2018 self.assertFalse(test.called)
2019
2020 def test_metaclass_dict_as_property(self):
2021 class Meta(type):
2022 @property
2023 def __dict__(self):
2024 self.executed = True
2025
2026 class Thing(metaclass=Meta):
2027 executed = False
2028
2029 def __init__(self):
2030 self.spam = 42
2031
2032 instance = Thing()
2033 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
2034 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00002035
Michael Foorda51623b2011-12-18 22:01:40 +00002036 def test_module(self):
2037 sentinel = object()
2038 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
2039 sentinel)
2040
Michael Foord3ba95f82011-12-22 01:13:37 +00002041 def test_metaclass_with_metaclass_with_dict_as_property(self):
2042 class MetaMeta(type):
2043 @property
2044 def __dict__(self):
2045 self.executed = True
2046 return dict(spam=42)
2047
2048 class Meta(type, metaclass=MetaMeta):
2049 executed = False
2050
2051 class Thing(metaclass=Meta):
2052 pass
2053
2054 with self.assertRaises(AttributeError):
2055 inspect.getattr_static(Thing, "spam")
2056 self.assertFalse(Thing.executed)
2057
Nick Coghlane0f04652010-11-21 03:44:04 +00002058class TestGetGeneratorState(unittest.TestCase):
2059
2060 def setUp(self):
2061 def number_generator():
2062 for number in range(5):
2063 yield number
2064 self.generator = number_generator()
2065
2066 def _generatorstate(self):
2067 return inspect.getgeneratorstate(self.generator)
2068
2069 def test_created(self):
2070 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
2071
2072 def test_suspended(self):
2073 next(self.generator)
2074 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
2075
2076 def test_closed_after_exhaustion(self):
2077 for i in self.generator:
2078 pass
2079 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
2080
2081 def test_closed_after_immediate_exception(self):
2082 with self.assertRaises(RuntimeError):
2083 self.generator.throw(RuntimeError)
2084 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
2085
2086 def test_running(self):
2087 # As mentioned on issue #10220, checking for the RUNNING state only
2088 # makes sense inside the generator itself.
2089 # The following generator checks for this by using the closure's
2090 # reference to self and the generator state checking helper method
2091 def running_check_generator():
2092 for number in range(5):
2093 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
2094 yield number
2095 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
2096 self.generator = running_check_generator()
2097 # Running up to the first yield
2098 next(self.generator)
2099 # Running after the first yield
2100 next(self.generator)
2101
Nick Coghlan7921b9f2010-11-30 06:36:04 +00002102 def test_easy_debugging(self):
2103 # repr() and str() of a generator state should contain the state name
2104 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
2105 for name in names:
2106 state = getattr(inspect, name)
2107 self.assertIn(name, repr(state))
2108 self.assertIn(name, str(state))
2109
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10002110 def test_getgeneratorlocals(self):
2111 def each(lst, a=None):
2112 b=(1, 2, 3)
2113 for v in lst:
2114 if v == 3:
2115 c = 12
2116 yield v
2117
2118 numbers = each([1, 2, 3])
2119 self.assertEqual(inspect.getgeneratorlocals(numbers),
2120 {'a': None, 'lst': [1, 2, 3]})
2121 next(numbers)
2122 self.assertEqual(inspect.getgeneratorlocals(numbers),
2123 {'a': None, 'lst': [1, 2, 3], 'v': 1,
2124 'b': (1, 2, 3)})
2125 next(numbers)
2126 self.assertEqual(inspect.getgeneratorlocals(numbers),
2127 {'a': None, 'lst': [1, 2, 3], 'v': 2,
2128 'b': (1, 2, 3)})
2129 next(numbers)
2130 self.assertEqual(inspect.getgeneratorlocals(numbers),
2131 {'a': None, 'lst': [1, 2, 3], 'v': 3,
2132 'b': (1, 2, 3), 'c': 12})
2133 try:
2134 next(numbers)
2135 except StopIteration:
2136 pass
2137 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
2138
2139 def test_getgeneratorlocals_empty(self):
2140 def yield_one():
2141 yield 1
2142 one = yield_one()
2143 self.assertEqual(inspect.getgeneratorlocals(one), {})
2144 try:
2145 next(one)
2146 except StopIteration:
2147 pass
2148 self.assertEqual(inspect.getgeneratorlocals(one), {})
2149
2150 def test_getgeneratorlocals_error(self):
2151 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
2152 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
2153 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
2154 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
2155
Nick Coghlane0f04652010-11-21 03:44:04 +00002156
Yury Selivanov5376ba92015-06-22 12:19:30 -04002157class TestGetCoroutineState(unittest.TestCase):
2158
2159 def setUp(self):
2160 @types.coroutine
2161 def number_coroutine():
2162 for number in range(5):
2163 yield number
2164 async def coroutine():
2165 await number_coroutine()
2166 self.coroutine = coroutine()
2167
2168 def tearDown(self):
2169 self.coroutine.close()
2170
2171 def _coroutinestate(self):
2172 return inspect.getcoroutinestate(self.coroutine)
2173
2174 def test_created(self):
2175 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
2176
2177 def test_suspended(self):
2178 self.coroutine.send(None)
2179 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
2180
2181 def test_closed_after_exhaustion(self):
2182 while True:
2183 try:
2184 self.coroutine.send(None)
2185 except StopIteration:
2186 break
2187
2188 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2189
2190 def test_closed_after_immediate_exception(self):
2191 with self.assertRaises(RuntimeError):
2192 self.coroutine.throw(RuntimeError)
2193 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2194
2195 def test_easy_debugging(self):
2196 # repr() and str() of a coroutine state should contain the state name
2197 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2198 for name in names:
2199 state = getattr(inspect, name)
2200 self.assertIn(name, repr(state))
2201 self.assertIn(name, str(state))
2202
2203 def test_getcoroutinelocals(self):
2204 @types.coroutine
2205 def gencoro():
2206 yield
2207
2208 gencoro = gencoro()
2209 async def func(a=None):
2210 b = 'spam'
2211 await gencoro
2212
2213 coro = func()
2214 self.assertEqual(inspect.getcoroutinelocals(coro),
2215 {'a': None, 'gencoro': gencoro})
2216 coro.send(None)
2217 self.assertEqual(inspect.getcoroutinelocals(coro),
2218 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2219
2220
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002221class MySignature(inspect.Signature):
2222 # Top-level to make it picklable;
2223 # used in test_signature_object_pickle
2224 pass
2225
2226class MyParameter(inspect.Parameter):
2227 # Top-level to make it picklable;
2228 # used in test_signature_object_pickle
2229 pass
2230
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002231
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002232
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002233class TestSignatureObject(unittest.TestCase):
2234 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002235 def signature(func, **kw):
2236 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002237 return (tuple((param.name,
2238 (... if param.default is param.empty else param.default),
2239 (... if param.annotation is param.empty
2240 else param.annotation),
2241 str(param.kind).lower())
2242 for param in sig.parameters.values()),
2243 (... if sig.return_annotation is sig.empty
2244 else sig.return_annotation))
2245
2246 def test_signature_object(self):
2247 S = inspect.Signature
2248 P = inspect.Parameter
2249
2250 self.assertEqual(str(S()), '()')
Jens Reidel611836a2020-03-18 03:22:46 +01002251 self.assertEqual(repr(S().parameters), 'mappingproxy(OrderedDict())')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002252
Yury Selivanov07a9e452014-01-29 10:58:16 -05002253 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002254 pass
2255 sig = inspect.signature(test)
2256 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002257 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002258 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002259 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002260 args = sig.parameters['args']
2261 ko = sig.parameters['ko']
2262 kwargs = sig.parameters['kwargs']
2263
2264 S((po, pk, args, ko, kwargs))
2265
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002266 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002267 S((pk, po, args, ko, kwargs))
2268
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002269 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002270 S((po, args, pk, ko, kwargs))
2271
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002272 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002273 S((args, po, pk, ko, kwargs))
2274
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002275 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002276 S((po, pk, args, kwargs, ko))
2277
2278 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002279 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002280 S((po, pk, args, kwargs2, ko))
2281
Yury Selivanov07a9e452014-01-29 10:58:16 -05002282 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2283 S((pod, po))
2284
2285 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2286 S((po, pkd, pk))
2287
2288 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2289 S((pkd, pk))
2290
Yury Selivanov374375d2014-03-27 12:41:53 -04002291 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002292 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002293
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002294 def test_signature_object_pickle(self):
2295 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2296 foo_partial = functools.partial(foo, a=1)
2297
2298 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002299
2300 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2301 with self.subTest(pickle_ver=ver, subclass=False):
2302 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2303 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002304
2305 # Test that basic sub-classing works
2306 sig = inspect.signature(foo)
2307 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2308 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2309 mysig = MySignature().replace(parameters=myparams.values(),
2310 return_annotation=sig.return_annotation)
2311 self.assertTrue(isinstance(mysig, MySignature))
2312 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2313
2314 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2315 with self.subTest(pickle_ver=ver, subclass=True):
2316 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2317 self.assertEqual(mysig, sig_pickled)
2318 self.assertTrue(isinstance(sig_pickled, MySignature))
2319 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2320 MyParameter))
2321
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002322 def test_signature_immutability(self):
2323 def test(a):
2324 pass
2325 sig = inspect.signature(test)
2326
2327 with self.assertRaises(AttributeError):
2328 sig.foo = 'bar'
2329
2330 with self.assertRaises(TypeError):
2331 sig.parameters['a'] = None
2332
2333 def test_signature_on_noarg(self):
2334 def test():
2335 pass
2336 self.assertEqual(self.signature(test), ((), ...))
2337
2338 def test_signature_on_wargs(self):
2339 def test(a, b:'foo') -> 123:
2340 pass
2341 self.assertEqual(self.signature(test),
2342 ((('a', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002343 ('b', ..., 'foo', "positional_or_keyword")),
2344 123))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002345
2346 def test_signature_on_wkwonly(self):
2347 def test(*, a:float, b:str) -> int:
2348 pass
2349 self.assertEqual(self.signature(test),
2350 ((('a', ..., float, "keyword_only"),
2351 ('b', ..., str, "keyword_only")),
2352 int))
2353
2354 def test_signature_on_complex_args(self):
2355 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2356 pass
2357 self.assertEqual(self.signature(test),
2358 ((('a', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002359 ('b', 10, 'foo', "positional_or_keyword"),
2360 ('args', ..., 'bar', "var_positional"),
2361 ('spam', ..., 'baz', "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002362 ('ham', 123, ..., "keyword_only"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002363 ('kwargs', ..., int, "var_keyword")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002364 ...))
2365
Dong-hee Na378d7062017-05-18 04:00:51 +09002366 def test_signature_without_self(self):
2367 def test_args_only(*args): # NOQA
2368 pass
2369
2370 def test_args_kwargs_only(*args, **kwargs): # NOQA
2371 pass
2372
2373 class A:
2374 @classmethod
2375 def test_classmethod(*args): # NOQA
2376 pass
2377
2378 @staticmethod
2379 def test_staticmethod(*args): # NOQA
2380 pass
2381
2382 f1 = functools.partialmethod((test_classmethod), 1)
2383 f2 = functools.partialmethod((test_args_only), 1)
2384 f3 = functools.partialmethod((test_staticmethod), 1)
2385 f4 = functools.partialmethod((test_args_kwargs_only),1)
2386
2387 self.assertEqual(self.signature(test_args_only),
2388 ((('args', ..., ..., 'var_positional'),), ...))
2389 self.assertEqual(self.signature(test_args_kwargs_only),
2390 ((('args', ..., ..., 'var_positional'),
2391 ('kwargs', ..., ..., 'var_keyword')), ...))
2392 self.assertEqual(self.signature(A.f1),
2393 ((('args', ..., ..., 'var_positional'),), ...))
2394 self.assertEqual(self.signature(A.f2),
2395 ((('args', ..., ..., 'var_positional'),), ...))
2396 self.assertEqual(self.signature(A.f3),
2397 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002398 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002399 ((('args', ..., ..., 'var_positional'),
2400 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002401 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002402 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2403 "Signature information for builtins requires docstrings")
2404 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002405 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002406
Larry Hastings5c661892014-01-24 06:17:25 -08002407 def test_unbound_method(o):
2408 """Use this to test unbound methods (things that should have a self)"""
2409 signature = inspect.signature(o)
2410 self.assertTrue(isinstance(signature, inspect.Signature))
2411 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2412 return signature
2413
2414 def test_callable(o):
2415 """Use this to test bound methods or normal callables (things that don't expect self)"""
2416 signature = inspect.signature(o)
2417 self.assertTrue(isinstance(signature, inspect.Signature))
2418 if signature.parameters:
2419 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2420 return signature
2421
2422 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002423 def p(name): return signature.parameters[name].default
2424 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002425 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002426 self.assertEqual(p('d'), 3.14)
2427 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002428 self.assertEqual(p('n'), None)
2429 self.assertEqual(p('t'), True)
2430 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002431 self.assertEqual(p('local'), 3)
2432 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002433 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002434
Larry Hastings5c661892014-01-24 06:17:25 -08002435 test_callable(object)
2436
2437 # normal method
2438 # (PyMethodDescr_Type, "method_descriptor")
2439 test_unbound_method(_pickle.Pickler.dump)
2440 d = _pickle.Pickler(io.StringIO())
2441 test_callable(d.dump)
2442
2443 # static method
Serhiy Storchaka279f4462019-09-14 12:24:05 +03002444 test_callable(bytes.maketrans)
2445 test_callable(b'abc'.maketrans)
Larry Hastings5c661892014-01-24 06:17:25 -08002446
2447 # class method
2448 test_callable(dict.fromkeys)
2449 test_callable({}.fromkeys)
2450
2451 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2452 test_unbound_method(type.__call__)
2453 test_unbound_method(int.__add__)
2454 test_callable((3).__add__)
2455
2456 # _PyMethodWrapper_Type
2457 # support for 'method-wrapper'
2458 test_callable(min.__call__)
2459
Larry Hastings2623c8c2014-02-08 22:15:29 -08002460 # This doesn't work now.
2461 # (We don't have a valid signature for "type" in 3.4)
2462 with self.assertRaisesRegex(ValueError, "no signature found"):
2463 class ThisWorksNow:
2464 __call__ = type
2465 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002466
Yury Selivanov056e2652014-03-02 12:25:27 -05002467 # Regression test for issue #20786
2468 test_unbound_method(dict.__delitem__)
2469 test_unbound_method(property.__delete__)
2470
Zachary Ware8ef887c2015-04-13 18:22:35 -05002471 # Regression test for issue #20586
2472 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2473
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002474 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002475 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2476 "Signature information for builtins requires docstrings")
2477 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002478 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002479 func = _testcapi.docstring_with_signature_with_defaults
2480
2481 def decorator(func):
2482 @functools.wraps(func)
2483 def wrapper(*args, **kwargs) -> int:
2484 return func(*args, **kwargs)
2485 return wrapper
2486
2487 decorated_func = decorator(func)
2488
2489 self.assertEqual(inspect.signature(func),
2490 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002491
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002492 def wrapper_like(*args, **kwargs) -> int: pass
2493 self.assertEqual(inspect.signature(decorated_func,
2494 follow_wrapped=False),
2495 inspect.signature(wrapper_like))
2496
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002497 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002498 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002499 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002500 with self.assertRaisesRegex(ValueError,
2501 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002502 inspect.signature(_testcapi.docstring_no_signature)
2503
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002504 with self.assertRaisesRegex(ValueError,
2505 'no signature found for builtin'):
2506 inspect.signature(str)
2507
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002508 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002509 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002510 inspect.signature(42)
2511
Yury Selivanov63da7c72014-01-31 14:48:37 -05002512 def test_signature_from_functionlike_object(self):
2513 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2514 pass
2515
2516 class funclike:
2517 # Has to be callable, and have correct
2518 # __code__, __annotations__, __defaults__, __name__,
2519 # and __kwdefaults__ attributes
2520
2521 def __init__(self, func):
2522 self.__name__ = func.__name__
2523 self.__code__ = func.__code__
2524 self.__annotations__ = func.__annotations__
2525 self.__defaults__ = func.__defaults__
2526 self.__kwdefaults__ = func.__kwdefaults__
2527 self.func = func
2528
2529 def __call__(self, *args, **kwargs):
2530 return self.func(*args, **kwargs)
2531
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002532 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002533
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002534 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002535 self.assertEqual(sig_funclike, sig_func)
2536
2537 sig_funclike = inspect.signature(funclike(func))
2538 self.assertEqual(sig_funclike, sig_func)
2539
2540 # If object is not a duck type of function, then
2541 # signature will try to get a signature for its '__call__'
2542 # method
2543 fl = funclike(func)
2544 del fl.__defaults__
2545 self.assertEqual(self.signature(fl),
2546 ((('args', ..., ..., "var_positional"),
2547 ('kwargs', ..., ..., "var_keyword")),
2548 ...))
2549
Yury Selivanova773de02014-02-21 18:30:53 -05002550 # Test with cython-like builtins:
2551 _orig_isdesc = inspect.ismethoddescriptor
2552 def _isdesc(obj):
2553 if hasattr(obj, '_builtinmock'):
2554 return True
2555 return _orig_isdesc(obj)
2556
2557 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2558 builtin_func = funclike(func)
2559 # Make sure that our mock setup is working
2560 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2561 builtin_func._builtinmock = True
2562 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2563 self.assertEqual(inspect.signature(builtin_func), sig_func)
2564
Yury Selivanov63da7c72014-01-31 14:48:37 -05002565 def test_signature_functionlike_class(self):
2566 # We only want to duck type function-like objects,
2567 # not classes.
2568
2569 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2570 pass
2571
2572 class funclike:
2573 def __init__(self, marker):
2574 pass
2575
2576 __name__ = func.__name__
2577 __code__ = func.__code__
2578 __annotations__ = func.__annotations__
2579 __defaults__ = func.__defaults__
2580 __kwdefaults__ = func.__kwdefaults__
2581
Yury Selivanov63da7c72014-01-31 14:48:37 -05002582 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2583
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002584 def test_signature_on_method(self):
2585 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002586 def __init__(*args):
2587 pass
2588 def m1(self, arg1, arg2=1) -> int:
2589 pass
2590 def m2(*args):
2591 pass
2592 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002593 pass
2594
Yury Selivanov62560fb2014-01-28 12:26:24 -05002595 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002596 ((('arg1', ..., ..., "positional_or_keyword"),
2597 ('arg2', 1, ..., "positional_or_keyword")),
2598 int))
2599
Yury Selivanov62560fb2014-01-28 12:26:24 -05002600 self.assertEqual(self.signature(Test().m2),
2601 ((('args', ..., ..., "var_positional"),),
2602 ...))
2603
2604 self.assertEqual(self.signature(Test),
2605 ((('args', ..., ..., "var_positional"),),
2606 ...))
2607
2608 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2609 self.signature(Test())
2610
Yury Selivanov46c759d2015-05-27 21:56:53 -04002611 def test_signature_wrapped_bound_method(self):
2612 # Issue 24298
2613 class Test:
2614 def m1(self, arg1, arg2=1) -> int:
2615 pass
2616 @functools.wraps(Test().m1)
2617 def m1d(*args, **kwargs):
2618 pass
2619 self.assertEqual(self.signature(m1d),
2620 ((('arg1', ..., ..., "positional_or_keyword"),
2621 ('arg2', 1, ..., "positional_or_keyword")),
2622 int))
2623
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002624 def test_signature_on_classmethod(self):
2625 class Test:
2626 @classmethod
2627 def foo(cls, arg1, *, arg2=1):
2628 pass
2629
2630 meth = Test().foo
2631 self.assertEqual(self.signature(meth),
2632 ((('arg1', ..., ..., "positional_or_keyword"),
2633 ('arg2', 1, ..., "keyword_only")),
2634 ...))
2635
2636 meth = Test.foo
2637 self.assertEqual(self.signature(meth),
2638 ((('arg1', ..., ..., "positional_or_keyword"),
2639 ('arg2', 1, ..., "keyword_only")),
2640 ...))
2641
2642 def test_signature_on_staticmethod(self):
2643 class Test:
2644 @staticmethod
2645 def foo(cls, *, arg):
2646 pass
2647
2648 meth = Test().foo
2649 self.assertEqual(self.signature(meth),
2650 ((('cls', ..., ..., "positional_or_keyword"),
2651 ('arg', ..., ..., "keyword_only")),
2652 ...))
2653
2654 meth = Test.foo
2655 self.assertEqual(self.signature(meth),
2656 ((('cls', ..., ..., "positional_or_keyword"),
2657 ('arg', ..., ..., "keyword_only")),
2658 ...))
2659
2660 def test_signature_on_partial(self):
2661 from functools import partial
2662
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002663 Parameter = inspect.Parameter
2664
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002665 def test():
2666 pass
2667
2668 self.assertEqual(self.signature(partial(test)), ((), ...))
2669
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002670 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002671 inspect.signature(partial(test, 1))
2672
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002673 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002674 inspect.signature(partial(test, a=1))
2675
2676 def test(a, b, *, c, d):
2677 pass
2678
2679 self.assertEqual(self.signature(partial(test)),
2680 ((('a', ..., ..., "positional_or_keyword"),
2681 ('b', ..., ..., "positional_or_keyword"),
2682 ('c', ..., ..., "keyword_only"),
2683 ('d', ..., ..., "keyword_only")),
2684 ...))
2685
2686 self.assertEqual(self.signature(partial(test, 1)),
2687 ((('b', ..., ..., "positional_or_keyword"),
2688 ('c', ..., ..., "keyword_only"),
2689 ('d', ..., ..., "keyword_only")),
2690 ...))
2691
2692 self.assertEqual(self.signature(partial(test, 1, c=2)),
2693 ((('b', ..., ..., "positional_or_keyword"),
2694 ('c', 2, ..., "keyword_only"),
2695 ('d', ..., ..., "keyword_only")),
2696 ...))
2697
2698 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2699 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002700 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002701 ('c', 2, ..., "keyword_only"),
2702 ('d', ..., ..., "keyword_only")),
2703 ...))
2704
2705 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002706 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002707 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002708 ('d', ..., ..., "keyword_only")),
2709 ...))
2710
2711 self.assertEqual(self.signature(partial(test, a=1)),
2712 ((('a', 1, ..., "keyword_only"),
2713 ('b', ..., ..., "keyword_only"),
2714 ('c', ..., ..., "keyword_only"),
2715 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002716 ...))
2717
2718 def test(a, *args, b, **kwargs):
2719 pass
2720
2721 self.assertEqual(self.signature(partial(test, 1)),
2722 ((('args', ..., ..., "var_positional"),
2723 ('b', ..., ..., "keyword_only"),
2724 ('kwargs', ..., ..., "var_keyword")),
2725 ...))
2726
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002727 self.assertEqual(self.signature(partial(test, a=1)),
2728 ((('a', 1, ..., "keyword_only"),
2729 ('b', ..., ..., "keyword_only"),
2730 ('kwargs', ..., ..., "var_keyword")),
2731 ...))
2732
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002733 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2734 ((('args', ..., ..., "var_positional"),
2735 ('b', ..., ..., "keyword_only"),
2736 ('kwargs', ..., ..., "var_keyword")),
2737 ...))
2738
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002739 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2740 ((('args', ..., ..., "var_positional"),
2741 ('b', ..., ..., "keyword_only"),
2742 ('kwargs', ..., ..., "var_keyword")),
2743 ...))
2744
2745 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2746 ((('args', ..., ..., "var_positional"),
2747 ('b', 0, ..., "keyword_only"),
2748 ('kwargs', ..., ..., "var_keyword")),
2749 ...))
2750
2751 self.assertEqual(self.signature(partial(test, b=0)),
2752 ((('a', ..., ..., "positional_or_keyword"),
2753 ('args', ..., ..., "var_positional"),
2754 ('b', 0, ..., "keyword_only"),
2755 ('kwargs', ..., ..., "var_keyword")),
2756 ...))
2757
2758 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2759 ((('a', ..., ..., "positional_or_keyword"),
2760 ('args', ..., ..., "var_positional"),
2761 ('b', 0, ..., "keyword_only"),
2762 ('kwargs', ..., ..., "var_keyword")),
2763 ...))
2764
2765 def test(a, b, c:int) -> 42:
2766 pass
2767
2768 sig = test.__signature__ = inspect.signature(test)
2769
2770 self.assertEqual(self.signature(partial(partial(test, 1))),
2771 ((('b', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002772 ('c', ..., int, "positional_or_keyword")),
2773 42))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002774
2775 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002776 ((('c', ..., int, "positional_or_keyword"),),
2777 42))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002778
2779 psig = inspect.signature(partial(partial(test, 1), 2))
2780
2781 def foo(a):
2782 return a
2783 _foo = partial(partial(foo, a=10), a=20)
2784 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002785 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002786 ...))
2787 # check that we don't have any side-effects in signature(),
2788 # and the partial object is still functioning
2789 self.assertEqual(_foo(), 20)
2790
2791 def foo(a, b, c):
2792 return a, b, c
2793 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002794
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002795 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002796 ((('b', 30, ..., "keyword_only"),
2797 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002798 ...))
2799 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002800
2801 def foo(a, b, c, *, d):
2802 return a, b, c, d
2803 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2804 self.assertEqual(self.signature(_foo),
2805 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002806 ('b', 10, ..., "keyword_only"),
2807 ('c', 20, ..., "keyword_only"),
2808 ('d', 30, ..., "keyword_only"),
2809 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002810 ...))
2811 ba = inspect.signature(_foo).bind(a=200, b=11)
2812 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2813
2814 def foo(a=1, b=2, c=3):
2815 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002816 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2817
2818 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002819 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002820
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002821 ba = inspect.signature(_foo).bind(11, 12)
2822 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002823
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002824 ba = inspect.signature(_foo).bind(11, b=12)
2825 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002826
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002827 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002828 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2829
2830 _foo = partial(_foo, b=10, c=20)
2831 ba = inspect.signature(_foo).bind(12)
2832 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2833
2834
2835 def foo(a, b, c, d, **kwargs):
2836 pass
2837 sig = inspect.signature(foo)
2838 params = sig.parameters.copy()
2839 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2840 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2841 foo.__signature__ = inspect.Signature(params.values())
2842 sig = inspect.signature(foo)
2843 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2844
2845 self.assertEqual(self.signature(partial(foo, 1)),
2846 ((('b', ..., ..., 'positional_only'),
2847 ('c', ..., ..., 'positional_or_keyword'),
2848 ('d', ..., ..., 'positional_or_keyword'),
2849 ('kwargs', ..., ..., 'var_keyword')),
2850 ...))
2851
2852 self.assertEqual(self.signature(partial(foo, 1, 2)),
2853 ((('c', ..., ..., 'positional_or_keyword'),
2854 ('d', ..., ..., 'positional_or_keyword'),
2855 ('kwargs', ..., ..., 'var_keyword')),
2856 ...))
2857
2858 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2859 ((('d', ..., ..., 'positional_or_keyword'),
2860 ('kwargs', ..., ..., 'var_keyword')),
2861 ...))
2862
2863 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2864 ((('c', 3, ..., 'keyword_only'),
2865 ('d', ..., ..., 'keyword_only'),
2866 ('kwargs', ..., ..., 'var_keyword')),
2867 ...))
2868
2869 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2870 ((('b', ..., ..., 'positional_only'),
2871 ('c', 3, ..., 'keyword_only'),
2872 ('d', ..., ..., 'keyword_only'),
2873 ('kwargs', ..., ..., 'var_keyword')),
2874 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002875
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002876 def test_signature_on_partialmethod(self):
2877 from functools import partialmethod
2878
2879 class Spam:
2880 def test():
2881 pass
2882 ham = partialmethod(test)
2883
2884 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2885 inspect.signature(Spam.ham)
2886
2887 class Spam:
2888 def test(it, a, *, c) -> 'spam':
2889 pass
2890 ham = partialmethod(test, c=1)
2891
larryhastings74613a42021-04-29 21:16:28 -07002892 self.assertEqual(self.signature(Spam.ham, eval_str=False),
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002893 ((('it', ..., ..., 'positional_or_keyword'),
2894 ('a', ..., ..., 'positional_or_keyword'),
2895 ('c', 1, ..., 'keyword_only')),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002896 'spam'))
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002897
larryhastings74613a42021-04-29 21:16:28 -07002898 self.assertEqual(self.signature(Spam().ham, eval_str=False),
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002899 ((('a', ..., ..., 'positional_or_keyword'),
2900 ('c', 1, ..., 'keyword_only')),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002901 'spam'))
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002902
Yury Selivanov8a387212018-03-06 12:59:45 -05002903 class Spam:
2904 def test(self: 'anno', x):
2905 pass
2906
2907 g = partialmethod(test, 1)
2908
larryhastings74613a42021-04-29 21:16:28 -07002909 self.assertEqual(self.signature(Spam.g, eval_str=False),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002910 ((('self', ..., 'anno', 'positional_or_keyword'),),
Yury Selivanov8a387212018-03-06 12:59:45 -05002911 ...))
2912
Yury Selivanov0486f812014-01-29 12:18:59 -05002913 def test_signature_on_fake_partialmethod(self):
2914 def foo(a): pass
2915 foo._partialmethod = 'spam'
2916 self.assertEqual(str(inspect.signature(foo)), '(a)')
2917
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002918 def test_signature_on_decorated(self):
2919 import functools
2920
2921 def decorator(func):
2922 @functools.wraps(func)
2923 def wrapper(*args, **kwargs) -> int:
2924 return func(*args, **kwargs)
2925 return wrapper
2926
2927 class Foo:
2928 @decorator
2929 def bar(self, a, b):
2930 pass
2931
2932 self.assertEqual(self.signature(Foo.bar),
2933 ((('self', ..., ..., "positional_or_keyword"),
2934 ('a', ..., ..., "positional_or_keyword"),
2935 ('b', ..., ..., "positional_or_keyword")),
2936 ...))
2937
2938 self.assertEqual(self.signature(Foo().bar),
2939 ((('a', ..., ..., "positional_or_keyword"),
2940 ('b', ..., ..., "positional_or_keyword")),
2941 ...))
2942
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002943 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2944 ((('args', ..., ..., "var_positional"),
2945 ('kwargs', ..., ..., "var_keyword")),
2946 ...)) # functools.wraps will copy __annotations__
2947 # from "func" to "wrapper", hence no
2948 # return_annotation
2949
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002950 # Test that we handle method wrappers correctly
2951 def decorator(func):
2952 @functools.wraps(func)
2953 def wrapper(*args, **kwargs) -> int:
2954 return func(42, *args, **kwargs)
2955 sig = inspect.signature(func)
2956 new_params = tuple(sig.parameters.values())[1:]
2957 wrapper.__signature__ = sig.replace(parameters=new_params)
2958 return wrapper
2959
2960 class Foo:
2961 @decorator
2962 def __call__(self, a, b):
2963 pass
2964
2965 self.assertEqual(self.signature(Foo.__call__),
2966 ((('a', ..., ..., "positional_or_keyword"),
2967 ('b', ..., ..., "positional_or_keyword")),
2968 ...))
2969
2970 self.assertEqual(self.signature(Foo().__call__),
2971 ((('b', ..., ..., "positional_or_keyword"),),
2972 ...))
2973
Nick Coghlane8c45d62013-07-28 20:00:01 +10002974 # Test we handle __signature__ partway down the wrapper stack
2975 def wrapped_foo_call():
2976 pass
2977 wrapped_foo_call.__wrapped__ = Foo.__call__
2978
2979 self.assertEqual(self.signature(wrapped_foo_call),
2980 ((('a', ..., ..., "positional_or_keyword"),
2981 ('b', ..., ..., "positional_or_keyword")),
2982 ...))
2983
2984
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002985 def test_signature_on_class(self):
2986 class C:
2987 def __init__(self, a):
2988 pass
2989
2990 self.assertEqual(self.signature(C),
2991 ((('a', ..., ..., "positional_or_keyword"),),
2992 ...))
2993
2994 class CM(type):
2995 def __call__(cls, a):
2996 pass
2997 class C(metaclass=CM):
2998 def __init__(self, b):
2999 pass
3000
3001 self.assertEqual(self.signature(C),
3002 ((('a', ..., ..., "positional_or_keyword"),),
3003 ...))
3004
3005 class CM(type):
3006 def __new__(mcls, name, bases, dct, *, foo=1):
3007 return super().__new__(mcls, name, bases, dct)
3008 class C(metaclass=CM):
3009 def __init__(self, b):
3010 pass
3011
3012 self.assertEqual(self.signature(C),
3013 ((('b', ..., ..., "positional_or_keyword"),),
3014 ...))
3015
3016 self.assertEqual(self.signature(CM),
3017 ((('name', ..., ..., "positional_or_keyword"),
3018 ('bases', ..., ..., "positional_or_keyword"),
3019 ('dct', ..., ..., "positional_or_keyword"),
3020 ('foo', 1, ..., "keyword_only")),
3021 ...))
3022
3023 class CMM(type):
3024 def __new__(mcls, name, bases, dct, *, foo=1):
3025 return super().__new__(mcls, name, bases, dct)
3026 def __call__(cls, nm, bs, dt):
3027 return type(nm, bs, dt)
3028 class CM(type, metaclass=CMM):
3029 def __new__(mcls, name, bases, dct, *, bar=2):
3030 return super().__new__(mcls, name, bases, dct)
3031 class C(metaclass=CM):
3032 def __init__(self, b):
3033 pass
3034
3035 self.assertEqual(self.signature(CMM),
3036 ((('name', ..., ..., "positional_or_keyword"),
3037 ('bases', ..., ..., "positional_or_keyword"),
3038 ('dct', ..., ..., "positional_or_keyword"),
3039 ('foo', 1, ..., "keyword_only")),
3040 ...))
3041
3042 self.assertEqual(self.signature(CM),
3043 ((('nm', ..., ..., "positional_or_keyword"),
3044 ('bs', ..., ..., "positional_or_keyword"),
3045 ('dt', ..., ..., "positional_or_keyword")),
3046 ...))
3047
3048 self.assertEqual(self.signature(C),
3049 ((('b', ..., ..., "positional_or_keyword"),),
3050 ...))
3051
3052 class CM(type):
3053 def __init__(cls, name, bases, dct, *, bar=2):
3054 return super().__init__(name, bases, dct)
3055 class C(metaclass=CM):
3056 def __init__(self, b):
3057 pass
3058
3059 self.assertEqual(self.signature(CM),
3060 ((('name', ..., ..., "positional_or_keyword"),
3061 ('bases', ..., ..., "positional_or_keyword"),
3062 ('dct', ..., ..., "positional_or_keyword"),
3063 ('bar', 2, ..., "keyword_only")),
3064 ...))
3065
Yury Selivanov145dff82014-02-01 13:49:29 -05003066 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3067 "Signature information for builtins requires docstrings")
3068 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003069 # Test classes without user-defined __init__ or __new__
3070 class C: pass
3071 self.assertEqual(str(inspect.signature(C)), '()')
3072 class D(C): pass
3073 self.assertEqual(str(inspect.signature(D)), '()')
3074
3075 # Test meta-classes without user-defined __init__ or __new__
3076 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003077 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08003078 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
3079 self.assertEqual(inspect.signature(C), None)
3080 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
3081 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003082
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003083 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3084 "Signature information for builtins requires docstrings")
3085 def test_signature_on_builtin_class(self):
Antoine Pitrou91f43802019-05-26 17:10:09 +02003086 expected = ('(file, protocol=None, fix_imports=True, '
3087 'buffer_callback=None)')
3088 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003089
3090 class P(_pickle.Pickler): pass
3091 class EmptyTrait: pass
3092 class P2(EmptyTrait, P): pass
Antoine Pitrou91f43802019-05-26 17:10:09 +02003093 self.assertEqual(str(inspect.signature(P)), expected)
3094 self.assertEqual(str(inspect.signature(P2)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003095
3096 class P3(P2):
3097 def __init__(self, spam):
3098 pass
3099 self.assertEqual(str(inspect.signature(P3)), '(spam)')
3100
3101 class MetaP(type):
3102 def __call__(cls, foo, bar):
3103 pass
3104 class P4(P2, metaclass=MetaP):
3105 pass
3106 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
3107
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003108 def test_signature_on_callable_objects(self):
3109 class Foo:
3110 def __call__(self, a):
3111 pass
3112
3113 self.assertEqual(self.signature(Foo()),
3114 ((('a', ..., ..., "positional_or_keyword"),),
3115 ...))
3116
3117 class Spam:
3118 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003119 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003120 inspect.signature(Spam())
3121
3122 class Bar(Spam, Foo):
3123 pass
3124
3125 self.assertEqual(self.signature(Bar()),
3126 ((('a', ..., ..., "positional_or_keyword"),),
3127 ...))
3128
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003129 class Wrapped:
3130 pass
3131 Wrapped.__wrapped__ = lambda a: None
3132 self.assertEqual(self.signature(Wrapped),
3133 ((('a', ..., ..., "positional_or_keyword"),),
3134 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10003135 # wrapper loop:
3136 Wrapped.__wrapped__ = Wrapped
3137 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3138 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003139
3140 def test_signature_on_lambdas(self):
3141 self.assertEqual(self.signature((lambda a=10: a)),
3142 ((('a', 10, ..., "positional_or_keyword"),),
3143 ...))
3144
3145 def test_signature_equality(self):
3146 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003147 self.assertFalse(inspect.signature(foo) == 42)
3148 self.assertTrue(inspect.signature(foo) != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003149 self.assertTrue(inspect.signature(foo) == ALWAYS_EQ)
3150 self.assertFalse(inspect.signature(foo) != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003151
3152 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003153 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3154 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003155 self.assertEqual(
3156 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003157
3158 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003159 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3160 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003161 self.assertNotEqual(
3162 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003163
3164 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003165 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3166 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003167 self.assertNotEqual(
3168 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003169
3170 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003171 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3172 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003173 self.assertNotEqual(
3174 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003175
3176 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003177 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3178 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003179 self.assertNotEqual(
3180 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003181
3182 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003183 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3184 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003185 self.assertNotEqual(
3186 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003187 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003188 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3189 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003190 self.assertNotEqual(
3191 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003192
3193 def foo(*, a, b, c): pass
3194 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003195 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3196 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003197 self.assertEqual(
3198 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003199
3200 def foo(*, a=1, b, c): pass
3201 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003202 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3203 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003204 self.assertEqual(
3205 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003206
3207 def foo(pos, *, a=1, b, c): pass
3208 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003209 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3210 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003211 self.assertEqual(
3212 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003213
3214 def foo(pos, *, a, b, c): pass
3215 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003216 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3217 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003218 self.assertNotEqual(
3219 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003220
3221 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3222 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003223 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3224 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003225 self.assertEqual(
3226 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003227
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003228 def test_signature_hashable(self):
3229 S = inspect.Signature
3230 P = inspect.Parameter
3231
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003232 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003233 foo_sig = inspect.signature(foo)
3234
3235 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3236
3237 self.assertEqual(hash(foo_sig), hash(manual_sig))
3238 self.assertNotEqual(hash(foo_sig),
3239 hash(manual_sig.replace(return_annotation='spam')))
3240
3241 def bar(a) -> 1: pass
3242 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3243
3244 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003245 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003246 hash(inspect.signature(foo))
3247
Pablo Galindob0544ba2021-04-21 12:41:19 +01003248 def foo(a) -> {}: pass
3249 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3250 hash(inspect.signature(foo))
3251
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003252 def test_signature_str(self):
3253 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3254 pass
3255 self.assertEqual(str(inspect.signature(foo)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003256 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003257
3258 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3259 pass
3260 self.assertEqual(str(inspect.signature(foo)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003261 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003262
3263 def foo():
3264 pass
3265 self.assertEqual(str(inspect.signature(foo)), '()')
3266
3267 def test_signature_str_positional_only(self):
3268 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003269 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003270
3271 def test(a_po, *, b, **kwargs):
3272 return a_po, kwargs
3273
3274 sig = inspect.signature(test)
3275 new_params = list(sig.parameters.values())
3276 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3277 test.__signature__ = sig.replace(parameters=new_params)
3278
3279 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003280 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003281
Yury Selivanov2393dca2014-01-27 15:07:58 -05003282 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3283 '(foo, /)')
3284
3285 self.assertEqual(str(S(parameters=[
3286 P('foo', P.POSITIONAL_ONLY),
3287 P('bar', P.VAR_KEYWORD)])),
3288 '(foo, /, **bar)')
3289
3290 self.assertEqual(str(S(parameters=[
3291 P('foo', P.POSITIONAL_ONLY),
3292 P('bar', P.VAR_POSITIONAL)])),
3293 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003294
3295 def test_signature_replace_anno(self):
3296 def test() -> 42:
3297 pass
3298
3299 sig = inspect.signature(test)
3300 sig = sig.replace(return_annotation=None)
3301 self.assertIs(sig.return_annotation, None)
3302 sig = sig.replace(return_annotation=sig.empty)
3303 self.assertIs(sig.return_annotation, sig.empty)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003304 sig = sig.replace(return_annotation=42)
3305 self.assertEqual(sig.return_annotation, 42)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003306 self.assertEqual(sig, inspect.signature(test))
3307
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003308 def test_signature_on_mangled_parameters(self):
3309 class Spam:
3310 def foo(self, __p1:1=2, *, __p2:2=3):
3311 pass
3312 class Ham(Spam):
3313 pass
3314
3315 self.assertEqual(self.signature(Spam.foo),
3316 ((('self', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003317 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3318 ('_Spam__p2', 3, 2, "keyword_only")),
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003319 ...))
3320
3321 self.assertEqual(self.signature(Spam.foo),
3322 self.signature(Ham.foo))
3323
Yury Selivanovda396452014-03-27 12:09:24 -04003324 def test_signature_from_callable_python_obj(self):
3325 class MySignature(inspect.Signature): pass
3326 def foo(a, *, b:1): pass
3327 foo_sig = MySignature.from_callable(foo)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003328 self.assertIsInstance(foo_sig, MySignature)
3329
3330 def test_signature_from_callable_class(self):
3331 # A regression test for a class inheriting its signature from `object`.
3332 class MySignature(inspect.Signature): pass
3333 class foo: pass
3334 foo_sig = MySignature.from_callable(foo)
3335 self.assertIsInstance(foo_sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003336
3337 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3338 "Signature information for builtins requires docstrings")
3339 def test_signature_from_callable_builtin_obj(self):
3340 class MySignature(inspect.Signature): pass
3341 sig = MySignature.from_callable(_pickle.Pickler)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003342 self.assertIsInstance(sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003343
larryhastingsf36ba122018-01-28 11:13:09 -08003344 def test_signature_definition_order_preserved_on_kwonly(self):
3345 for fn in signatures_with_lexicographic_keyword_only_parameters():
3346 signature = inspect.signature(fn)
3347 l = list(signature.parameters)
3348 sorted_l = sorted(l)
3349 self.assertTrue(l)
3350 self.assertEqual(l, sorted_l)
3351 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3352 l = list(signature.parameters)
3353 self.assertEqual(l, unsorted_keyword_only_parameters)
3354
Jens Reidel611836a2020-03-18 03:22:46 +01003355 def test_signater_parameters_is_ordered(self):
3356 p1 = inspect.signature(lambda x, y: None).parameters
3357 p2 = inspect.signature(lambda y, x: None).parameters
3358 self.assertNotEqual(p1, p2)
3359
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003360 def test_signature_annotations_with_local_namespaces(self):
3361 class Foo: ...
3362 def func(foo: Foo) -> int: pass
Pablo Galindob0544ba2021-04-21 12:41:19 +01003363 def func2(foo: Foo, bar: 'Bar') -> int: pass
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003364
3365 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3366 with self.subTest(signature_func = signature_func):
3367 sig1 = signature_func(func)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003368 self.assertEqual(sig1.return_annotation, int)
3369 self.assertEqual(sig1.parameters['foo'].annotation, Foo)
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003370
larryhastings74613a42021-04-29 21:16:28 -07003371 sig2 = signature_func(func, locals=locals())
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003372 self.assertEqual(sig2.return_annotation, int)
3373 self.assertEqual(sig2.parameters['foo'].annotation, Foo)
3374
larryhastings74613a42021-04-29 21:16:28 -07003375 sig3 = signature_func(func2, globals={'Bar': int}, locals=locals())
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003376 self.assertEqual(sig3.return_annotation, int)
3377 self.assertEqual(sig3.parameters['foo'].annotation, Foo)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003378 self.assertEqual(sig3.parameters['bar'].annotation, 'Bar')
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003379
larryhastings74613a42021-04-29 21:16:28 -07003380 def test_signature_eval_str(self):
3381 isa = inspect_stringized_annotations
3382 sig = inspect.Signature
3383 par = inspect.Parameter
3384 PORK = inspect.Parameter.POSITIONAL_OR_KEYWORD
3385 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3386 with self.subTest(signature_func = signature_func):
3387 self.assertEqual(
3388 signature_func(isa.MyClass),
3389 sig(
3390 parameters=(
3391 par('a', PORK),
3392 par('b', PORK),
3393 )))
3394 self.assertEqual(
3395 signature_func(isa.function),
3396 sig(
3397 return_annotation='MyClass',
3398 parameters=(
3399 par('a', PORK, annotation='int'),
3400 par('b', PORK, annotation='str'),
3401 )))
3402 self.assertEqual(
3403 signature_func(isa.function2),
3404 sig(
3405 return_annotation='MyClass',
3406 parameters=(
3407 par('a', PORK, annotation='int'),
3408 par('b', PORK, annotation="'str'"),
3409 par('c', PORK, annotation="MyClass"),
3410 )))
3411 self.assertEqual(
3412 signature_func(isa.function3),
3413 sig(
3414 parameters=(
3415 par('a', PORK, annotation="'int'"),
3416 par('b', PORK, annotation="'str'"),
3417 par('c', PORK, annotation="'MyClass'"),
3418 )))
3419
3420 self.assertEqual(signature_func(isa.UnannotatedClass), sig())
3421 self.assertEqual(signature_func(isa.unannotated_function),
3422 sig(
3423 parameters=(
3424 par('a', PORK),
3425 par('b', PORK),
3426 par('c', PORK),
3427 )))
3428
3429 self.assertEqual(
3430 signature_func(isa.MyClass, eval_str=True),
3431 sig(
3432 parameters=(
3433 par('a', PORK),
3434 par('b', PORK),
3435 )))
3436 self.assertEqual(
3437 signature_func(isa.function, eval_str=True),
3438 sig(
3439 return_annotation=isa.MyClass,
3440 parameters=(
3441 par('a', PORK, annotation=int),
3442 par('b', PORK, annotation=str),
3443 )))
3444 self.assertEqual(
3445 signature_func(isa.function2, eval_str=True),
3446 sig(
3447 return_annotation=isa.MyClass,
3448 parameters=(
3449 par('a', PORK, annotation=int),
3450 par('b', PORK, annotation='str'),
3451 par('c', PORK, annotation=isa.MyClass),
3452 )))
3453 self.assertEqual(
3454 signature_func(isa.function3, eval_str=True),
3455 sig(
3456 parameters=(
3457 par('a', PORK, annotation='int'),
3458 par('b', PORK, annotation='str'),
3459 par('c', PORK, annotation='MyClass'),
3460 )))
3461
3462 globalns = {'int': float, 'str': complex}
3463 localns = {'str': tuple, 'MyClass': dict}
3464 with self.assertRaises(NameError):
3465 signature_func(isa.function, eval_str=True, globals=globalns)
3466
3467 self.assertEqual(
3468 signature_func(isa.function, eval_str=True, locals=localns),
3469 sig(
3470 return_annotation=dict,
3471 parameters=(
3472 par('a', PORK, annotation=int),
3473 par('b', PORK, annotation=tuple),
3474 )))
3475
3476 self.assertEqual(
3477 signature_func(isa.function, eval_str=True, globals=globalns, locals=localns),
3478 sig(
3479 return_annotation=dict,
3480 parameters=(
3481 par('a', PORK, annotation=float),
3482 par('b', PORK, annotation=tuple),
3483 )))
3484
3485 def test_signature_none_annotation(self):
3486 class funclike:
3487 # Has to be callable, and have correct
3488 # __code__, __annotations__, __defaults__, __name__,
3489 # and __kwdefaults__ attributes
3490
3491 def __init__(self, func):
3492 self.__name__ = func.__name__
3493 self.__code__ = func.__code__
3494 self.__annotations__ = func.__annotations__
3495 self.__defaults__ = func.__defaults__
3496 self.__kwdefaults__ = func.__kwdefaults__
3497 self.func = func
3498
3499 def __call__(self, *args, **kwargs):
3500 return self.func(*args, **kwargs)
3501
3502 def foo(): pass
3503 foo = funclike(foo)
3504 foo.__annotations__ = None
3505 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3506 with self.subTest(signature_func = signature_func):
3507 self.assertEqual(signature_func(foo), inspect.Signature())
3508 self.assertEqual(inspect.get_annotations(foo), {})
3509
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003510
3511class TestParameterObject(unittest.TestCase):
3512 def test_signature_parameter_kinds(self):
3513 P = inspect.Parameter
3514 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3515 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3516
3517 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3518 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3519
3520 def test_signature_parameter_object(self):
3521 p = inspect.Parameter('foo', default=10,
3522 kind=inspect.Parameter.POSITIONAL_ONLY)
3523 self.assertEqual(p.name, 'foo')
3524 self.assertEqual(p.default, 10)
3525 self.assertIs(p.annotation, p.empty)
3526 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3527
Dong-hee Naa9cab432018-05-30 00:04:08 +09003528 with self.assertRaisesRegex(ValueError, "value '123' is "
3529 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003530 inspect.Parameter('foo', default=10, kind='123')
3531
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003532 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003533 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3534
Yury Selivanov2393dca2014-01-27 15:07:58 -05003535 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003536 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3537
Yury Selivanov2393dca2014-01-27 15:07:58 -05003538 with self.assertRaisesRegex(ValueError,
3539 'is not a valid parameter name'):
3540 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3541
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003542 with self.assertRaisesRegex(ValueError,
3543 'is not a valid parameter name'):
3544 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3545
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003546 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003547 inspect.Parameter('a', default=42,
3548 kind=inspect.Parameter.VAR_KEYWORD)
3549
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003550 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003551 inspect.Parameter('a', default=42,
3552 kind=inspect.Parameter.VAR_POSITIONAL)
3553
3554 p = inspect.Parameter('a', default=42,
3555 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003556 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003557 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3558
3559 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003560 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003561
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003562 def test_signature_parameter_hashable(self):
3563 P = inspect.Parameter
3564 foo = P('foo', kind=P.POSITIONAL_ONLY)
3565 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3566 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3567 default=42)))
3568 self.assertNotEqual(hash(foo),
3569 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3570
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003571 def test_signature_parameter_equality(self):
3572 P = inspect.Parameter
3573 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3574
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003575 self.assertTrue(p == p)
3576 self.assertFalse(p != p)
3577 self.assertFalse(p == 42)
3578 self.assertTrue(p != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003579 self.assertTrue(p == ALWAYS_EQ)
3580 self.assertFalse(p != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003581
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003582 self.assertTrue(p == P('foo', default=42,
3583 kind=inspect.Parameter.KEYWORD_ONLY))
3584 self.assertFalse(p != P('foo', default=42,
3585 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003586
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003587 def test_signature_parameter_replace(self):
3588 p = inspect.Parameter('foo', default=42,
3589 kind=inspect.Parameter.KEYWORD_ONLY)
3590
3591 self.assertIsNot(p, p.replace())
3592 self.assertEqual(p, p.replace())
3593
3594 p2 = p.replace(annotation=1)
3595 self.assertEqual(p2.annotation, 1)
3596 p2 = p2.replace(annotation=p2.empty)
3597 self.assertEqual(p, p2)
3598
3599 p2 = p2.replace(name='bar')
3600 self.assertEqual(p2.name, 'bar')
3601 self.assertNotEqual(p2, p)
3602
Yury Selivanov2393dca2014-01-27 15:07:58 -05003603 with self.assertRaisesRegex(ValueError,
3604 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003605 p2 = p2.replace(name=p2.empty)
3606
3607 p2 = p2.replace(name='foo', default=None)
3608 self.assertIs(p2.default, None)
3609 self.assertNotEqual(p2, p)
3610
3611 p2 = p2.replace(name='foo', default=p2.empty)
3612 self.assertIs(p2.default, p2.empty)
3613
3614
3615 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3616 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3617 self.assertNotEqual(p2, p)
3618
Dong-hee Naa9cab432018-05-30 00:04:08 +09003619 with self.assertRaisesRegex(ValueError,
3620 "value <class 'inspect._empty'> "
3621 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003622 p2 = p2.replace(kind=p2.empty)
3623
3624 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3625 self.assertEqual(p2, p)
3626
3627 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003628 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3629 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003630
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003631 @cpython_only
3632 def test_signature_parameter_implicit(self):
3633 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003634 'implicit arguments must be passed as '
3635 'positional or keyword arguments, '
3636 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003637 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3638
3639 param = inspect.Parameter(
3640 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3641 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3642 self.assertEqual(param.name, 'implicit0')
3643
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003644 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003645 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003646
3647 with self.assertRaises(AttributeError):
3648 p.foo = 'bar'
3649
3650 with self.assertRaises(AttributeError):
3651 p.kind = 123
3652
3653
3654class TestSignatureBind(unittest.TestCase):
3655 @staticmethod
3656 def call(func, *args, **kwargs):
3657 sig = inspect.signature(func)
3658 ba = sig.bind(*args, **kwargs)
3659 return func(*ba.args, **ba.kwargs)
3660
3661 def test_signature_bind_empty(self):
3662 def test():
3663 return 42
3664
3665 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003666 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003667 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003668 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003669 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003670 with self.assertRaisesRegex(
3671 TypeError, "got an unexpected keyword argument 'spam'"):
3672
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003673 self.call(test, spam=1)
3674
3675 def test_signature_bind_var(self):
3676 def test(*args, **kwargs):
3677 return args, kwargs
3678
3679 self.assertEqual(self.call(test), ((), {}))
3680 self.assertEqual(self.call(test, 1), ((1,), {}))
3681 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3682 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3683 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3684 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3685 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3686 ((1, 2), {'foo': 'bar'}))
3687
3688 def test_signature_bind_just_args(self):
3689 def test(a, b, c):
3690 return a, b, c
3691
3692 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3693
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003694 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003695 self.call(test, 1, 2, 3, 4)
3696
Yury Selivanov86872752015-05-19 00:27:49 -04003697 with self.assertRaisesRegex(TypeError,
3698 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003699 self.call(test, 1)
3700
Yury Selivanov86872752015-05-19 00:27:49 -04003701 with self.assertRaisesRegex(TypeError,
3702 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003703 self.call(test)
3704
3705 def test(a, b, c=10):
3706 return a, b, c
3707 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3708 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3709
3710 def test(a=1, b=2, c=3):
3711 return a, b, c
3712 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3713 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3714 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3715
3716 def test_signature_bind_varargs_order(self):
3717 def test(*args):
3718 return args
3719
3720 self.assertEqual(self.call(test), ())
3721 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3722
3723 def test_signature_bind_args_and_varargs(self):
3724 def test(a, b, c=3, *args):
3725 return a, b, c, args
3726
3727 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3728 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3729 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3730 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3731
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003732 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003733 "multiple values for argument 'c'"):
3734 self.call(test, 1, 2, 3, c=4)
3735
3736 def test_signature_bind_just_kwargs(self):
3737 def test(**kwargs):
3738 return kwargs
3739
3740 self.assertEqual(self.call(test), {})
3741 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3742 {'foo': 'bar', 'spam': 'ham'})
3743
3744 def test_signature_bind_args_and_kwargs(self):
3745 def test(a, b, c=3, **kwargs):
3746 return a, b, c, kwargs
3747
3748 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3749 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3750 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3751 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3752 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3753 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3754 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3755 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3756 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3757 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3758 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3759 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3760 (1, 2, 4, {'foo': 'bar'}))
3761 self.assertEqual(self.call(test, c=5, a=4, b=3),
3762 (4, 3, 5, {}))
3763
3764 def test_signature_bind_kwonly(self):
3765 def test(*, foo):
3766 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003767 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003768 'too many positional arguments'):
3769 self.call(test, 1)
3770 self.assertEqual(self.call(test, foo=1), 1)
3771
3772 def test(a, *, foo=1, bar):
3773 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003774 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003775 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003776 self.call(test, 1)
3777
3778 def test(foo, *, bar):
3779 return foo, bar
3780 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3781 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3782
Yury Selivanov86872752015-05-19 00:27:49 -04003783 with self.assertRaisesRegex(
3784 TypeError, "got an unexpected keyword argument 'spam'"):
3785
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003786 self.call(test, bar=2, foo=1, spam=10)
3787
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003788 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003789 'too many positional arguments'):
3790 self.call(test, 1, 2)
3791
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003792 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003793 'too many positional arguments'):
3794 self.call(test, 1, 2, bar=2)
3795
Yury Selivanov86872752015-05-19 00:27:49 -04003796 with self.assertRaisesRegex(
3797 TypeError, "got an unexpected keyword argument 'spam'"):
3798
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003799 self.call(test, 1, bar=2, spam='ham')
3800
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003801 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003802 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003803 self.call(test, 1)
3804
3805 def test(foo, *, bar, **bin):
3806 return foo, bar, bin
3807 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3808 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3809 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3810 (1, 2, {'spam': 'ham'}))
3811 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3812 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003813 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003814 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003815 self.call(test, spam='ham', bar=2)
3816 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3817 (1, 2, {'bin': 1, 'spam': 10}))
3818
3819 def test_signature_bind_arguments(self):
3820 def test(a, *args, b, z=100, **kwargs):
3821 pass
3822 sig = inspect.signature(test)
3823 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3824 # we won't have 'z' argument in the bound arguments object, as we didn't
3825 # pass it to the 'bind'
3826 self.assertEqual(tuple(ba.arguments.items()),
3827 (('a', 10), ('args', (20,)), ('b', 30),
3828 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3829 self.assertEqual(ba.kwargs,
3830 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3831 self.assertEqual(ba.args, (10, 20))
3832
3833 def test_signature_bind_positional_only(self):
3834 P = inspect.Parameter
3835
3836 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3837 return a_po, b_po, c_po, foo, bar, kwargs
3838
3839 sig = inspect.signature(test)
3840 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3841 for name in ('a_po', 'b_po', 'c_po'):
3842 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3843 new_sig = sig.replace(parameters=new_params.values())
3844 test.__signature__ = new_sig
3845
3846 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3847 (1, 2, 4, 5, 6, {}))
3848
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003849 self.assertEqual(self.call(test, 1, 2),
3850 (1, 2, 3, 42, 50, {}))
3851
3852 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3853 (1, 2, 3, 4, 5, {}))
3854
3855 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3856 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3857
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003858 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003859 self.call(test, 1, 2, c_po=4)
3860
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003861 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003862 self.call(test, a_po=1, b_po=2)
3863
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003864 def test_signature_bind_with_self_arg(self):
3865 # Issue #17071: one of the parameters is named "self
3866 def test(a, self, b):
3867 pass
3868 sig = inspect.signature(test)
3869 ba = sig.bind(1, 2, 3)
3870 self.assertEqual(ba.args, (1, 2, 3))
3871 ba = sig.bind(1, self=2, b=3)
3872 self.assertEqual(ba.args, (1, 2, 3))
3873
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003874 def test_signature_bind_vararg_name(self):
3875 def test(a, *args):
3876 return a, args
3877 sig = inspect.signature(test)
3878
Yury Selivanov86872752015-05-19 00:27:49 -04003879 with self.assertRaisesRegex(
3880 TypeError, "got an unexpected keyword argument 'args'"):
3881
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003882 sig.bind(a=0, args=1)
3883
3884 def test(*args, **kwargs):
3885 return args, kwargs
3886 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3887
3888 sig = inspect.signature(test)
3889 ba = sig.bind(args=1)
3890 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3891
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003892 @cpython_only
3893 def test_signature_bind_implicit_arg(self):
3894 # Issue #19611: getcallargs should work with set comprehensions
3895 def make_set():
3896 return {z * z for z in range(5)}
3897 setcomp_code = make_set.__code__.co_consts[1]
3898 setcomp_func = types.FunctionType(setcomp_code, {})
3899
3900 iterator = iter(range(5))
3901 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3902
Pablo Galindof3ef06a2019-10-15 12:40:02 +01003903 def test_signature_bind_posonly_kwargs(self):
3904 def foo(bar, /, **kwargs):
3905 return bar, kwargs.get(bar)
3906
3907 sig = inspect.signature(foo)
3908 result = sig.bind("pos-only", bar="keyword")
3909
3910 self.assertEqual(result.kwargs, {"bar": "keyword"})
3911 self.assertIn(("bar", "pos-only"), result.arguments.items())
3912
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003913
3914class TestBoundArguments(unittest.TestCase):
3915 def test_signature_bound_arguments_unhashable(self):
3916 def foo(a): pass
3917 ba = inspect.signature(foo).bind(1)
3918
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003919 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003920 hash(ba)
3921
3922 def test_signature_bound_arguments_equality(self):
3923 def foo(a): pass
3924 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003925 self.assertTrue(ba == ba)
3926 self.assertFalse(ba != ba)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003927 self.assertTrue(ba == ALWAYS_EQ)
3928 self.assertFalse(ba != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003929
3930 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003931 self.assertTrue(ba == ba2)
3932 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003933
3934 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003935 self.assertFalse(ba == ba3)
3936 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003937 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003938 self.assertTrue(ba == ba3)
3939 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003940
3941 def bar(b): pass
3942 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003943 self.assertFalse(ba == ba4)
3944 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003945
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003946 def foo(*, a, b): pass
3947 sig = inspect.signature(foo)
3948 ba1 = sig.bind(a=1, b=2)
3949 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003950 self.assertTrue(ba1 == ba2)
3951 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003952
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003953 def test_signature_bound_arguments_pickle(self):
3954 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3955 sig = inspect.signature(foo)
3956 ba = sig.bind(20, 30, z={})
3957
3958 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3959 with self.subTest(pickle_ver=ver):
3960 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3961 self.assertEqual(ba, ba_pickled)
3962
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003963 def test_signature_bound_arguments_repr(self):
3964 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3965 sig = inspect.signature(foo)
3966 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003967 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003968
Yury Selivanovb907a512015-05-16 13:45:09 -04003969 def test_signature_bound_arguments_apply_defaults(self):
3970 def foo(a, b=1, *args, c:1={}, **kw): pass
3971 sig = inspect.signature(foo)
3972
3973 ba = sig.bind(20)
3974 ba.apply_defaults()
3975 self.assertEqual(
3976 list(ba.arguments.items()),
3977 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3978
3979 # Make sure that we preserve the order:
3980 # i.e. 'c' should be *before* 'kw'.
3981 ba = sig.bind(10, 20, 30, d=1)
3982 ba.apply_defaults()
3983 self.assertEqual(
3984 list(ba.arguments.items()),
3985 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3986
3987 # Make sure that BoundArguments produced by bind_partial()
3988 # are supported.
3989 def foo(a, b): pass
3990 sig = inspect.signature(foo)
3991 ba = sig.bind_partial(20)
3992 ba.apply_defaults()
3993 self.assertEqual(
3994 list(ba.arguments.items()),
3995 [('a', 20)])
3996
3997 # Test no args
3998 def foo(): pass
3999 sig = inspect.signature(foo)
4000 ba = sig.bind()
4001 ba.apply_defaults()
4002 self.assertEqual(list(ba.arguments.items()), [])
4003
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05004004 # Make sure a no-args binding still acquires proper defaults.
4005 def foo(a='spam'): pass
4006 sig = inspect.signature(foo)
4007 ba = sig.bind()
4008 ba.apply_defaults()
4009 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
4010
Rémi Lapeyre2cca8ef2020-01-28 13:47:03 +01004011 def test_signature_bound_arguments_arguments_type(self):
4012 def foo(a): pass
4013 ba = inspect.signature(foo).bind(1)
4014 self.assertIs(type(ba.arguments), dict)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004015
Yury Selivanovd82eddc2014-01-29 11:24:39 -05004016class TestSignaturePrivateHelpers(unittest.TestCase):
4017 def test_signature_get_bound_param(self):
4018 getter = inspect._signature_get_bound_param
4019
4020 self.assertEqual(getter('($self)'), 'self')
4021 self.assertEqual(getter('($self, obj)'), 'self')
4022 self.assertEqual(getter('($cls, /, obj)'), 'cls')
4023
Larry Hastings2623c8c2014-02-08 22:15:29 -08004024 def _strip_non_python_syntax(self, input,
4025 clean_signature, self_parameter, last_positional_only):
4026 computed_clean_signature, \
4027 computed_self_parameter, \
4028 computed_last_positional_only = \
4029 inspect._signature_strip_non_python_syntax(input)
4030 self.assertEqual(computed_clean_signature, clean_signature)
4031 self.assertEqual(computed_self_parameter, self_parameter)
4032 self.assertEqual(computed_last_positional_only, last_positional_only)
4033
4034 def test_signature_strip_non_python_syntax(self):
4035 self._strip_non_python_syntax(
4036 "($module, /, path, mode, *, dir_fd=None, " +
4037 "effective_ids=False,\n follow_symlinks=True)",
4038 "(module, path, mode, *, dir_fd=None, " +
4039 "effective_ids=False, follow_symlinks=True)",
4040 0,
4041 0)
4042
4043 self._strip_non_python_syntax(
4044 "($module, word, salt, /)",
4045 "(module, word, salt)",
4046 0,
4047 2)
4048
4049 self._strip_non_python_syntax(
4050 "(x, y=None, z=None, /)",
4051 "(x, y=None, z=None)",
4052 None,
4053 2)
4054
4055 self._strip_non_python_syntax(
4056 "(x, y=None, z=None)",
4057 "(x, y=None, z=None)",
4058 None,
4059 None)
4060
4061 self._strip_non_python_syntax(
4062 "(x,\n y=None,\n z = None )",
4063 "(x, y=None, z=None)",
4064 None,
4065 None)
4066
4067 self._strip_non_python_syntax(
4068 "",
4069 "",
4070 None,
4071 None)
4072
4073 self._strip_non_python_syntax(
4074 None,
4075 None,
4076 None,
4077 None)
4078
Nick Coghlan9c680b02015-04-13 12:54:54 -04004079class TestSignatureDefinitions(unittest.TestCase):
4080 # This test case provides a home for checking that particular APIs
4081 # have signatures available for introspection
4082
4083 @cpython_only
4084 @unittest.skipIf(MISSING_C_DOCSTRINGS,
4085 "Signature information for builtins requires docstrings")
4086 def test_builtins_have_signatures(self):
4087 # This checks all builtin callables in CPython have signatures
4088 # A few have signatures Signature can't yet handle, so we skip those
4089 # since they will have to wait until PEP 457 adds the required
4090 # introspection support to the inspect module
4091 # Some others also haven't been converted yet for various other
4092 # reasons, so we also skip those for the time being, but design
4093 # the test to fail in order to indicate when it needs to be
4094 # updated.
4095 no_signature = set()
4096 # These need PEP 457 groups
4097 needs_groups = {"range", "slice", "dir", "getattr",
4098 "next", "iter", "vars"}
4099 no_signature |= needs_groups
Joshua Bronsonf0a6fde2021-03-23 18:47:21 -04004100 # These have unrepresentable parameter default values of NULL
4101 needs_null = {"anext"}
4102 no_signature |= needs_null
Nick Coghlan9c680b02015-04-13 12:54:54 -04004103 # These need PEP 457 groups or a signature change to accept None
4104 needs_semantic_update = {"round"}
4105 no_signature |= needs_semantic_update
4106 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04004107 needs_varargs = {"breakpoint", "min", "max", "print",
4108 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04004109 no_signature |= needs_varargs
4110 # These simply weren't covered in the initial AC conversion
4111 # for builtin callables
4112 not_converted_yet = {"open", "__import__"}
4113 no_signature |= not_converted_yet
4114 # These builtin types are expected to provide introspection info
4115 types_with_signatures = set()
4116 # Check the signatures we expect to be there
4117 ns = vars(builtins)
4118 for name, obj in sorted(ns.items()):
4119 if not callable(obj):
4120 continue
4121 # The builtin types haven't been converted to AC yet
4122 if isinstance(obj, type) and (name not in types_with_signatures):
4123 # Note that this also skips all the exception types
4124 no_signature.add(name)
4125 if (name in no_signature):
4126 # Not yet converted
4127 continue
4128 with self.subTest(builtin=name):
4129 self.assertIsNotNone(inspect.signature(obj))
4130 # Check callables that haven't been converted don't claim a signature
4131 # This ensures this test will start failing as more signatures are
4132 # added, so the affected items can be moved into the scope of the
4133 # regression test above
4134 for name in no_signature:
4135 with self.subTest(builtin=name):
4136 self.assertIsNone(obj.__text_signature__)
4137
Serhiy Storchakad53cf992019-05-06 22:40:27 +03004138 def test_python_function_override_signature(self):
4139 def func(*args, **kwargs):
4140 pass
4141 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
4142 sig = inspect.signature(func)
4143 self.assertIsNotNone(sig)
4144 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
4145 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
4146 sig = inspect.signature(func)
4147 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
4148
Yury Selivanovd82eddc2014-01-29 11:24:39 -05004149
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01004150class NTimesUnwrappable:
4151 def __init__(self, n):
4152 self.n = n
4153 self._next = None
4154
4155 @property
4156 def __wrapped__(self):
4157 if self.n <= 0:
4158 raise Exception("Unwrapped too many times")
4159 if self._next is None:
4160 self._next = NTimesUnwrappable(self.n - 1)
4161 return self._next
4162
Nick Coghlane8c45d62013-07-28 20:00:01 +10004163class TestUnwrap(unittest.TestCase):
4164
4165 def test_unwrap_one(self):
4166 def func(a, b):
4167 return a + b
4168 wrapper = functools.lru_cache(maxsize=20)(func)
4169 self.assertIs(inspect.unwrap(wrapper), func)
4170
4171 def test_unwrap_several(self):
4172 def func(a, b):
4173 return a + b
4174 wrapper = func
4175 for __ in range(10):
4176 @functools.wraps(wrapper)
4177 def wrapper():
4178 pass
4179 self.assertIsNot(wrapper.__wrapped__, func)
4180 self.assertIs(inspect.unwrap(wrapper), func)
4181
4182 def test_stop(self):
4183 def func1(a, b):
4184 return a + b
4185 @functools.wraps(func1)
4186 def func2():
4187 pass
4188 @functools.wraps(func2)
4189 def wrapper():
4190 pass
4191 func2.stop_here = 1
4192 unwrapped = inspect.unwrap(wrapper,
4193 stop=(lambda f: hasattr(f, "stop_here")))
4194 self.assertIs(unwrapped, func2)
4195
4196 def test_cycle(self):
4197 def func1(): pass
4198 func1.__wrapped__ = func1
4199 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4200 inspect.unwrap(func1)
4201
4202 def func2(): pass
4203 func2.__wrapped__ = func1
4204 func1.__wrapped__ = func2
4205 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4206 inspect.unwrap(func1)
4207 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4208 inspect.unwrap(func2)
4209
4210 def test_unhashable(self):
4211 def func(): pass
4212 func.__wrapped__ = None
4213 class C:
4214 __hash__ = None
4215 __wrapped__ = func
4216 self.assertIsNone(inspect.unwrap(C()))
4217
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01004218 def test_recursion_limit(self):
4219 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
4220 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4221 inspect.unwrap(obj)
4222
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004223class TestMain(unittest.TestCase):
4224 def test_only_source(self):
4225 module = importlib.import_module('unittest')
4226 rc, out, err = assert_python_ok('-m', 'inspect',
4227 'unittest')
4228 lines = out.decode().splitlines()
4229 # ignore the final newline
4230 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
4231 self.assertEqual(err, b'')
4232
Yury Selivanov42407ab2014-06-23 10:23:50 -07004233 def test_custom_getattr(self):
4234 def foo():
4235 pass
4236 foo.__signature__ = 42
4237 with self.assertRaises(TypeError):
4238 inspect.signature(foo)
4239
Brett Cannon634a8fc2013-10-02 10:25:42 -04004240 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04004241 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004242 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004243 rc, out, err = assert_python_ok('-m', 'inspect',
4244 'concurrent.futures:ThreadPoolExecutor')
4245 lines = out.decode().splitlines()
4246 # ignore the final newline
4247 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04004248 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004249 self.assertEqual(err, b'')
4250
4251 def test_builtins(self):
4252 module = importlib.import_module('unittest')
4253 _, out, err = assert_python_failure('-m', 'inspect',
4254 'sys')
4255 lines = err.decode().splitlines()
4256 self.assertEqual(lines, ["Can't get info for builtin modules."])
4257
4258 def test_details(self):
4259 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01004260 args = support.optim_args_from_interpreter_flags()
4261 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004262 'unittest', '--details')
4263 output = out.decode()
4264 # Just a quick sanity check on the output
4265 self.assertIn(module.__name__, output)
4266 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01004267 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004268 self.assertEqual(err, b'')
4269
4270
Yury Selivanovef1e7502014-12-08 16:05:34 -05004271class TestReload(unittest.TestCase):
4272
4273 src_before = textwrap.dedent("""\
4274def foo():
4275 print("Bla")
4276 """)
4277
4278 src_after = textwrap.dedent("""\
4279def foo():
4280 print("Oh no!")
4281 """)
4282
4283 def assertInspectEqual(self, path, source):
4284 inspected_src = inspect.getsource(source)
Inada Naokifb786922021-04-06 11:18:41 +09004285 with open(path, encoding='utf-8') as src:
Yury Selivanovef1e7502014-12-08 16:05:34 -05004286 self.assertEqual(
4287 src.read().splitlines(True),
4288 inspected_src.splitlines(True)
4289 )
4290
4291 def test_getsource_reload(self):
4292 # see issue 1218234
4293 with _ready_to_import('reload_bug', self.src_before) as (name, path):
4294 module = importlib.import_module(name)
4295 self.assertInspectEqual(path, module)
Inada Naokifb786922021-04-06 11:18:41 +09004296 with open(path, 'w', encoding='utf-8') as src:
Yury Selivanovef1e7502014-12-08 16:05:34 -05004297 src.write(self.src_after)
4298 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004299
Nick Coghlane8c45d62013-07-28 20:00:01 +10004300
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004301def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00004302 run_unittest(
Irit Katriel6e1eec72020-12-04 16:45:38 +00004303 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBlockComments,
4304 TestBuggyCases, TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00004305 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00004306 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004307 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04004308 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04004309 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04004310 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07004311 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00004312 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00004313
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004314if __name__ == "__main__":
4315 test_main()