blob: 157f315999c428c3b7b6cd67dc75f7799c812c1b [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 Storchaka5cf2b7252015-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 Storchaka5cf2b7252015-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 Storchaka5cf2b7252015-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
Miss Islington (bot)f468ede2021-07-30 10:46:42 -0700588class TestGetsourceInteractive(unittest.TestCase):
589 def tearDown(self):
Miss Islington (bot)a1eaa742021-08-02 06:41:08 -0700590 mod.ParrotDroppings.__module__ = self.mod
Miss Islington (bot)f468ede2021-07-30 10:46:42 -0700591 sys.modules['__main__'] = self.main
592
593 def test_getclasses_interactive(self):
594 self.main = sys.modules['__main__']
Miss Islington (bot)a1eaa742021-08-02 06:41:08 -0700595 self.mod = mod.ParrotDroppings.__module__
Miss Islington (bot)f468ede2021-07-30 10:46:42 -0700596 class MockModule:
597 __file__ = None
598 sys.modules['__main__'] = MockModule
599 mod.ParrotDroppings.__module__ = '__main__'
600 with self.assertRaisesRegex(OSError, 'source code not available') as e:
601 inspect.getsource(mod.ParrotDroppings)
602
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700603class TestGettingSourceOfToplevelFrames(GetSourceBase):
604 fodderModule = mod
605
606 def test_range_toplevel_frame(self):
607 self.maxDiff = None
608 self.assertSourceEqual(mod.currentframe, 1, None)
609
610 def test_range_traceback_toplevel_frame(self):
611 self.assertSourceEqual(mod.tb, 1, None)
612
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000613class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000614 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000615
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000616 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000617 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000618
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000619 def test_replacing_decorator(self):
620 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000621
Yury Selivanov081bbf62014-09-26 17:34:54 -0400622 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200623 self.assertSourceEqual(mod2.real, 130, 132)
624
625 def test_decorator_with_lambda(self):
626 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400627
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000628class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000629 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000630 def test_oneline_lambda(self):
631 # Test inspect.getsource with a one-line lambda function.
632 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000633
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000634 def test_threeline_lambda(self):
635 # Test inspect.getsource with a three-line lambda function,
636 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000637 self.assertSourceEqual(mod2.tll, 28, 30)
638
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000639 def test_twoline_indented_lambda(self):
640 # Test inspect.getsource with a two-line lambda function,
641 # where the second line _is_ indented.
642 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000643
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000644 def test_onelinefunc(self):
645 # Test inspect.getsource with a regular one-line function.
646 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000647
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000648 def test_manyargs(self):
649 # Test inspect.getsource with a regular function where
650 # the arguments are on two lines and _not_ indented and
651 # the body on the second line with the last arguments.
652 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000653
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000654 def test_twolinefunc(self):
655 # Test inspect.getsource with a regular function where
656 # the body is on two lines, following the argument list and
657 # continued on the next line by a \\.
658 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000659
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000660 def test_lambda_in_list(self):
661 # Test inspect.getsource with a one-line lambda function
662 # defined in a list, indented.
663 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000664
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000665 def test_anonymous(self):
666 # Test inspect.getsource with a lambda function defined
667 # as argument to another function.
668 self.assertSourceEqual(mod2.anonymous, 55, 55)
669
Irit Katriel6e1eec72020-12-04 16:45:38 +0000670class TestBlockComments(GetSourceBase):
671 fodderModule = mod
672
673 def test_toplevel_class(self):
674 self.assertSourceEqual(mod.WhichComments, 96, 114)
675
676 def test_class_method(self):
677 self.assertSourceEqual(mod.WhichComments.f, 99, 104)
678
679 def test_class_async_method(self):
680 self.assertSourceEqual(mod.WhichComments.asyncf, 109, 112)
681
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000682class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000683 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000684
685 def test_with_comment(self):
686 self.assertSourceEqual(mod2.with_comment, 58, 59)
687
688 def test_multiline_sig(self):
689 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
690
Armin Rigodd5c0232005-09-25 11:45:45 +0000691 def test_nested_class(self):
692 self.assertSourceEqual(mod2.func69().func71, 71, 72)
693
694 def test_one_liner_followed_by_non_name(self):
695 self.assertSourceEqual(mod2.func77, 77, 77)
696
697 def test_one_liner_dedent_non_name(self):
698 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
699
700 def test_with_comment_instead_of_docstring(self):
701 self.assertSourceEqual(mod2.func88, 88, 90)
702
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000703 def test_method_in_dynamic_class(self):
704 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
705
R David Murray32562d72014-10-03 11:15:38 -0400706 # This should not skip for CPython, but might on a repackaged python where
707 # unicodedata is not an external module, or on pypy.
708 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
709 unicodedata.__file__.endswith('.py'),
710 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000711 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200712 self.assertRaises(OSError, inspect.getsource, unicodedata)
713 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000714
R. David Murraya1b37402010-06-17 02:04:29 +0000715 def test_findsource_code_in_linecache(self):
716 lines = ["x=1"]
717 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200718 self.assertRaises(OSError, inspect.findsource, co)
719 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000720 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200721 try:
722 self.assertEqual(inspect.findsource(co), (lines,0))
723 self.assertEqual(inspect.getsource(co), lines[0])
724 finally:
725 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000726
Ezio Melotti1b145922013-03-30 05:17:24 +0200727 def test_findsource_without_filename(self):
728 for fname in ['', '<string>']:
729 co = compile('x=1', fname, "exec")
730 self.assertRaises(IOError, inspect.findsource, co)
731 self.assertRaises(IOError, inspect.getsource, co)
732
Irit Katriel2e0760b2020-12-04 21:22:03 +0000733 def test_findsource_with_out_of_bounds_lineno(self):
734 mod_len = len(inspect.getsource(mod))
735 src = '\n' * 2* mod_len + "def f(): pass"
736 co = compile(src, mod.__file__, "exec")
737 g, l = {}, {}
738 eval(co, g, l)
739 func = l['f']
740 self.assertEqual(func.__code__.co_firstlineno, 1+2*mod_len)
741 with self.assertRaisesRegex(IOError, "lineno is out of bounds"):
742 inspect.findsource(func)
743
Antoine Pitroua8723a02015-04-15 00:41:29 +0200744 def test_getsource_on_method(self):
745 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
746
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300747 def test_nested_func(self):
748 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
749
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530750 def test_class_definition_in_multiline_string_definition(self):
751 self.assertSourceEqual(mod2.cls149, 149, 152)
752
753 def test_class_definition_in_multiline_comment(self):
754 self.assertSourceEqual(mod2.cls160, 160, 163)
755
756 def test_nested_class_definition_indented_string(self):
757 self.assertSourceEqual(mod2.cls173.cls175, 175, 176)
758
759 def test_nested_class_definition(self):
760 self.assertSourceEqual(mod2.cls183, 183, 188)
761 self.assertSourceEqual(mod2.cls183.cls185, 185, 188)
762
763 def test_class_decorator(self):
764 self.assertSourceEqual(mod2.cls196, 194, 201)
765 self.assertSourceEqual(mod2.cls196.cls200, 198, 201)
766
767 def test_class_inside_conditional(self):
768 self.assertSourceEqual(mod2.cls238, 238, 240)
769 self.assertSourceEqual(mod2.cls238.cls239, 239, 240)
770
771 def test_multiple_children_classes(self):
772 self.assertSourceEqual(mod2.cls203, 203, 209)
773 self.assertSourceEqual(mod2.cls203.cls204, 204, 206)
774 self.assertSourceEqual(mod2.cls203.cls204.cls205, 205, 206)
775 self.assertSourceEqual(mod2.cls203.cls207, 207, 209)
776 self.assertSourceEqual(mod2.cls203.cls207.cls205, 208, 209)
777
778 def test_nested_class_definition_inside_function(self):
779 self.assertSourceEqual(mod2.func212(), 213, 214)
780 self.assertSourceEqual(mod2.cls213, 218, 222)
781 self.assertSourceEqual(mod2.cls213().func219(), 220, 221)
782
783 def test_nested_class_definition_inside_async_function(self):
784 import asyncio
785 self.addCleanup(asyncio.set_event_loop_policy, None)
786 self.assertSourceEqual(asyncio.run(mod2.func225()), 226, 227)
787 self.assertSourceEqual(mod2.cls226, 231, 235)
788 self.assertSourceEqual(asyncio.run(mod2.cls226().func232()), 233, 234)
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300789
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000790class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400791 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000792 self.tempdir = TESTFN + '_dir'
793 os.mkdir(self.tempdir)
Inada Naokifb786922021-04-06 11:18:41 +0900794 with open(os.path.join(self.tempdir, 'inspect_fodder3%spy' % os.extsep),
795 'w', encoding='utf-8') as f:
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000796 f.write("class X:\n pass # No EOL")
797 with DirsOnSysPath(self.tempdir):
798 import inspect_fodder3 as mod3
799 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400800 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000801
802 def tearDown(self):
803 shutil.rmtree(self.tempdir)
804
805 def test_class(self):
806 self.assertSourceEqual(self.fodderModule.X, 1, 2)
807
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100808
809class _BrokenDataDescriptor(object):
810 """
811 A broken data descriptor. See bug #1785.
812 """
813 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700814 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100815
816 def __set__(*args):
817 raise RuntimeError
818
819 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700820 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100821
822
823class _BrokenMethodDescriptor(object):
824 """
825 A broken method descriptor. See bug #1785.
826 """
827 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700828 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100829
830 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700831 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100832
833
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000834# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000835def attrs_wo_objs(cls):
836 return [t[:3] for t in inspect.classify_class_attrs(cls)]
837
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100838
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000839class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000840 def test_newstyle_mro(self):
841 # The same w/ new-class MRO.
842 class A(object): pass
843 class B(A): pass
844 class C(A): pass
845 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000846
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000847 expected = (D, B, C, A, object)
848 got = inspect.getmro(D)
849 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000850
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500851 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
852 varkw_e=None, defaults_e=None, formatted=None):
Xtreak6d0b7472019-05-30 17:31:39 +0530853 with self.assertWarns(DeprecationWarning):
854 args, varargs, varkw, defaults = inspect.getargspec(routine)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500855 self.assertEqual(args, args_e)
856 self.assertEqual(varargs, varargs_e)
857 self.assertEqual(varkw, varkw_e)
858 self.assertEqual(defaults, defaults_e)
859 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530860 with self.assertWarns(DeprecationWarning):
861 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
862 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500863
Christian Heimes3795b532007-11-08 13:48:53 +0000864 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
865 varkw_e=None, defaults_e=None,
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100866 posonlyargs_e=[], kwonlyargs_e=[],
867 kwonlydefaults_e=None,
Christian Heimes3795b532007-11-08 13:48:53 +0000868 ann_e={}, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100869 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
870 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000871 self.assertEqual(args, args_e)
872 self.assertEqual(varargs, varargs_e)
873 self.assertEqual(varkw, varkw_e)
874 self.assertEqual(defaults, defaults_e)
875 self.assertEqual(kwonlyargs, kwonlyargs_e)
876 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
877 self.assertEqual(ann, ann_e)
878 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530879 with self.assertWarns(DeprecationWarning):
880 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
881 kwonlyargs, kwonlydefaults, ann),
882 formatted)
Christian Heimes3795b532007-11-08 13:48:53 +0000883
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500884 def test_getargspec(self):
885 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
886
Pablo Galindod5d2b452019-04-30 02:01:14 +0100887 self.assertArgSpecEquals(mod.spam,
888 ['a', 'b', 'c', 'd', 'e', 'f'],
889 'g', 'h', (3, 4, 5),
890 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500891
892 self.assertRaises(ValueError, self.assertArgSpecEquals,
893 mod2.keyworded, [])
894
895 self.assertRaises(ValueError, self.assertArgSpecEquals,
896 mod2.annotated, [])
897 self.assertRaises(ValueError, self.assertArgSpecEquals,
898 mod2.keyword_only_arg, [])
899
900
Christian Heimes3795b532007-11-08 13:48:53 +0000901 def test_getfullargspec(self):
902 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
903 kwonlyargs_e=['arg2'],
904 kwonlydefaults_e={'arg2':1},
905 formatted='(*arg1, arg2=1)')
906
907 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000908 ann_e={'arg1' : list},
Pablo Galindob0544ba2021-04-21 12:41:19 +0100909 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000910 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
911 kwonlyargs_e=['arg'],
912 formatted='(*, arg)')
913
Pablo Galindod5d2b452019-04-30 02:01:14 +0100914 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100915 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100916 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100917
918 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100919 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100920 varargs_e='args',
921 varkw_e='kwargs',
922 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100923 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100924
Pablo Galindod5d2b452019-04-30 02:01:14 +0100925 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100926 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100927 kwonlyargs_e=['e', 'f'],
928 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100929 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100930
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500931 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500932 # Issue 20684: low level introspection API must ignore __wrapped__
933 @functools.wraps(mod.spam)
934 def ham(x, y):
935 pass
936 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500937 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500938 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
939 self.assertFullArgSpecEquals(functools.partial(ham),
940 ['x', 'y'], formatted='(x, y)')
941 # Other variants
942 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500943 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
944 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500945 class C:
946 @functools.wraps(mod.spam)
947 def ham(self, x, y):
948 pass
949 pham = functools.partialmethod(ham)
950 @functools.wraps(mod.spam)
951 def __call__(self, x, y):
952 pass
953 check_method(C())
954 check_method(C.ham)
955 check_method(C().ham)
956 check_method(C.pham)
957 check_method(C().pham)
958
959 class C_new:
960 @functools.wraps(mod.spam)
961 def __new__(self, x, y):
962 pass
963 check_method(C_new)
964
965 class C_init:
966 @functools.wraps(mod.spam)
967 def __init__(self, x, y):
968 pass
969 check_method(C_init)
970
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500971 def test_getfullargspec_signature_attr(self):
972 def test():
973 pass
974 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
975 test.__signature__ = inspect.Signature(parameters=(spam_param,))
976
Pablo Galindod5d2b452019-04-30 02:01:14 +0100977 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500978
Yury Selivanov4cb93912014-01-29 11:54:12 -0500979 def test_getfullargspec_signature_annos(self):
980 def test(a:'spam') -> 'ham': pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100981 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500982 self.assertEqual(test.__annotations__, spec.annotations)
983
984 def test(): pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100985 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500986 self.assertEqual(test.__annotations__, spec.annotations)
987
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500988 @unittest.skipIf(MISSING_C_DOCSTRINGS,
989 "Signature information for builtins requires docstrings")
990 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100991 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
992 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500993
Pablo Galindod5d2b452019-04-30 02:01:14 +0100994 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
995 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500996
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500997 self.assertFullArgSpecEquals(
998 os.stat,
999 args_e=['path'],
1000 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
1001 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
1002 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
1003
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001004 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001005 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1006 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +08001007 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001008 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001009 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindoaee19f52019-05-16 21:08:15 +01001010 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001011 self.assertEqual(spec.defaults[0], 'avocado')
1012
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001013 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001014 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1015 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +08001016 def test_getfullargspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001017 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001018 builtin = _testcapi.docstring_no_signature
Pablo Galindoaee19f52019-05-16 21:08:15 +01001019 with self.assertRaises(TypeError):
1020 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +00001021
larryhastingsf36ba122018-01-28 11:13:09 -08001022 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
1023 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindoaee19f52019-05-16 21:08:15 +01001024 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -08001025 l = list(signature.kwonlyargs)
1026 sorted_l = sorted(l)
1027 self.assertTrue(l)
1028 self.assertEqual(l, sorted_l)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001029 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -08001030 l = list(signature.kwonlyargs)
1031 self.assertEqual(l, unsorted_keyword_only_parameters)
1032
Yury Selivanov37dc2b22016-01-11 15:15:01 -05001033 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001034 class A(object):
1035 def m(self):
1036 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -05001037 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +00001038
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001039 def test_classify_newstyle(self):
1040 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +00001041
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001042 def s(): pass
1043 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +00001044
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001045 def c(cls): pass
1046 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +00001047
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001048 def getp(self): pass
1049 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +00001050
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001051 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001052
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001053 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001054
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001055 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +00001056
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001057 dd = _BrokenDataDescriptor()
1058 md = _BrokenMethodDescriptor()
1059
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001060 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001061
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001062 self.assertIn(('__new__', 'static method', object), attrs,
1063 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001064 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
1065
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')
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001069 self.assertIn(('m', 'method', A), attrs,
1070 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001071 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1072 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001073 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1074 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001075
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001076 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001077
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001078 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001079
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001080 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001081 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1082 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1083 self.assertIn(('p', 'property', A), attrs, 'missing property')
1084 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1085 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1086 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001087 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1088 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001089
1090
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001091 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001092
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001093 def m(self): pass
1094 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001095
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001096 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001097 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1098 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1099 self.assertIn(('p', 'property', A), attrs, 'missing property')
1100 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
1101 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1102 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001103 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1104 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001105
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001106 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001107
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001108 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001109
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001110 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001111 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1112 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1113 self.assertIn(('p', 'property', A), attrs, 'missing property')
1114 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1115 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1116 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001117 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1118 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1119
1120 def test_classify_builtin_types(self):
1121 # Simple sanity check that all built-in types can have their
1122 # attributes classified.
1123 for name in dir(__builtins__):
1124 builtin = getattr(__builtins__, name)
1125 if isinstance(builtin, type):
1126 inspect.classify_class_attrs(builtin)
1127
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001128 attrs = attrs_wo_objs(bool)
1129 self.assertIn(('__new__', 'static method', bool), attrs,
1130 'missing __new__')
1131 self.assertIn(('from_bytes', 'class method', int), attrs,
1132 'missing class method')
1133 self.assertIn(('to_bytes', 'method', int), attrs,
1134 'missing plain method')
1135 self.assertIn(('__add__', 'method', int), attrs,
1136 'missing plain method')
1137 self.assertIn(('__and__', 'method', bool), attrs,
1138 'missing plain method')
1139
Ethan Furman63c141c2013-10-18 00:27:39 -07001140 def test_classify_DynamicClassAttribute(self):
1141 class Meta(type):
1142 def __getattr__(self, name):
1143 if name == 'ham':
1144 return 'spam'
1145 return super().__getattr__(name)
1146 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001147 @types.DynamicClassAttribute
1148 def ham(self):
1149 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001150 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1151 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001152 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001153 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1154
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001155 def test_classify_overrides_bool(self):
1156 class NoBool(object):
1157 def __eq__(self, other):
1158 return NoBool()
1159
1160 def __bool__(self):
1161 raise NotImplementedError(
1162 "This object does not specify a boolean value")
1163
1164 class HasNB(object):
1165 dd = NoBool()
1166
1167 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1168 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1169
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001170 def test_classify_metaclass_class_attribute(self):
1171 class Meta(type):
1172 fish = 'slap'
1173 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001174 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001175 class Class(metaclass=Meta):
1176 pass
1177 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1178 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1179
Ethan Furman63c141c2013-10-18 00:27:39 -07001180 def test_classify_VirtualAttribute(self):
1181 class Meta(type):
1182 def __dir__(cls):
1183 return ['__class__', '__module__', '__name__', 'BOOM']
1184 def __getattr__(self, name):
1185 if name =='BOOM':
1186 return 42
1187 return super().__getattr(name)
1188 class Class(metaclass=Meta):
1189 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001190 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001191 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1192
1193 def test_classify_VirtualAttribute_multi_classes(self):
1194 class Meta1(type):
1195 def __dir__(cls):
1196 return ['__class__', '__module__', '__name__', 'one']
1197 def __getattr__(self, name):
1198 if name =='one':
1199 return 1
1200 return super().__getattr__(name)
1201 class Meta2(type):
1202 def __dir__(cls):
1203 return ['__class__', '__module__', '__name__', 'two']
1204 def __getattr__(self, name):
1205 if name =='two':
1206 return 2
1207 return super().__getattr__(name)
1208 class Meta3(Meta1, Meta2):
1209 def __dir__(cls):
1210 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1211 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1212 def __getattr__(self, name):
1213 if name =='three':
1214 return 3
1215 return super().__getattr__(name)
1216 class Class1(metaclass=Meta1):
1217 pass
1218 class Class2(Class1, metaclass=Meta3):
1219 pass
1220
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001221 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1222 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1223 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001224 cca = inspect.classify_class_attrs(Class2)
1225 for sf in (should_find1, should_find2, should_find3):
1226 self.assertIn(sf, cca)
1227
1228 def test_classify_class_attrs_with_buggy_dir(self):
1229 class M(type):
1230 def __dir__(cls):
1231 return ['__class__', '__name__', 'missing']
1232 class C(metaclass=M):
1233 pass
1234 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1235 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001236
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001237 def test_getmembers_descriptors(self):
1238 class A(object):
1239 dd = _BrokenDataDescriptor()
1240 md = _BrokenMethodDescriptor()
1241
1242 def pred_wrapper(pred):
1243 # A quick'n'dirty way to discard standard attributes of new-style
1244 # classes.
1245 class Empty(object):
1246 pass
1247 def wrapped(x):
1248 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1249 return False
1250 return pred(x)
1251 return wrapped
1252
1253 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1254 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1255
1256 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1257 [('md', A.__dict__['md'])])
1258 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1259 [('dd', A.__dict__['dd'])])
1260
1261 class B(A):
1262 pass
1263
1264 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1265 [('md', A.__dict__['md'])])
1266 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1267 [('dd', A.__dict__['dd'])])
1268
Antoine Pitrou0c603812012-01-18 17:40:18 +01001269 def test_getmembers_method(self):
1270 class B:
1271 def f(self):
1272 pass
1273
1274 self.assertIn(('f', B.f), inspect.getmembers(B))
1275 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1276 b = B()
1277 self.assertIn(('f', b.f), inspect.getmembers(b))
1278 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1279
Ethan Furmane03ea372013-09-25 07:14:41 -07001280 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001281 class M(type):
1282 def __getattr__(cls, name):
1283 if name == 'eggs':
1284 return 'scrambled'
1285 return super().__getattr__(name)
1286 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001287 @types.DynamicClassAttribute
1288 def eggs(self):
1289 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001290 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1291 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1292
1293 def test_getmembers_with_buggy_dir(self):
1294 class M(type):
1295 def __dir__(cls):
1296 return ['__class__', '__name__', 'missing']
1297 class C(metaclass=M):
1298 pass
1299 attrs = [a[0] for a in inspect.getmembers(C)]
1300 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001301
larryhastings74613a42021-04-29 21:16:28 -07001302 def test_get_annotations_with_stock_annotations(self):
1303 def foo(a:int, b:str): pass
1304 self.assertEqual(inspect.get_annotations(foo), {'a': int, 'b': str})
1305
1306 foo.__annotations__ = {'a': 'foo', 'b':'str'}
1307 self.assertEqual(inspect.get_annotations(foo), {'a': 'foo', 'b': 'str'})
1308
1309 self.assertEqual(inspect.get_annotations(foo, eval_str=True, locals=locals()), {'a': foo, 'b': str})
1310 self.assertEqual(inspect.get_annotations(foo, eval_str=True, globals=locals()), {'a': foo, 'b': str})
1311
1312 isa = inspect_stock_annotations
1313 self.assertEqual(inspect.get_annotations(isa), {'a': int, 'b': str})
1314 self.assertEqual(inspect.get_annotations(isa.MyClass), {'a': int, 'b': str})
1315 self.assertEqual(inspect.get_annotations(isa.function), {'a': int, 'b': str, 'return': isa.MyClass})
1316 self.assertEqual(inspect.get_annotations(isa.function2), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1317 self.assertEqual(inspect.get_annotations(isa.function3), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1318 self.assertEqual(inspect.get_annotations(inspect), {}) # inspect module has no annotations
1319 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass), {})
1320 self.assertEqual(inspect.get_annotations(isa.unannotated_function), {})
1321
1322 self.assertEqual(inspect.get_annotations(isa, eval_str=True), {'a': int, 'b': str})
1323 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=True), {'a': int, 'b': str})
1324 self.assertEqual(inspect.get_annotations(isa.function, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1325 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=True), {'a': int, 'b': str, 'c': isa.MyClass, 'return': isa.MyClass})
1326 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=True), {'a': int, 'b': str, 'c': isa.MyClass})
1327 self.assertEqual(inspect.get_annotations(inspect, eval_str=True), {})
1328 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=True), {})
1329 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=True), {})
1330
1331 self.assertEqual(inspect.get_annotations(isa, eval_str=False), {'a': int, 'b': str})
1332 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=False), {'a': int, 'b': str})
1333 self.assertEqual(inspect.get_annotations(isa.function, eval_str=False), {'a': int, 'b': str, 'return': isa.MyClass})
1334 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=False), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1335 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=False), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1336 self.assertEqual(inspect.get_annotations(inspect, eval_str=False), {})
1337 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=False), {})
1338 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=False), {})
1339
1340 def times_three(fn):
1341 @functools.wraps(fn)
1342 def wrapper(a, b):
1343 return fn(a*3, b*3)
1344 return wrapper
1345
1346 wrapped = times_three(isa.function)
1347 self.assertEqual(wrapped(1, 'x'), isa.MyClass(3, 'xxx'))
1348 self.assertIsNot(wrapped.__globals__, isa.function.__globals__)
1349 self.assertEqual(inspect.get_annotations(wrapped), {'a': int, 'b': str, 'return': isa.MyClass})
1350 self.assertEqual(inspect.get_annotations(wrapped, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1351 self.assertEqual(inspect.get_annotations(wrapped, eval_str=False), {'a': int, 'b': str, 'return': isa.MyClass})
1352
1353 def test_get_annotations_with_stringized_annotations(self):
1354 isa = inspect_stringized_annotations
1355 self.assertEqual(inspect.get_annotations(isa), {'a': 'int', 'b': 'str'})
1356 self.assertEqual(inspect.get_annotations(isa.MyClass), {'a': 'int', 'b': 'str'})
1357 self.assertEqual(inspect.get_annotations(isa.function), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1358 self.assertEqual(inspect.get_annotations(isa.function2), {'a': 'int', 'b': "'str'", 'c': 'MyClass', 'return': 'MyClass'})
1359 self.assertEqual(inspect.get_annotations(isa.function3), {'a': "'int'", 'b': "'str'", 'c': "'MyClass'"})
1360 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass), {})
1361 self.assertEqual(inspect.get_annotations(isa.unannotated_function), {})
1362
1363 self.assertEqual(inspect.get_annotations(isa, eval_str=True), {'a': int, 'b': str})
1364 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=True), {'a': int, 'b': str})
1365 self.assertEqual(inspect.get_annotations(isa.function, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1366 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=True), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1367 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=True), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1368 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=True), {})
1369 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=True), {})
1370
1371 self.assertEqual(inspect.get_annotations(isa, eval_str=False), {'a': 'int', 'b': 'str'})
1372 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=False), {'a': 'int', 'b': 'str'})
1373 self.assertEqual(inspect.get_annotations(isa.function, eval_str=False), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1374 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=False), {'a': 'int', 'b': "'str'", 'c': 'MyClass', 'return': 'MyClass'})
1375 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=False), {'a': "'int'", 'b': "'str'", 'c': "'MyClass'"})
1376 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=False), {})
1377 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=False), {})
1378
1379 isa2 = inspect_stringized_annotations_2
1380 self.assertEqual(inspect.get_annotations(isa2), {})
1381 self.assertEqual(inspect.get_annotations(isa2, eval_str=True), {})
1382 self.assertEqual(inspect.get_annotations(isa2, eval_str=False), {})
1383
1384 def times_three(fn):
1385 @functools.wraps(fn)
1386 def wrapper(a, b):
1387 return fn(a*3, b*3)
1388 return wrapper
1389
1390 wrapped = times_three(isa.function)
1391 self.assertEqual(wrapped(1, 'x'), isa.MyClass(3, 'xxx'))
1392 self.assertIsNot(wrapped.__globals__, isa.function.__globals__)
1393 self.assertEqual(inspect.get_annotations(wrapped), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1394 self.assertEqual(inspect.get_annotations(wrapped, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1395 self.assertEqual(inspect.get_annotations(wrapped, eval_str=False), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1396
1397 # test that local namespace lookups work
1398 self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations), {'x': 'mytype'})
1399 self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations, eval_str=True), {'x': int})
1400
1401
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001402class TestIsDataDescriptor(unittest.TestCase):
1403
1404 def test_custom_descriptors(self):
1405 class NonDataDescriptor:
1406 def __get__(self, value, type=None): pass
1407 class DataDescriptor0:
1408 def __set__(self, name, value): pass
1409 class DataDescriptor1:
1410 def __delete__(self, name): pass
1411 class DataDescriptor2:
1412 __set__ = None
1413 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1414 'class with only __get__ not a data descriptor')
1415 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1416 'class with __set__ is a data descriptor')
1417 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1418 'class with __delete__ is a data descriptor')
1419 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1420 'class with __set__ = None is a data descriptor')
1421
1422 def test_slot(self):
1423 class Slotted:
1424 __slots__ = 'foo',
1425 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1426 'a slot is a data descriptor')
1427
1428 def test_property(self):
1429 class Propertied:
1430 @property
1431 def a_property(self):
1432 pass
1433 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1434 'a property is a data descriptor')
1435
1436 def test_functions(self):
1437 class Test(object):
1438 def instance_method(self): pass
1439 @classmethod
1440 def class_method(cls): pass
1441 @staticmethod
1442 def static_method(): pass
1443 def function():
1444 pass
1445 a_lambda = lambda: None
1446 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1447 'a instance method is not a data descriptor')
1448 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1449 'a class method is not a data descriptor')
1450 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1451 'a static method is not a data descriptor')
1452 self.assertFalse(inspect.isdatadescriptor(function),
1453 'a function is not a data descriptor')
1454 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1455 'a lambda is not a data descriptor')
1456
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001457
Nick Coghlan2f92e542012-06-23 19:39:55 +10001458_global_ref = object()
1459class TestGetClosureVars(unittest.TestCase):
1460
1461 def test_name_resolution(self):
1462 # Basic test of the 4 different resolution mechanisms
1463 def f(nonlocal_ref):
1464 def g(local_ref):
1465 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
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_generator_closure(self):
1477 def f(nonlocal_ref):
1478 def g(local_ref):
1479 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1480 yield
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(f(_arg)), expected)
1490
1491 def test_method_closure(self):
1492 class C:
1493 def f(self, nonlocal_ref):
1494 def g(local_ref):
1495 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1496 return g
1497 _arg = object()
1498 nonlocal_vars = {"nonlocal_ref": _arg}
1499 global_vars = {"_global_ref": _global_ref}
1500 builtin_vars = {"print": print}
1501 unbound_names = {"unbound_ref"}
1502 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1503 builtin_vars, unbound_names)
1504 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1505
1506 def test_nonlocal_vars(self):
1507 # More complex tests of nonlocal resolution
1508 def _nonlocal_vars(f):
1509 return inspect.getclosurevars(f).nonlocals
1510
1511 def make_adder(x):
1512 def add(y):
1513 return x + y
1514 return add
1515
1516 def curry(func, arg1):
1517 return lambda arg2: func(arg1, arg2)
1518
1519 def less_than(a, b):
1520 return a < b
1521
1522 # The infamous Y combinator.
1523 def Y(le):
1524 def g(f):
1525 return le(lambda x: f(f)(x))
1526 Y.g_ref = g
1527 return g(g)
1528
1529 def check_y_combinator(func):
1530 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1531
1532 inc = make_adder(1)
1533 add_two = make_adder(2)
1534 greater_than_five = curry(less_than, 5)
1535
1536 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1537 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1538 self.assertEqual(_nonlocal_vars(greater_than_five),
1539 {'arg1': 5, 'func': less_than})
1540 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1541 {'x': 3})
1542 Y(check_y_combinator)
1543
1544 def test_getclosurevars_empty(self):
1545 def foo(): pass
1546 _empty = inspect.ClosureVars({}, {}, {}, set())
1547 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1548 self.assertEqual(inspect.getclosurevars(foo), _empty)
1549
1550 def test_getclosurevars_error(self):
1551 class T: pass
1552 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1553 self.assertRaises(TypeError, inspect.getclosurevars, list)
1554 self.assertRaises(TypeError, inspect.getclosurevars, {})
1555
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001556 def _private_globals(self):
1557 code = """def f(): print(path)"""
1558 ns = {}
1559 exec(code, ns)
1560 return ns["f"], ns
1561
1562 def test_builtins_fallback(self):
1563 f, ns = self._private_globals()
1564 ns.pop("__builtins__", None)
1565 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1566 self.assertEqual(inspect.getclosurevars(f), expected)
1567
1568 def test_builtins_as_dict(self):
1569 f, ns = self._private_globals()
1570 ns["__builtins__"] = {"path":1}
1571 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1572 self.assertEqual(inspect.getclosurevars(f), expected)
1573
1574 def test_builtins_as_module(self):
1575 f, ns = self._private_globals()
1576 ns["__builtins__"] = os
1577 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1578 self.assertEqual(inspect.getclosurevars(f), expected)
1579
Nick Coghlan2f92e542012-06-23 19:39:55 +10001580
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001581class TestGetcallargsFunctions(unittest.TestCase):
1582
1583 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1584 locs = dict(locs or {}, func=func)
1585 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001586 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1587 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001588 self.assertEqual(r1, r2)
1589
1590 def assertEqualException(self, func, call_param_string, locs=None):
1591 locs = dict(locs or {}, func=func)
1592 try:
1593 eval('func(%s)' % call_param_string, None, locs)
1594 except Exception as e:
1595 ex1 = e
1596 else:
1597 self.fail('Exception not raised')
1598 try:
Pablo Galindoaee19f52019-05-16 21:08:15 +01001599 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1600 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001601 except Exception as e:
1602 ex2 = e
1603 else:
1604 self.fail('Exception not raised')
1605 self.assertIs(type(ex1), type(ex2))
1606 self.assertEqual(str(ex1), str(ex2))
1607 del ex1, ex2
1608
1609 def makeCallable(self, signature):
1610 """Create a function that returns its locals()"""
1611 code = "lambda %s: locals()"
1612 return eval(code % signature)
1613
1614 def test_plain(self):
1615 f = self.makeCallable('a, b=1')
1616 self.assertEqualCallArgs(f, '2')
1617 self.assertEqualCallArgs(f, '2, 3')
1618 self.assertEqualCallArgs(f, 'a=2')
1619 self.assertEqualCallArgs(f, 'b=3, a=2')
1620 self.assertEqualCallArgs(f, '2, b=3')
1621 # expand *iterable / **mapping
1622 self.assertEqualCallArgs(f, '*(2,)')
1623 self.assertEqualCallArgs(f, '*[2]')
1624 self.assertEqualCallArgs(f, '*(2, 3)')
1625 self.assertEqualCallArgs(f, '*[2, 3]')
1626 self.assertEqualCallArgs(f, '**{"a":2}')
1627 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1628 self.assertEqualCallArgs(f, '2, **{"b":3}')
1629 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1630 # expand UserList / UserDict
1631 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1632 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1633 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1634 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1635 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1636
1637 def test_varargs(self):
1638 f = self.makeCallable('a, b=1, *c')
1639 self.assertEqualCallArgs(f, '2')
1640 self.assertEqualCallArgs(f, '2, 3')
1641 self.assertEqualCallArgs(f, '2, 3, 4')
1642 self.assertEqualCallArgs(f, '*(2,3,4)')
1643 self.assertEqualCallArgs(f, '2, *[3,4]')
1644 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1645
1646 def test_varkw(self):
1647 f = self.makeCallable('a, b=1, **c')
1648 self.assertEqualCallArgs(f, 'a=2')
1649 self.assertEqualCallArgs(f, '2, b=3, c=4')
1650 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1651 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1652 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1653 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1654 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1655 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1656 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1657
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001658 def test_varkw_only(self):
1659 # issue11256:
1660 f = self.makeCallable('**c')
1661 self.assertEqualCallArgs(f, '')
1662 self.assertEqualCallArgs(f, 'a=1')
1663 self.assertEqualCallArgs(f, 'a=1, b=2')
1664 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1665 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1666 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1667
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001668 def test_keyword_only(self):
1669 f = self.makeCallable('a=3, *, c, d=2')
1670 self.assertEqualCallArgs(f, 'c=3')
1671 self.assertEqualCallArgs(f, 'c=3, a=3')
1672 self.assertEqualCallArgs(f, 'a=2, c=4')
1673 self.assertEqualCallArgs(f, '4, c=4')
1674 self.assertEqualException(f, '')
1675 self.assertEqualException(f, '3')
1676 self.assertEqualException(f, 'a=3')
1677 self.assertEqualException(f, 'd=4')
1678
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001679 f = self.makeCallable('*, c, d=2')
1680 self.assertEqualCallArgs(f, 'c=3')
1681 self.assertEqualCallArgs(f, 'c=3, d=4')
1682 self.assertEqualCallArgs(f, 'd=4, c=3')
1683
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001684 def test_multiple_features(self):
1685 f = self.makeCallable('a, b=2, *f, **g')
1686 self.assertEqualCallArgs(f, '2, 3, 7')
1687 self.assertEqualCallArgs(f, '2, 3, x=8')
1688 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1689 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1690 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1691 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1692 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1693 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1694 '(4,[5,6])]), **collections.UserDict('
1695 'y=9, z=10)')
1696
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001697 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1698 self.assertEqualCallArgs(f, '2, 3, x=8')
1699 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1700 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1701 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1702 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1703 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1704 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1705 '(4,[5,6])]), q=0, **collections.UserDict('
1706 'y=9, z=10)')
1707
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001708 def test_errors(self):
1709 f0 = self.makeCallable('')
1710 f1 = self.makeCallable('a, b')
1711 f2 = self.makeCallable('a, b=1')
1712 # f0 takes no arguments
1713 self.assertEqualException(f0, '1')
1714 self.assertEqualException(f0, 'x=1')
1715 self.assertEqualException(f0, '1,x=1')
1716 # f1 takes exactly 2 arguments
1717 self.assertEqualException(f1, '')
1718 self.assertEqualException(f1, '1')
1719 self.assertEqualException(f1, 'a=2')
1720 self.assertEqualException(f1, 'b=3')
1721 # f2 takes at least 1 argument
1722 self.assertEqualException(f2, '')
1723 self.assertEqualException(f2, 'b=3')
1724 for f in f1, f2:
1725 # f1/f2 takes exactly/at most 2 arguments
1726 self.assertEqualException(f, '2, 3, 4')
1727 self.assertEqualException(f, '1, 2, 3, a=1')
1728 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001729 # XXX: success of this one depends on dict order
1730 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001731 # f got an unexpected keyword argument
1732 self.assertEqualException(f, 'c=2')
1733 self.assertEqualException(f, '2, c=3')
1734 self.assertEqualException(f, '2, 3, c=4')
1735 self.assertEqualException(f, '2, c=4, b=3')
1736 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1737 # f got multiple values for keyword argument
1738 self.assertEqualException(f, '1, a=2')
1739 self.assertEqualException(f, '1, **{"a":2}')
1740 self.assertEqualException(f, '1, 2, b=3')
1741 # XXX: Python inconsistency
1742 # - for functions and bound methods: unexpected keyword 'c'
1743 # - for unbound methods: multiple values for keyword 'a'
1744 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001745 # issue11256:
1746 f3 = self.makeCallable('**c')
1747 self.assertEqualException(f3, '1, 2')
1748 self.assertEqualException(f3, '1, 2, a=1, b=2')
1749 f4 = self.makeCallable('*, a, b=0')
1750 self.assertEqualException(f3, '1, 2')
1751 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001752
Yury Selivanov875df202014-03-27 18:23:03 -04001753 # issue #20816: getcallargs() fails to iterate over non-existent
1754 # kwonlydefaults and raises a wrong TypeError
1755 def f5(*, a): pass
1756 with self.assertRaisesRegex(TypeError,
1757 'missing 1 required keyword-only'):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001758 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001759
1760
Yury Selivanovdccfa132014-03-27 18:42:52 -04001761 # issue20817:
1762 def f6(a, b, c):
1763 pass
1764 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001765 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001766
Dong-hee Naa9cab432018-05-30 00:04:08 +09001767 # bpo-33197
1768 with self.assertRaisesRegex(ValueError,
1769 'variadic keyword parameters cannot'
1770 ' have default values'):
1771 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1772 default=42)
1773 with self.assertRaisesRegex(ValueError,
1774 "value 5 is not a valid Parameter.kind"):
1775 inspect.Parameter("bar", kind=5, default=42)
1776
1777 with self.assertRaisesRegex(TypeError,
1778 'name must be a str, not a int'):
1779 inspect.Parameter(123, kind=4)
1780
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001781class TestGetcallargsMethods(TestGetcallargsFunctions):
1782
1783 def setUp(self):
1784 class Foo(object):
1785 pass
1786 self.cls = Foo
1787 self.inst = Foo()
1788
1789 def makeCallable(self, signature):
1790 assert 'self' not in signature
1791 mk = super(TestGetcallargsMethods, self).makeCallable
1792 self.cls.method = mk('self, ' + signature)
1793 return self.inst.method
1794
1795class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1796
1797 def makeCallable(self, signature):
1798 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1799 return self.cls.method
1800
1801 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1802 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1803 *self._getAssertEqualParams(func, call_params_string, locs))
1804
1805 def assertEqualException(self, func, call_params_string, locs=None):
1806 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1807 *self._getAssertEqualParams(func, call_params_string, locs))
1808
1809 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1810 assert 'inst' not in call_params_string
1811 locs = dict(locs or {}, inst=self.inst)
1812 return (func, 'inst,' + call_params_string, locs)
1813
Michael Foord95fc51d2010-11-20 15:07:30 +00001814
1815class TestGetattrStatic(unittest.TestCase):
1816
1817 def test_basic(self):
1818 class Thing(object):
1819 x = object()
1820
1821 thing = Thing()
1822 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1823 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1824 with self.assertRaises(AttributeError):
1825 inspect.getattr_static(thing, 'y')
1826
1827 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1828
1829 def test_inherited(self):
1830 class Thing(object):
1831 x = object()
1832 class OtherThing(Thing):
1833 pass
1834
1835 something = OtherThing()
1836 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1837
1838 def test_instance_attr(self):
1839 class Thing(object):
1840 x = 2
1841 def __init__(self, x):
1842 self.x = x
1843 thing = Thing(3)
1844 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1845 del thing.x
1846 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1847
1848 def test_property(self):
1849 class Thing(object):
1850 @property
1851 def x(self):
1852 raise AttributeError("I'm pretending not to exist")
1853 thing = Thing()
1854 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1855
Ezio Melotti75cbd732011-04-28 00:59:29 +03001856 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001857 class descriptor(object):
1858 def __get__(*_):
1859 raise AttributeError("I'm pretending not to exist")
1860 desc = descriptor()
1861 class Thing(object):
1862 x = desc
1863 thing = Thing()
1864 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1865
1866 def test_classAttribute(self):
1867 class Thing(object):
1868 x = object()
1869
1870 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1871
Ethan Furmane03ea372013-09-25 07:14:41 -07001872 def test_classVirtualAttribute(self):
1873 class Thing(object):
1874 @types.DynamicClassAttribute
1875 def x(self):
1876 return self._x
1877 _x = object()
1878
1879 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1880
Michael Foord95fc51d2010-11-20 15:07:30 +00001881 def test_inherited_classattribute(self):
1882 class Thing(object):
1883 x = object()
1884 class OtherThing(Thing):
1885 pass
1886
1887 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1888
1889 def test_slots(self):
1890 class Thing(object):
1891 y = 'bar'
1892 __slots__ = ['x']
1893 def __init__(self):
1894 self.x = 'foo'
1895 thing = Thing()
1896 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1897 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1898
1899 del thing.x
1900 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1901
1902 def test_metaclass(self):
1903 class meta(type):
1904 attr = 'foo'
1905 class Thing(object, metaclass=meta):
1906 pass
1907 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1908
1909 class sub(meta):
1910 pass
1911 class OtherThing(object, metaclass=sub):
1912 x = 3
1913 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1914
1915 class OtherOtherThing(OtherThing):
1916 pass
1917 # this test is odd, but it was added as it exposed a bug
1918 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1919
1920 def test_no_dict_no_slots(self):
1921 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1922 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1923
1924 def test_no_dict_no_slots_instance_member(self):
1925 # returns descriptor
Inada Naokifb786922021-04-06 11:18:41 +09001926 with open(__file__, encoding='utf-8') as handle:
Michael Foord95fc51d2010-11-20 15:07:30 +00001927 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1928
1929 def test_inherited_slots(self):
1930 # returns descriptor
1931 class Thing(object):
1932 __slots__ = ['x']
1933 def __init__(self):
1934 self.x = 'foo'
1935
1936 class OtherThing(Thing):
1937 pass
1938 # it would be nice if this worked...
1939 # we get the descriptor instead of the instance attribute
1940 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1941
1942 def test_descriptor(self):
1943 class descriptor(object):
1944 def __get__(self, instance, owner):
1945 return 3
1946 class Foo(object):
1947 d = descriptor()
1948
1949 foo = Foo()
1950
1951 # for a non data descriptor we return the instance attribute
1952 foo.__dict__['d'] = 1
1953 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1954
Mike53f7a7c2017-12-14 14:04:53 +03001955 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001956 # descriptor
1957 descriptor.__set__ = lambda s, i, v: None
1958 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1959
1960
1961 def test_metaclass_with_descriptor(self):
1962 class descriptor(object):
1963 def __get__(self, instance, owner):
1964 return 3
1965 class meta(type):
1966 d = descriptor()
1967 class Thing(object, metaclass=meta):
1968 pass
1969 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1970
1971
Michael Foordcc7ebb82010-11-20 16:20:16 +00001972 def test_class_as_property(self):
1973 class Base(object):
1974 foo = 3
1975
1976 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001977 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001978 @property
1979 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001980 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001981 return object
1982
Michael Foord35184ed2010-11-20 16:58:30 +00001983 instance = Something()
1984 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1985 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001986 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1987
Michael Foorde5162652010-11-20 16:40:44 +00001988 def test_mro_as_property(self):
1989 class Meta(type):
1990 @property
1991 def __mro__(self):
1992 return (object,)
1993
1994 class Base(object):
1995 foo = 3
1996
1997 class Something(Base, metaclass=Meta):
1998 pass
1999
2000 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
2001 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
2002
Michael Foorddcebe0f2011-03-15 19:20:44 -04002003 def test_dict_as_property(self):
2004 test = self
2005 test.called = False
2006
2007 class Foo(dict):
2008 a = 3
2009 @property
2010 def __dict__(self):
2011 test.called = True
2012 return {}
2013
2014 foo = Foo()
2015 foo.a = 4
2016 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
2017 self.assertFalse(test.called)
2018
2019 def test_custom_object_dict(self):
2020 test = self
2021 test.called = False
2022
2023 class Custom(dict):
2024 def get(self, key, default=None):
2025 test.called = True
2026 super().get(key, default)
2027
2028 class Foo(object):
2029 a = 3
2030 foo = Foo()
2031 foo.__dict__ = Custom()
2032 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
2033 self.assertFalse(test.called)
2034
2035 def test_metaclass_dict_as_property(self):
2036 class Meta(type):
2037 @property
2038 def __dict__(self):
2039 self.executed = True
2040
2041 class Thing(metaclass=Meta):
2042 executed = False
2043
2044 def __init__(self):
2045 self.spam = 42
2046
2047 instance = Thing()
2048 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
2049 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00002050
Michael Foorda51623b2011-12-18 22:01:40 +00002051 def test_module(self):
2052 sentinel = object()
2053 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
2054 sentinel)
2055
Michael Foord3ba95f82011-12-22 01:13:37 +00002056 def test_metaclass_with_metaclass_with_dict_as_property(self):
2057 class MetaMeta(type):
2058 @property
2059 def __dict__(self):
2060 self.executed = True
2061 return dict(spam=42)
2062
2063 class Meta(type, metaclass=MetaMeta):
2064 executed = False
2065
2066 class Thing(metaclass=Meta):
2067 pass
2068
2069 with self.assertRaises(AttributeError):
2070 inspect.getattr_static(Thing, "spam")
2071 self.assertFalse(Thing.executed)
2072
Nick Coghlane0f04652010-11-21 03:44:04 +00002073class TestGetGeneratorState(unittest.TestCase):
2074
2075 def setUp(self):
2076 def number_generator():
2077 for number in range(5):
2078 yield number
2079 self.generator = number_generator()
2080
2081 def _generatorstate(self):
2082 return inspect.getgeneratorstate(self.generator)
2083
2084 def test_created(self):
2085 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
2086
2087 def test_suspended(self):
2088 next(self.generator)
2089 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
2090
2091 def test_closed_after_exhaustion(self):
2092 for i in self.generator:
2093 pass
2094 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
2095
2096 def test_closed_after_immediate_exception(self):
2097 with self.assertRaises(RuntimeError):
2098 self.generator.throw(RuntimeError)
2099 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
2100
2101 def test_running(self):
2102 # As mentioned on issue #10220, checking for the RUNNING state only
2103 # makes sense inside the generator itself.
2104 # The following generator checks for this by using the closure's
2105 # reference to self and the generator state checking helper method
2106 def running_check_generator():
2107 for number in range(5):
2108 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
2109 yield number
2110 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
2111 self.generator = running_check_generator()
2112 # Running up to the first yield
2113 next(self.generator)
2114 # Running after the first yield
2115 next(self.generator)
2116
Nick Coghlan7921b9f2010-11-30 06:36:04 +00002117 def test_easy_debugging(self):
2118 # repr() and str() of a generator state should contain the state name
2119 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
2120 for name in names:
2121 state = getattr(inspect, name)
2122 self.assertIn(name, repr(state))
2123 self.assertIn(name, str(state))
2124
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10002125 def test_getgeneratorlocals(self):
2126 def each(lst, a=None):
2127 b=(1, 2, 3)
2128 for v in lst:
2129 if v == 3:
2130 c = 12
2131 yield v
2132
2133 numbers = each([1, 2, 3])
2134 self.assertEqual(inspect.getgeneratorlocals(numbers),
2135 {'a': None, 'lst': [1, 2, 3]})
2136 next(numbers)
2137 self.assertEqual(inspect.getgeneratorlocals(numbers),
2138 {'a': None, 'lst': [1, 2, 3], 'v': 1,
2139 'b': (1, 2, 3)})
2140 next(numbers)
2141 self.assertEqual(inspect.getgeneratorlocals(numbers),
2142 {'a': None, 'lst': [1, 2, 3], 'v': 2,
2143 'b': (1, 2, 3)})
2144 next(numbers)
2145 self.assertEqual(inspect.getgeneratorlocals(numbers),
2146 {'a': None, 'lst': [1, 2, 3], 'v': 3,
2147 'b': (1, 2, 3), 'c': 12})
2148 try:
2149 next(numbers)
2150 except StopIteration:
2151 pass
2152 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
2153
2154 def test_getgeneratorlocals_empty(self):
2155 def yield_one():
2156 yield 1
2157 one = yield_one()
2158 self.assertEqual(inspect.getgeneratorlocals(one), {})
2159 try:
2160 next(one)
2161 except StopIteration:
2162 pass
2163 self.assertEqual(inspect.getgeneratorlocals(one), {})
2164
2165 def test_getgeneratorlocals_error(self):
2166 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
2167 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
2168 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
2169 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
2170
Nick Coghlane0f04652010-11-21 03:44:04 +00002171
Yury Selivanov5376ba92015-06-22 12:19:30 -04002172class TestGetCoroutineState(unittest.TestCase):
2173
2174 def setUp(self):
2175 @types.coroutine
2176 def number_coroutine():
2177 for number in range(5):
2178 yield number
2179 async def coroutine():
2180 await number_coroutine()
2181 self.coroutine = coroutine()
2182
2183 def tearDown(self):
2184 self.coroutine.close()
2185
2186 def _coroutinestate(self):
2187 return inspect.getcoroutinestate(self.coroutine)
2188
2189 def test_created(self):
2190 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
2191
2192 def test_suspended(self):
2193 self.coroutine.send(None)
2194 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
2195
2196 def test_closed_after_exhaustion(self):
2197 while True:
2198 try:
2199 self.coroutine.send(None)
2200 except StopIteration:
2201 break
2202
2203 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2204
2205 def test_closed_after_immediate_exception(self):
2206 with self.assertRaises(RuntimeError):
2207 self.coroutine.throw(RuntimeError)
2208 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2209
2210 def test_easy_debugging(self):
2211 # repr() and str() of a coroutine state should contain the state name
2212 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2213 for name in names:
2214 state = getattr(inspect, name)
2215 self.assertIn(name, repr(state))
2216 self.assertIn(name, str(state))
2217
2218 def test_getcoroutinelocals(self):
2219 @types.coroutine
2220 def gencoro():
2221 yield
2222
2223 gencoro = gencoro()
2224 async def func(a=None):
2225 b = 'spam'
2226 await gencoro
2227
2228 coro = func()
2229 self.assertEqual(inspect.getcoroutinelocals(coro),
2230 {'a': None, 'gencoro': gencoro})
2231 coro.send(None)
2232 self.assertEqual(inspect.getcoroutinelocals(coro),
2233 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2234
2235
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002236class MySignature(inspect.Signature):
2237 # Top-level to make it picklable;
2238 # used in test_signature_object_pickle
2239 pass
2240
2241class MyParameter(inspect.Parameter):
2242 # Top-level to make it picklable;
2243 # used in test_signature_object_pickle
2244 pass
2245
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002246
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002247
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002248class TestSignatureObject(unittest.TestCase):
2249 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002250 def signature(func, **kw):
2251 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002252 return (tuple((param.name,
2253 (... if param.default is param.empty else param.default),
2254 (... if param.annotation is param.empty
2255 else param.annotation),
2256 str(param.kind).lower())
2257 for param in sig.parameters.values()),
2258 (... if sig.return_annotation is sig.empty
2259 else sig.return_annotation))
2260
2261 def test_signature_object(self):
2262 S = inspect.Signature
2263 P = inspect.Parameter
2264
2265 self.assertEqual(str(S()), '()')
Jens Reidel611836a2020-03-18 03:22:46 +01002266 self.assertEqual(repr(S().parameters), 'mappingproxy(OrderedDict())')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002267
Yury Selivanov07a9e452014-01-29 10:58:16 -05002268 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002269 pass
2270 sig = inspect.signature(test)
2271 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002272 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002273 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002274 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002275 args = sig.parameters['args']
2276 ko = sig.parameters['ko']
2277 kwargs = sig.parameters['kwargs']
2278
2279 S((po, pk, args, ko, kwargs))
2280
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002281 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002282 S((pk, po, args, ko, kwargs))
2283
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002284 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002285 S((po, args, pk, ko, kwargs))
2286
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002287 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002288 S((args, po, pk, ko, kwargs))
2289
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002290 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002291 S((po, pk, args, kwargs, ko))
2292
2293 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002294 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002295 S((po, pk, args, kwargs2, ko))
2296
Yury Selivanov07a9e452014-01-29 10:58:16 -05002297 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2298 S((pod, po))
2299
2300 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2301 S((po, pkd, pk))
2302
2303 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2304 S((pkd, pk))
2305
Yury Selivanov374375d2014-03-27 12:41:53 -04002306 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002307 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002308
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002309 def test_signature_object_pickle(self):
2310 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2311 foo_partial = functools.partial(foo, a=1)
2312
2313 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002314
2315 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2316 with self.subTest(pickle_ver=ver, subclass=False):
2317 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2318 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002319
2320 # Test that basic sub-classing works
2321 sig = inspect.signature(foo)
2322 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2323 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2324 mysig = MySignature().replace(parameters=myparams.values(),
2325 return_annotation=sig.return_annotation)
2326 self.assertTrue(isinstance(mysig, MySignature))
2327 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2328
2329 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2330 with self.subTest(pickle_ver=ver, subclass=True):
2331 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2332 self.assertEqual(mysig, sig_pickled)
2333 self.assertTrue(isinstance(sig_pickled, MySignature))
2334 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2335 MyParameter))
2336
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002337 def test_signature_immutability(self):
2338 def test(a):
2339 pass
2340 sig = inspect.signature(test)
2341
2342 with self.assertRaises(AttributeError):
2343 sig.foo = 'bar'
2344
2345 with self.assertRaises(TypeError):
2346 sig.parameters['a'] = None
2347
2348 def test_signature_on_noarg(self):
2349 def test():
2350 pass
2351 self.assertEqual(self.signature(test), ((), ...))
2352
2353 def test_signature_on_wargs(self):
2354 def test(a, b:'foo') -> 123:
2355 pass
2356 self.assertEqual(self.signature(test),
2357 ((('a', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002358 ('b', ..., 'foo', "positional_or_keyword")),
2359 123))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002360
2361 def test_signature_on_wkwonly(self):
2362 def test(*, a:float, b:str) -> int:
2363 pass
2364 self.assertEqual(self.signature(test),
2365 ((('a', ..., float, "keyword_only"),
2366 ('b', ..., str, "keyword_only")),
2367 int))
2368
2369 def test_signature_on_complex_args(self):
2370 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2371 pass
2372 self.assertEqual(self.signature(test),
2373 ((('a', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002374 ('b', 10, 'foo', "positional_or_keyword"),
2375 ('args', ..., 'bar', "var_positional"),
2376 ('spam', ..., 'baz', "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002377 ('ham', 123, ..., "keyword_only"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002378 ('kwargs', ..., int, "var_keyword")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002379 ...))
2380
Dong-hee Na378d7062017-05-18 04:00:51 +09002381 def test_signature_without_self(self):
2382 def test_args_only(*args): # NOQA
2383 pass
2384
2385 def test_args_kwargs_only(*args, **kwargs): # NOQA
2386 pass
2387
2388 class A:
2389 @classmethod
2390 def test_classmethod(*args): # NOQA
2391 pass
2392
2393 @staticmethod
2394 def test_staticmethod(*args): # NOQA
2395 pass
2396
2397 f1 = functools.partialmethod((test_classmethod), 1)
2398 f2 = functools.partialmethod((test_args_only), 1)
2399 f3 = functools.partialmethod((test_staticmethod), 1)
2400 f4 = functools.partialmethod((test_args_kwargs_only),1)
2401
2402 self.assertEqual(self.signature(test_args_only),
2403 ((('args', ..., ..., 'var_positional'),), ...))
2404 self.assertEqual(self.signature(test_args_kwargs_only),
2405 ((('args', ..., ..., 'var_positional'),
2406 ('kwargs', ..., ..., 'var_keyword')), ...))
2407 self.assertEqual(self.signature(A.f1),
2408 ((('args', ..., ..., 'var_positional'),), ...))
2409 self.assertEqual(self.signature(A.f2),
2410 ((('args', ..., ..., 'var_positional'),), ...))
2411 self.assertEqual(self.signature(A.f3),
2412 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002413 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002414 ((('args', ..., ..., 'var_positional'),
2415 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002416 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002417 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2418 "Signature information for builtins requires docstrings")
2419 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002420 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002421
Larry Hastings5c661892014-01-24 06:17:25 -08002422 def test_unbound_method(o):
2423 """Use this to test unbound methods (things that should have a self)"""
2424 signature = inspect.signature(o)
2425 self.assertTrue(isinstance(signature, inspect.Signature))
2426 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2427 return signature
2428
2429 def test_callable(o):
2430 """Use this to test bound methods or normal callables (things that don't expect self)"""
2431 signature = inspect.signature(o)
2432 self.assertTrue(isinstance(signature, inspect.Signature))
2433 if signature.parameters:
2434 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2435 return signature
2436
2437 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002438 def p(name): return signature.parameters[name].default
2439 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002440 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002441 self.assertEqual(p('d'), 3.14)
2442 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002443 self.assertEqual(p('n'), None)
2444 self.assertEqual(p('t'), True)
2445 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002446 self.assertEqual(p('local'), 3)
2447 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002448 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002449
Larry Hastings5c661892014-01-24 06:17:25 -08002450 test_callable(object)
2451
2452 # normal method
2453 # (PyMethodDescr_Type, "method_descriptor")
2454 test_unbound_method(_pickle.Pickler.dump)
2455 d = _pickle.Pickler(io.StringIO())
2456 test_callable(d.dump)
2457
2458 # static method
Serhiy Storchaka279f4462019-09-14 12:24:05 +03002459 test_callable(bytes.maketrans)
2460 test_callable(b'abc'.maketrans)
Larry Hastings5c661892014-01-24 06:17:25 -08002461
2462 # class method
2463 test_callable(dict.fromkeys)
2464 test_callable({}.fromkeys)
2465
2466 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2467 test_unbound_method(type.__call__)
2468 test_unbound_method(int.__add__)
2469 test_callable((3).__add__)
2470
2471 # _PyMethodWrapper_Type
2472 # support for 'method-wrapper'
2473 test_callable(min.__call__)
2474
Larry Hastings2623c8c2014-02-08 22:15:29 -08002475 # This doesn't work now.
2476 # (We don't have a valid signature for "type" in 3.4)
2477 with self.assertRaisesRegex(ValueError, "no signature found"):
2478 class ThisWorksNow:
2479 __call__ = type
2480 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002481
Yury Selivanov056e2652014-03-02 12:25:27 -05002482 # Regression test for issue #20786
2483 test_unbound_method(dict.__delitem__)
2484 test_unbound_method(property.__delete__)
2485
Zachary Ware8ef887c2015-04-13 18:22:35 -05002486 # Regression test for issue #20586
2487 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2488
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002489 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002490 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2491 "Signature information for builtins requires docstrings")
2492 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002493 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002494 func = _testcapi.docstring_with_signature_with_defaults
2495
2496 def decorator(func):
2497 @functools.wraps(func)
2498 def wrapper(*args, **kwargs) -> int:
2499 return func(*args, **kwargs)
2500 return wrapper
2501
2502 decorated_func = decorator(func)
2503
2504 self.assertEqual(inspect.signature(func),
2505 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002506
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002507 def wrapper_like(*args, **kwargs) -> int: pass
2508 self.assertEqual(inspect.signature(decorated_func,
2509 follow_wrapped=False),
2510 inspect.signature(wrapper_like))
2511
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002512 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002513 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002514 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002515 with self.assertRaisesRegex(ValueError,
2516 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002517 inspect.signature(_testcapi.docstring_no_signature)
2518
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002519 with self.assertRaisesRegex(ValueError,
2520 'no signature found for builtin'):
2521 inspect.signature(str)
2522
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002523 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002524 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002525 inspect.signature(42)
2526
Yury Selivanov63da7c72014-01-31 14:48:37 -05002527 def test_signature_from_functionlike_object(self):
2528 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2529 pass
2530
2531 class funclike:
2532 # Has to be callable, and have correct
2533 # __code__, __annotations__, __defaults__, __name__,
2534 # and __kwdefaults__ attributes
2535
2536 def __init__(self, func):
2537 self.__name__ = func.__name__
2538 self.__code__ = func.__code__
2539 self.__annotations__ = func.__annotations__
2540 self.__defaults__ = func.__defaults__
2541 self.__kwdefaults__ = func.__kwdefaults__
2542 self.func = func
2543
2544 def __call__(self, *args, **kwargs):
2545 return self.func(*args, **kwargs)
2546
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002547 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002548
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002549 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002550 self.assertEqual(sig_funclike, sig_func)
2551
2552 sig_funclike = inspect.signature(funclike(func))
2553 self.assertEqual(sig_funclike, sig_func)
2554
2555 # If object is not a duck type of function, then
2556 # signature will try to get a signature for its '__call__'
2557 # method
2558 fl = funclike(func)
2559 del fl.__defaults__
2560 self.assertEqual(self.signature(fl),
2561 ((('args', ..., ..., "var_positional"),
2562 ('kwargs', ..., ..., "var_keyword")),
2563 ...))
2564
Yury Selivanova773de02014-02-21 18:30:53 -05002565 # Test with cython-like builtins:
2566 _orig_isdesc = inspect.ismethoddescriptor
2567 def _isdesc(obj):
2568 if hasattr(obj, '_builtinmock'):
2569 return True
2570 return _orig_isdesc(obj)
2571
2572 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2573 builtin_func = funclike(func)
2574 # Make sure that our mock setup is working
2575 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2576 builtin_func._builtinmock = True
2577 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2578 self.assertEqual(inspect.signature(builtin_func), sig_func)
2579
Yury Selivanov63da7c72014-01-31 14:48:37 -05002580 def test_signature_functionlike_class(self):
2581 # We only want to duck type function-like objects,
2582 # not classes.
2583
2584 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2585 pass
2586
2587 class funclike:
2588 def __init__(self, marker):
2589 pass
2590
2591 __name__ = func.__name__
2592 __code__ = func.__code__
2593 __annotations__ = func.__annotations__
2594 __defaults__ = func.__defaults__
2595 __kwdefaults__ = func.__kwdefaults__
2596
Yury Selivanov63da7c72014-01-31 14:48:37 -05002597 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2598
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002599 def test_signature_on_method(self):
2600 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002601 def __init__(*args):
2602 pass
2603 def m1(self, arg1, arg2=1) -> int:
2604 pass
2605 def m2(*args):
2606 pass
2607 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002608 pass
2609
Yury Selivanov62560fb2014-01-28 12:26:24 -05002610 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002611 ((('arg1', ..., ..., "positional_or_keyword"),
2612 ('arg2', 1, ..., "positional_or_keyword")),
2613 int))
2614
Yury Selivanov62560fb2014-01-28 12:26:24 -05002615 self.assertEqual(self.signature(Test().m2),
2616 ((('args', ..., ..., "var_positional"),),
2617 ...))
2618
2619 self.assertEqual(self.signature(Test),
2620 ((('args', ..., ..., "var_positional"),),
2621 ...))
2622
2623 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2624 self.signature(Test())
2625
Yury Selivanov46c759d2015-05-27 21:56:53 -04002626 def test_signature_wrapped_bound_method(self):
2627 # Issue 24298
2628 class Test:
2629 def m1(self, arg1, arg2=1) -> int:
2630 pass
2631 @functools.wraps(Test().m1)
2632 def m1d(*args, **kwargs):
2633 pass
2634 self.assertEqual(self.signature(m1d),
2635 ((('arg1', ..., ..., "positional_or_keyword"),
2636 ('arg2', 1, ..., "positional_or_keyword")),
2637 int))
2638
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002639 def test_signature_on_classmethod(self):
2640 class Test:
2641 @classmethod
2642 def foo(cls, arg1, *, arg2=1):
2643 pass
2644
2645 meth = Test().foo
2646 self.assertEqual(self.signature(meth),
2647 ((('arg1', ..., ..., "positional_or_keyword"),
2648 ('arg2', 1, ..., "keyword_only")),
2649 ...))
2650
2651 meth = Test.foo
2652 self.assertEqual(self.signature(meth),
2653 ((('arg1', ..., ..., "positional_or_keyword"),
2654 ('arg2', 1, ..., "keyword_only")),
2655 ...))
2656
2657 def test_signature_on_staticmethod(self):
2658 class Test:
2659 @staticmethod
2660 def foo(cls, *, arg):
2661 pass
2662
2663 meth = Test().foo
2664 self.assertEqual(self.signature(meth),
2665 ((('cls', ..., ..., "positional_or_keyword"),
2666 ('arg', ..., ..., "keyword_only")),
2667 ...))
2668
2669 meth = Test.foo
2670 self.assertEqual(self.signature(meth),
2671 ((('cls', ..., ..., "positional_or_keyword"),
2672 ('arg', ..., ..., "keyword_only")),
2673 ...))
2674
2675 def test_signature_on_partial(self):
2676 from functools import partial
2677
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002678 Parameter = inspect.Parameter
2679
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002680 def test():
2681 pass
2682
2683 self.assertEqual(self.signature(partial(test)), ((), ...))
2684
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002685 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002686 inspect.signature(partial(test, 1))
2687
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002688 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002689 inspect.signature(partial(test, a=1))
2690
2691 def test(a, b, *, c, d):
2692 pass
2693
2694 self.assertEqual(self.signature(partial(test)),
2695 ((('a', ..., ..., "positional_or_keyword"),
2696 ('b', ..., ..., "positional_or_keyword"),
2697 ('c', ..., ..., "keyword_only"),
2698 ('d', ..., ..., "keyword_only")),
2699 ...))
2700
2701 self.assertEqual(self.signature(partial(test, 1)),
2702 ((('b', ..., ..., "positional_or_keyword"),
2703 ('c', ..., ..., "keyword_only"),
2704 ('d', ..., ..., "keyword_only")),
2705 ...))
2706
2707 self.assertEqual(self.signature(partial(test, 1, c=2)),
2708 ((('b', ..., ..., "positional_or_keyword"),
2709 ('c', 2, ..., "keyword_only"),
2710 ('d', ..., ..., "keyword_only")),
2711 ...))
2712
2713 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2714 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002715 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002716 ('c', 2, ..., "keyword_only"),
2717 ('d', ..., ..., "keyword_only")),
2718 ...))
2719
2720 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002721 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002722 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002723 ('d', ..., ..., "keyword_only")),
2724 ...))
2725
2726 self.assertEqual(self.signature(partial(test, a=1)),
2727 ((('a', 1, ..., "keyword_only"),
2728 ('b', ..., ..., "keyword_only"),
2729 ('c', ..., ..., "keyword_only"),
2730 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002731 ...))
2732
2733 def test(a, *args, b, **kwargs):
2734 pass
2735
2736 self.assertEqual(self.signature(partial(test, 1)),
2737 ((('args', ..., ..., "var_positional"),
2738 ('b', ..., ..., "keyword_only"),
2739 ('kwargs', ..., ..., "var_keyword")),
2740 ...))
2741
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002742 self.assertEqual(self.signature(partial(test, a=1)),
2743 ((('a', 1, ..., "keyword_only"),
2744 ('b', ..., ..., "keyword_only"),
2745 ('kwargs', ..., ..., "var_keyword")),
2746 ...))
2747
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002748 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2749 ((('args', ..., ..., "var_positional"),
2750 ('b', ..., ..., "keyword_only"),
2751 ('kwargs', ..., ..., "var_keyword")),
2752 ...))
2753
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002754 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2755 ((('args', ..., ..., "var_positional"),
2756 ('b', ..., ..., "keyword_only"),
2757 ('kwargs', ..., ..., "var_keyword")),
2758 ...))
2759
2760 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2761 ((('args', ..., ..., "var_positional"),
2762 ('b', 0, ..., "keyword_only"),
2763 ('kwargs', ..., ..., "var_keyword")),
2764 ...))
2765
2766 self.assertEqual(self.signature(partial(test, b=0)),
2767 ((('a', ..., ..., "positional_or_keyword"),
2768 ('args', ..., ..., "var_positional"),
2769 ('b', 0, ..., "keyword_only"),
2770 ('kwargs', ..., ..., "var_keyword")),
2771 ...))
2772
2773 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2774 ((('a', ..., ..., "positional_or_keyword"),
2775 ('args', ..., ..., "var_positional"),
2776 ('b', 0, ..., "keyword_only"),
2777 ('kwargs', ..., ..., "var_keyword")),
2778 ...))
2779
2780 def test(a, b, c:int) -> 42:
2781 pass
2782
2783 sig = test.__signature__ = inspect.signature(test)
2784
2785 self.assertEqual(self.signature(partial(partial(test, 1))),
2786 ((('b', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002787 ('c', ..., int, "positional_or_keyword")),
2788 42))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002789
2790 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002791 ((('c', ..., int, "positional_or_keyword"),),
2792 42))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002793
2794 psig = inspect.signature(partial(partial(test, 1), 2))
2795
2796 def foo(a):
2797 return a
2798 _foo = partial(partial(foo, a=10), a=20)
2799 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002800 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002801 ...))
2802 # check that we don't have any side-effects in signature(),
2803 # and the partial object is still functioning
2804 self.assertEqual(_foo(), 20)
2805
2806 def foo(a, b, c):
2807 return a, b, c
2808 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002809
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002810 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002811 ((('b', 30, ..., "keyword_only"),
2812 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002813 ...))
2814 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002815
2816 def foo(a, b, c, *, d):
2817 return a, b, c, d
2818 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2819 self.assertEqual(self.signature(_foo),
2820 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002821 ('b', 10, ..., "keyword_only"),
2822 ('c', 20, ..., "keyword_only"),
2823 ('d', 30, ..., "keyword_only"),
2824 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002825 ...))
2826 ba = inspect.signature(_foo).bind(a=200, b=11)
2827 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2828
2829 def foo(a=1, b=2, c=3):
2830 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002831 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2832
2833 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002834 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002835
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002836 ba = inspect.signature(_foo).bind(11, 12)
2837 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002838
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002839 ba = inspect.signature(_foo).bind(11, b=12)
2840 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002841
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002842 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002843 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2844
2845 _foo = partial(_foo, b=10, c=20)
2846 ba = inspect.signature(_foo).bind(12)
2847 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2848
2849
2850 def foo(a, b, c, d, **kwargs):
2851 pass
2852 sig = inspect.signature(foo)
2853 params = sig.parameters.copy()
2854 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2855 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2856 foo.__signature__ = inspect.Signature(params.values())
2857 sig = inspect.signature(foo)
2858 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2859
2860 self.assertEqual(self.signature(partial(foo, 1)),
2861 ((('b', ..., ..., 'positional_only'),
2862 ('c', ..., ..., 'positional_or_keyword'),
2863 ('d', ..., ..., 'positional_or_keyword'),
2864 ('kwargs', ..., ..., 'var_keyword')),
2865 ...))
2866
2867 self.assertEqual(self.signature(partial(foo, 1, 2)),
2868 ((('c', ..., ..., 'positional_or_keyword'),
2869 ('d', ..., ..., 'positional_or_keyword'),
2870 ('kwargs', ..., ..., 'var_keyword')),
2871 ...))
2872
2873 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2874 ((('d', ..., ..., 'positional_or_keyword'),
2875 ('kwargs', ..., ..., 'var_keyword')),
2876 ...))
2877
2878 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2879 ((('c', 3, ..., 'keyword_only'),
2880 ('d', ..., ..., 'keyword_only'),
2881 ('kwargs', ..., ..., 'var_keyword')),
2882 ...))
2883
2884 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2885 ((('b', ..., ..., 'positional_only'),
2886 ('c', 3, ..., 'keyword_only'),
2887 ('d', ..., ..., 'keyword_only'),
2888 ('kwargs', ..., ..., 'var_keyword')),
2889 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002890
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002891 def test_signature_on_partialmethod(self):
2892 from functools import partialmethod
2893
2894 class Spam:
2895 def test():
2896 pass
2897 ham = partialmethod(test)
2898
2899 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2900 inspect.signature(Spam.ham)
2901
2902 class Spam:
2903 def test(it, a, *, c) -> 'spam':
2904 pass
2905 ham = partialmethod(test, c=1)
2906
larryhastings74613a42021-04-29 21:16:28 -07002907 self.assertEqual(self.signature(Spam.ham, eval_str=False),
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002908 ((('it', ..., ..., 'positional_or_keyword'),
2909 ('a', ..., ..., 'positional_or_keyword'),
2910 ('c', 1, ..., 'keyword_only')),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002911 'spam'))
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002912
larryhastings74613a42021-04-29 21:16:28 -07002913 self.assertEqual(self.signature(Spam().ham, eval_str=False),
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002914 ((('a', ..., ..., 'positional_or_keyword'),
2915 ('c', 1, ..., 'keyword_only')),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002916 'spam'))
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002917
Yury Selivanov8a387212018-03-06 12:59:45 -05002918 class Spam:
2919 def test(self: 'anno', x):
2920 pass
2921
2922 g = partialmethod(test, 1)
2923
larryhastings74613a42021-04-29 21:16:28 -07002924 self.assertEqual(self.signature(Spam.g, eval_str=False),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002925 ((('self', ..., 'anno', 'positional_or_keyword'),),
Yury Selivanov8a387212018-03-06 12:59:45 -05002926 ...))
2927
Yury Selivanov0486f812014-01-29 12:18:59 -05002928 def test_signature_on_fake_partialmethod(self):
2929 def foo(a): pass
2930 foo._partialmethod = 'spam'
2931 self.assertEqual(str(inspect.signature(foo)), '(a)')
2932
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002933 def test_signature_on_decorated(self):
2934 import functools
2935
2936 def decorator(func):
2937 @functools.wraps(func)
2938 def wrapper(*args, **kwargs) -> int:
2939 return func(*args, **kwargs)
2940 return wrapper
2941
2942 class Foo:
2943 @decorator
2944 def bar(self, a, b):
2945 pass
2946
2947 self.assertEqual(self.signature(Foo.bar),
2948 ((('self', ..., ..., "positional_or_keyword"),
2949 ('a', ..., ..., "positional_or_keyword"),
2950 ('b', ..., ..., "positional_or_keyword")),
2951 ...))
2952
2953 self.assertEqual(self.signature(Foo().bar),
2954 ((('a', ..., ..., "positional_or_keyword"),
2955 ('b', ..., ..., "positional_or_keyword")),
2956 ...))
2957
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002958 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2959 ((('args', ..., ..., "var_positional"),
2960 ('kwargs', ..., ..., "var_keyword")),
2961 ...)) # functools.wraps will copy __annotations__
2962 # from "func" to "wrapper", hence no
2963 # return_annotation
2964
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002965 # Test that we handle method wrappers correctly
2966 def decorator(func):
2967 @functools.wraps(func)
2968 def wrapper(*args, **kwargs) -> int:
2969 return func(42, *args, **kwargs)
2970 sig = inspect.signature(func)
2971 new_params = tuple(sig.parameters.values())[1:]
2972 wrapper.__signature__ = sig.replace(parameters=new_params)
2973 return wrapper
2974
2975 class Foo:
2976 @decorator
2977 def __call__(self, a, b):
2978 pass
2979
2980 self.assertEqual(self.signature(Foo.__call__),
2981 ((('a', ..., ..., "positional_or_keyword"),
2982 ('b', ..., ..., "positional_or_keyword")),
2983 ...))
2984
2985 self.assertEqual(self.signature(Foo().__call__),
2986 ((('b', ..., ..., "positional_or_keyword"),),
2987 ...))
2988
Nick Coghlane8c45d62013-07-28 20:00:01 +10002989 # Test we handle __signature__ partway down the wrapper stack
2990 def wrapped_foo_call():
2991 pass
2992 wrapped_foo_call.__wrapped__ = Foo.__call__
2993
2994 self.assertEqual(self.signature(wrapped_foo_call),
2995 ((('a', ..., ..., "positional_or_keyword"),
2996 ('b', ..., ..., "positional_or_keyword")),
2997 ...))
2998
2999
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003000 def test_signature_on_class(self):
3001 class C:
3002 def __init__(self, a):
3003 pass
3004
3005 self.assertEqual(self.signature(C),
3006 ((('a', ..., ..., "positional_or_keyword"),),
3007 ...))
3008
3009 class CM(type):
3010 def __call__(cls, a):
3011 pass
3012 class C(metaclass=CM):
3013 def __init__(self, b):
3014 pass
3015
3016 self.assertEqual(self.signature(C),
3017 ((('a', ..., ..., "positional_or_keyword"),),
3018 ...))
3019
3020 class CM(type):
3021 def __new__(mcls, name, bases, dct, *, foo=1):
3022 return super().__new__(mcls, name, bases, dct)
3023 class C(metaclass=CM):
3024 def __init__(self, b):
3025 pass
3026
3027 self.assertEqual(self.signature(C),
3028 ((('b', ..., ..., "positional_or_keyword"),),
3029 ...))
3030
3031 self.assertEqual(self.signature(CM),
3032 ((('name', ..., ..., "positional_or_keyword"),
3033 ('bases', ..., ..., "positional_or_keyword"),
3034 ('dct', ..., ..., "positional_or_keyword"),
3035 ('foo', 1, ..., "keyword_only")),
3036 ...))
3037
3038 class CMM(type):
3039 def __new__(mcls, name, bases, dct, *, foo=1):
3040 return super().__new__(mcls, name, bases, dct)
3041 def __call__(cls, nm, bs, dt):
3042 return type(nm, bs, dt)
3043 class CM(type, metaclass=CMM):
3044 def __new__(mcls, name, bases, dct, *, bar=2):
3045 return super().__new__(mcls, name, bases, dct)
3046 class C(metaclass=CM):
3047 def __init__(self, b):
3048 pass
3049
3050 self.assertEqual(self.signature(CMM),
3051 ((('name', ..., ..., "positional_or_keyword"),
3052 ('bases', ..., ..., "positional_or_keyword"),
3053 ('dct', ..., ..., "positional_or_keyword"),
3054 ('foo', 1, ..., "keyword_only")),
3055 ...))
3056
3057 self.assertEqual(self.signature(CM),
3058 ((('nm', ..., ..., "positional_or_keyword"),
3059 ('bs', ..., ..., "positional_or_keyword"),
3060 ('dt', ..., ..., "positional_or_keyword")),
3061 ...))
3062
3063 self.assertEqual(self.signature(C),
3064 ((('b', ..., ..., "positional_or_keyword"),),
3065 ...))
3066
3067 class CM(type):
3068 def __init__(cls, name, bases, dct, *, bar=2):
3069 return super().__init__(name, bases, dct)
3070 class C(metaclass=CM):
3071 def __init__(self, b):
3072 pass
3073
3074 self.assertEqual(self.signature(CM),
3075 ((('name', ..., ..., "positional_or_keyword"),
3076 ('bases', ..., ..., "positional_or_keyword"),
3077 ('dct', ..., ..., "positional_or_keyword"),
3078 ('bar', 2, ..., "keyword_only")),
3079 ...))
3080
Miss Islington (bot)948e39a2021-07-16 06:25:57 -07003081 def test_signature_on_subclass(self):
3082 class A:
3083 def __new__(cls, a=1, *args, **kwargs):
3084 return object.__new__(cls)
3085 class B(A):
3086 def __init__(self, b):
3087 pass
3088 class C(A):
3089 def __new__(cls, a=1, b=2, *args, **kwargs):
3090 return object.__new__(cls)
3091 class D(A):
3092 pass
3093
3094 self.assertEqual(self.signature(B),
3095 ((('b', ..., ..., "positional_or_keyword"),),
3096 ...))
3097 self.assertEqual(self.signature(C),
3098 ((('a', 1, ..., 'positional_or_keyword'),
3099 ('b', 2, ..., 'positional_or_keyword'),
3100 ('args', ..., ..., 'var_positional'),
3101 ('kwargs', ..., ..., 'var_keyword')),
3102 ...))
3103 self.assertEqual(self.signature(D),
3104 ((('a', 1, ..., 'positional_or_keyword'),
3105 ('args', ..., ..., 'var_positional'),
3106 ('kwargs', ..., ..., 'var_keyword')),
3107 ...))
3108
3109 def test_signature_on_generic_subclass(self):
3110 from typing import Generic, TypeVar
3111
3112 T = TypeVar('T')
3113
3114 class A(Generic[T]):
3115 def __init__(self, *, a: int) -> None:
3116 pass
3117
3118 self.assertEqual(self.signature(A),
3119 ((('a', ..., int, 'keyword_only'),),
3120 None))
3121
Yury Selivanov145dff82014-02-01 13:49:29 -05003122 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3123 "Signature information for builtins requires docstrings")
3124 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003125 # Test classes without user-defined __init__ or __new__
3126 class C: pass
3127 self.assertEqual(str(inspect.signature(C)), '()')
3128 class D(C): pass
3129 self.assertEqual(str(inspect.signature(D)), '()')
3130
3131 # Test meta-classes without user-defined __init__ or __new__
3132 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003133 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08003134 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
3135 self.assertEqual(inspect.signature(C), None)
3136 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
3137 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003138
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003139 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3140 "Signature information for builtins requires docstrings")
3141 def test_signature_on_builtin_class(self):
Antoine Pitrou91f43802019-05-26 17:10:09 +02003142 expected = ('(file, protocol=None, fix_imports=True, '
3143 'buffer_callback=None)')
3144 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003145
3146 class P(_pickle.Pickler): pass
3147 class EmptyTrait: pass
3148 class P2(EmptyTrait, P): pass
Antoine Pitrou91f43802019-05-26 17:10:09 +02003149 self.assertEqual(str(inspect.signature(P)), expected)
3150 self.assertEqual(str(inspect.signature(P2)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003151
3152 class P3(P2):
3153 def __init__(self, spam):
3154 pass
3155 self.assertEqual(str(inspect.signature(P3)), '(spam)')
3156
3157 class MetaP(type):
3158 def __call__(cls, foo, bar):
3159 pass
3160 class P4(P2, metaclass=MetaP):
3161 pass
3162 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
3163
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003164 def test_signature_on_callable_objects(self):
3165 class Foo:
3166 def __call__(self, a):
3167 pass
3168
3169 self.assertEqual(self.signature(Foo()),
3170 ((('a', ..., ..., "positional_or_keyword"),),
3171 ...))
3172
3173 class Spam:
3174 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003175 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003176 inspect.signature(Spam())
3177
3178 class Bar(Spam, Foo):
3179 pass
3180
3181 self.assertEqual(self.signature(Bar()),
3182 ((('a', ..., ..., "positional_or_keyword"),),
3183 ...))
3184
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003185 class Wrapped:
3186 pass
3187 Wrapped.__wrapped__ = lambda a: None
3188 self.assertEqual(self.signature(Wrapped),
3189 ((('a', ..., ..., "positional_or_keyword"),),
3190 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10003191 # wrapper loop:
3192 Wrapped.__wrapped__ = Wrapped
3193 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3194 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003195
3196 def test_signature_on_lambdas(self):
3197 self.assertEqual(self.signature((lambda a=10: a)),
3198 ((('a', 10, ..., "positional_or_keyword"),),
3199 ...))
3200
3201 def test_signature_equality(self):
3202 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003203 self.assertFalse(inspect.signature(foo) == 42)
3204 self.assertTrue(inspect.signature(foo) != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003205 self.assertTrue(inspect.signature(foo) == ALWAYS_EQ)
3206 self.assertFalse(inspect.signature(foo) != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003207
3208 def bar(a, *, b:int) -> float: 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 bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003215 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3216 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003217 self.assertNotEqual(
3218 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003219
3220 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003221 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3222 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003223 self.assertNotEqual(
3224 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003225
3226 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003227 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3228 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003229 self.assertNotEqual(
3230 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003231
3232 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003233 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3234 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003235 self.assertNotEqual(
3236 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003237
3238 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003239 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3240 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003241 self.assertNotEqual(
3242 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003243 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003244 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3245 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003246 self.assertNotEqual(
3247 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003248
3249 def foo(*, a, b, c): pass
3250 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003251 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3252 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003253 self.assertEqual(
3254 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003255
3256 def foo(*, a=1, b, c): pass
3257 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003258 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3259 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003260 self.assertEqual(
3261 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003262
3263 def foo(pos, *, a=1, b, c): pass
3264 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003265 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3266 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003267 self.assertEqual(
3268 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003269
3270 def foo(pos, *, a, b, c): pass
3271 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003272 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3273 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003274 self.assertNotEqual(
3275 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003276
3277 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3278 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003279 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3280 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003281 self.assertEqual(
3282 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003283
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003284 def test_signature_hashable(self):
3285 S = inspect.Signature
3286 P = inspect.Parameter
3287
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003288 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003289 foo_sig = inspect.signature(foo)
3290
3291 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3292
3293 self.assertEqual(hash(foo_sig), hash(manual_sig))
3294 self.assertNotEqual(hash(foo_sig),
3295 hash(manual_sig.replace(return_annotation='spam')))
3296
3297 def bar(a) -> 1: pass
3298 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3299
3300 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003301 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003302 hash(inspect.signature(foo))
3303
Pablo Galindob0544ba2021-04-21 12:41:19 +01003304 def foo(a) -> {}: pass
3305 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3306 hash(inspect.signature(foo))
3307
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003308 def test_signature_str(self):
3309 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3310 pass
3311 self.assertEqual(str(inspect.signature(foo)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003312 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003313
3314 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3315 pass
3316 self.assertEqual(str(inspect.signature(foo)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003317 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003318
3319 def foo():
3320 pass
3321 self.assertEqual(str(inspect.signature(foo)), '()')
3322
3323 def test_signature_str_positional_only(self):
3324 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003325 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003326
3327 def test(a_po, *, b, **kwargs):
3328 return a_po, kwargs
3329
3330 sig = inspect.signature(test)
3331 new_params = list(sig.parameters.values())
3332 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3333 test.__signature__ = sig.replace(parameters=new_params)
3334
3335 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003336 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003337
Yury Selivanov2393dca2014-01-27 15:07:58 -05003338 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3339 '(foo, /)')
3340
3341 self.assertEqual(str(S(parameters=[
3342 P('foo', P.POSITIONAL_ONLY),
3343 P('bar', P.VAR_KEYWORD)])),
3344 '(foo, /, **bar)')
3345
3346 self.assertEqual(str(S(parameters=[
3347 P('foo', P.POSITIONAL_ONLY),
3348 P('bar', P.VAR_POSITIONAL)])),
3349 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003350
3351 def test_signature_replace_anno(self):
3352 def test() -> 42:
3353 pass
3354
3355 sig = inspect.signature(test)
3356 sig = sig.replace(return_annotation=None)
3357 self.assertIs(sig.return_annotation, None)
3358 sig = sig.replace(return_annotation=sig.empty)
3359 self.assertIs(sig.return_annotation, sig.empty)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003360 sig = sig.replace(return_annotation=42)
3361 self.assertEqual(sig.return_annotation, 42)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003362 self.assertEqual(sig, inspect.signature(test))
3363
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003364 def test_signature_on_mangled_parameters(self):
3365 class Spam:
3366 def foo(self, __p1:1=2, *, __p2:2=3):
3367 pass
3368 class Ham(Spam):
3369 pass
3370
3371 self.assertEqual(self.signature(Spam.foo),
3372 ((('self', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003373 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3374 ('_Spam__p2', 3, 2, "keyword_only")),
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003375 ...))
3376
3377 self.assertEqual(self.signature(Spam.foo),
3378 self.signature(Ham.foo))
3379
Yury Selivanovda396452014-03-27 12:09:24 -04003380 def test_signature_from_callable_python_obj(self):
3381 class MySignature(inspect.Signature): pass
3382 def foo(a, *, b:1): pass
3383 foo_sig = MySignature.from_callable(foo)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003384 self.assertIsInstance(foo_sig, MySignature)
3385
3386 def test_signature_from_callable_class(self):
3387 # A regression test for a class inheriting its signature from `object`.
3388 class MySignature(inspect.Signature): pass
3389 class foo: pass
3390 foo_sig = MySignature.from_callable(foo)
3391 self.assertIsInstance(foo_sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003392
3393 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3394 "Signature information for builtins requires docstrings")
3395 def test_signature_from_callable_builtin_obj(self):
3396 class MySignature(inspect.Signature): pass
3397 sig = MySignature.from_callable(_pickle.Pickler)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003398 self.assertIsInstance(sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003399
larryhastingsf36ba122018-01-28 11:13:09 -08003400 def test_signature_definition_order_preserved_on_kwonly(self):
3401 for fn in signatures_with_lexicographic_keyword_only_parameters():
3402 signature = inspect.signature(fn)
3403 l = list(signature.parameters)
3404 sorted_l = sorted(l)
3405 self.assertTrue(l)
3406 self.assertEqual(l, sorted_l)
3407 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3408 l = list(signature.parameters)
3409 self.assertEqual(l, unsorted_keyword_only_parameters)
3410
Jens Reidel611836a2020-03-18 03:22:46 +01003411 def test_signater_parameters_is_ordered(self):
3412 p1 = inspect.signature(lambda x, y: None).parameters
3413 p2 = inspect.signature(lambda y, x: None).parameters
3414 self.assertNotEqual(p1, p2)
3415
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003416 def test_signature_annotations_with_local_namespaces(self):
3417 class Foo: ...
3418 def func(foo: Foo) -> int: pass
Pablo Galindob0544ba2021-04-21 12:41:19 +01003419 def func2(foo: Foo, bar: 'Bar') -> int: pass
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003420
3421 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3422 with self.subTest(signature_func = signature_func):
3423 sig1 = signature_func(func)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003424 self.assertEqual(sig1.return_annotation, int)
3425 self.assertEqual(sig1.parameters['foo'].annotation, Foo)
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003426
larryhastings74613a42021-04-29 21:16:28 -07003427 sig2 = signature_func(func, locals=locals())
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003428 self.assertEqual(sig2.return_annotation, int)
3429 self.assertEqual(sig2.parameters['foo'].annotation, Foo)
3430
larryhastings74613a42021-04-29 21:16:28 -07003431 sig3 = signature_func(func2, globals={'Bar': int}, locals=locals())
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003432 self.assertEqual(sig3.return_annotation, int)
3433 self.assertEqual(sig3.parameters['foo'].annotation, Foo)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003434 self.assertEqual(sig3.parameters['bar'].annotation, 'Bar')
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003435
larryhastings74613a42021-04-29 21:16:28 -07003436 def test_signature_eval_str(self):
3437 isa = inspect_stringized_annotations
3438 sig = inspect.Signature
3439 par = inspect.Parameter
3440 PORK = inspect.Parameter.POSITIONAL_OR_KEYWORD
3441 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3442 with self.subTest(signature_func = signature_func):
3443 self.assertEqual(
3444 signature_func(isa.MyClass),
3445 sig(
3446 parameters=(
3447 par('a', PORK),
3448 par('b', PORK),
3449 )))
3450 self.assertEqual(
3451 signature_func(isa.function),
3452 sig(
3453 return_annotation='MyClass',
3454 parameters=(
3455 par('a', PORK, annotation='int'),
3456 par('b', PORK, annotation='str'),
3457 )))
3458 self.assertEqual(
3459 signature_func(isa.function2),
3460 sig(
3461 return_annotation='MyClass',
3462 parameters=(
3463 par('a', PORK, annotation='int'),
3464 par('b', PORK, annotation="'str'"),
3465 par('c', PORK, annotation="MyClass"),
3466 )))
3467 self.assertEqual(
3468 signature_func(isa.function3),
3469 sig(
3470 parameters=(
3471 par('a', PORK, annotation="'int'"),
3472 par('b', PORK, annotation="'str'"),
3473 par('c', PORK, annotation="'MyClass'"),
3474 )))
3475
3476 self.assertEqual(signature_func(isa.UnannotatedClass), sig())
3477 self.assertEqual(signature_func(isa.unannotated_function),
3478 sig(
3479 parameters=(
3480 par('a', PORK),
3481 par('b', PORK),
3482 par('c', PORK),
3483 )))
3484
3485 self.assertEqual(
3486 signature_func(isa.MyClass, eval_str=True),
3487 sig(
3488 parameters=(
3489 par('a', PORK),
3490 par('b', PORK),
3491 )))
3492 self.assertEqual(
3493 signature_func(isa.function, eval_str=True),
3494 sig(
3495 return_annotation=isa.MyClass,
3496 parameters=(
3497 par('a', PORK, annotation=int),
3498 par('b', PORK, annotation=str),
3499 )))
3500 self.assertEqual(
3501 signature_func(isa.function2, eval_str=True),
3502 sig(
3503 return_annotation=isa.MyClass,
3504 parameters=(
3505 par('a', PORK, annotation=int),
3506 par('b', PORK, annotation='str'),
3507 par('c', PORK, annotation=isa.MyClass),
3508 )))
3509 self.assertEqual(
3510 signature_func(isa.function3, eval_str=True),
3511 sig(
3512 parameters=(
3513 par('a', PORK, annotation='int'),
3514 par('b', PORK, annotation='str'),
3515 par('c', PORK, annotation='MyClass'),
3516 )))
3517
3518 globalns = {'int': float, 'str': complex}
3519 localns = {'str': tuple, 'MyClass': dict}
3520 with self.assertRaises(NameError):
3521 signature_func(isa.function, eval_str=True, globals=globalns)
3522
3523 self.assertEqual(
3524 signature_func(isa.function, eval_str=True, locals=localns),
3525 sig(
3526 return_annotation=dict,
3527 parameters=(
3528 par('a', PORK, annotation=int),
3529 par('b', PORK, annotation=tuple),
3530 )))
3531
3532 self.assertEqual(
3533 signature_func(isa.function, eval_str=True, globals=globalns, locals=localns),
3534 sig(
3535 return_annotation=dict,
3536 parameters=(
3537 par('a', PORK, annotation=float),
3538 par('b', PORK, annotation=tuple),
3539 )))
3540
3541 def test_signature_none_annotation(self):
3542 class funclike:
3543 # Has to be callable, and have correct
3544 # __code__, __annotations__, __defaults__, __name__,
3545 # and __kwdefaults__ attributes
3546
3547 def __init__(self, func):
3548 self.__name__ = func.__name__
3549 self.__code__ = func.__code__
3550 self.__annotations__ = func.__annotations__
3551 self.__defaults__ = func.__defaults__
3552 self.__kwdefaults__ = func.__kwdefaults__
3553 self.func = func
3554
3555 def __call__(self, *args, **kwargs):
3556 return self.func(*args, **kwargs)
3557
3558 def foo(): pass
3559 foo = funclike(foo)
3560 foo.__annotations__ = None
3561 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3562 with self.subTest(signature_func = signature_func):
3563 self.assertEqual(signature_func(foo), inspect.Signature())
3564 self.assertEqual(inspect.get_annotations(foo), {})
3565
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003566
3567class TestParameterObject(unittest.TestCase):
3568 def test_signature_parameter_kinds(self):
3569 P = inspect.Parameter
3570 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3571 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3572
3573 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3574 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3575
3576 def test_signature_parameter_object(self):
3577 p = inspect.Parameter('foo', default=10,
3578 kind=inspect.Parameter.POSITIONAL_ONLY)
3579 self.assertEqual(p.name, 'foo')
3580 self.assertEqual(p.default, 10)
3581 self.assertIs(p.annotation, p.empty)
3582 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3583
Dong-hee Naa9cab432018-05-30 00:04:08 +09003584 with self.assertRaisesRegex(ValueError, "value '123' is "
3585 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003586 inspect.Parameter('foo', default=10, kind='123')
3587
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003588 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003589 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3590
Yury Selivanov2393dca2014-01-27 15:07:58 -05003591 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003592 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3593
Yury Selivanov2393dca2014-01-27 15:07:58 -05003594 with self.assertRaisesRegex(ValueError,
3595 'is not a valid parameter name'):
3596 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3597
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003598 with self.assertRaisesRegex(ValueError,
3599 'is not a valid parameter name'):
3600 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3601
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003602 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003603 inspect.Parameter('a', default=42,
3604 kind=inspect.Parameter.VAR_KEYWORD)
3605
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003606 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003607 inspect.Parameter('a', default=42,
3608 kind=inspect.Parameter.VAR_POSITIONAL)
3609
3610 p = inspect.Parameter('a', default=42,
3611 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003612 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003613 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3614
3615 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003616 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003617
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003618 def test_signature_parameter_hashable(self):
3619 P = inspect.Parameter
3620 foo = P('foo', kind=P.POSITIONAL_ONLY)
3621 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3622 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3623 default=42)))
3624 self.assertNotEqual(hash(foo),
3625 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3626
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003627 def test_signature_parameter_equality(self):
3628 P = inspect.Parameter
3629 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3630
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003631 self.assertTrue(p == p)
3632 self.assertFalse(p != p)
3633 self.assertFalse(p == 42)
3634 self.assertTrue(p != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003635 self.assertTrue(p == ALWAYS_EQ)
3636 self.assertFalse(p != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003637
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003638 self.assertTrue(p == P('foo', default=42,
3639 kind=inspect.Parameter.KEYWORD_ONLY))
3640 self.assertFalse(p != P('foo', default=42,
3641 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003642
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003643 def test_signature_parameter_replace(self):
3644 p = inspect.Parameter('foo', default=42,
3645 kind=inspect.Parameter.KEYWORD_ONLY)
3646
3647 self.assertIsNot(p, p.replace())
3648 self.assertEqual(p, p.replace())
3649
3650 p2 = p.replace(annotation=1)
3651 self.assertEqual(p2.annotation, 1)
3652 p2 = p2.replace(annotation=p2.empty)
3653 self.assertEqual(p, p2)
3654
3655 p2 = p2.replace(name='bar')
3656 self.assertEqual(p2.name, 'bar')
3657 self.assertNotEqual(p2, p)
3658
Yury Selivanov2393dca2014-01-27 15:07:58 -05003659 with self.assertRaisesRegex(ValueError,
3660 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003661 p2 = p2.replace(name=p2.empty)
3662
3663 p2 = p2.replace(name='foo', default=None)
3664 self.assertIs(p2.default, None)
3665 self.assertNotEqual(p2, p)
3666
3667 p2 = p2.replace(name='foo', default=p2.empty)
3668 self.assertIs(p2.default, p2.empty)
3669
3670
3671 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3672 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3673 self.assertNotEqual(p2, p)
3674
Dong-hee Naa9cab432018-05-30 00:04:08 +09003675 with self.assertRaisesRegex(ValueError,
3676 "value <class 'inspect._empty'> "
3677 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003678 p2 = p2.replace(kind=p2.empty)
3679
3680 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3681 self.assertEqual(p2, p)
3682
3683 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003684 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3685 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003686
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003687 @cpython_only
3688 def test_signature_parameter_implicit(self):
3689 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003690 'implicit arguments must be passed as '
3691 'positional or keyword arguments, '
3692 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003693 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3694
3695 param = inspect.Parameter(
3696 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3697 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3698 self.assertEqual(param.name, 'implicit0')
3699
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003700 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003701 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003702
3703 with self.assertRaises(AttributeError):
3704 p.foo = 'bar'
3705
3706 with self.assertRaises(AttributeError):
3707 p.kind = 123
3708
3709
3710class TestSignatureBind(unittest.TestCase):
3711 @staticmethod
3712 def call(func, *args, **kwargs):
3713 sig = inspect.signature(func)
3714 ba = sig.bind(*args, **kwargs)
3715 return func(*ba.args, **ba.kwargs)
3716
3717 def test_signature_bind_empty(self):
3718 def test():
3719 return 42
3720
3721 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003722 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003723 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003724 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003725 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003726 with self.assertRaisesRegex(
3727 TypeError, "got an unexpected keyword argument 'spam'"):
3728
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003729 self.call(test, spam=1)
3730
3731 def test_signature_bind_var(self):
3732 def test(*args, **kwargs):
3733 return args, kwargs
3734
3735 self.assertEqual(self.call(test), ((), {}))
3736 self.assertEqual(self.call(test, 1), ((1,), {}))
3737 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3738 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3739 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3740 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3741 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3742 ((1, 2), {'foo': 'bar'}))
3743
3744 def test_signature_bind_just_args(self):
3745 def test(a, b, c):
3746 return a, b, c
3747
3748 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3749
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003750 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003751 self.call(test, 1, 2, 3, 4)
3752
Yury Selivanov86872752015-05-19 00:27:49 -04003753 with self.assertRaisesRegex(TypeError,
3754 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003755 self.call(test, 1)
3756
Yury Selivanov86872752015-05-19 00:27:49 -04003757 with self.assertRaisesRegex(TypeError,
3758 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003759 self.call(test)
3760
3761 def test(a, b, c=10):
3762 return a, b, c
3763 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3764 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3765
3766 def test(a=1, b=2, c=3):
3767 return a, b, c
3768 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3769 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3770 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3771
3772 def test_signature_bind_varargs_order(self):
3773 def test(*args):
3774 return args
3775
3776 self.assertEqual(self.call(test), ())
3777 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3778
3779 def test_signature_bind_args_and_varargs(self):
3780 def test(a, b, c=3, *args):
3781 return a, b, c, args
3782
3783 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3784 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3785 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3786 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3787
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003788 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003789 "multiple values for argument 'c'"):
3790 self.call(test, 1, 2, 3, c=4)
3791
3792 def test_signature_bind_just_kwargs(self):
3793 def test(**kwargs):
3794 return kwargs
3795
3796 self.assertEqual(self.call(test), {})
3797 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3798 {'foo': 'bar', 'spam': 'ham'})
3799
3800 def test_signature_bind_args_and_kwargs(self):
3801 def test(a, b, c=3, **kwargs):
3802 return a, b, c, kwargs
3803
3804 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3805 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3806 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3807 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3808 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3809 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3810 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3811 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3812 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3813 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3814 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3815 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3816 (1, 2, 4, {'foo': 'bar'}))
3817 self.assertEqual(self.call(test, c=5, a=4, b=3),
3818 (4, 3, 5, {}))
3819
3820 def test_signature_bind_kwonly(self):
3821 def test(*, foo):
3822 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003823 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003824 'too many positional arguments'):
3825 self.call(test, 1)
3826 self.assertEqual(self.call(test, foo=1), 1)
3827
3828 def test(a, *, foo=1, bar):
3829 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003830 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003831 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003832 self.call(test, 1)
3833
3834 def test(foo, *, bar):
3835 return foo, bar
3836 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3837 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3838
Yury Selivanov86872752015-05-19 00:27:49 -04003839 with self.assertRaisesRegex(
3840 TypeError, "got an unexpected keyword argument 'spam'"):
3841
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003842 self.call(test, bar=2, foo=1, spam=10)
3843
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003844 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003845 'too many positional arguments'):
3846 self.call(test, 1, 2)
3847
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003848 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003849 'too many positional arguments'):
3850 self.call(test, 1, 2, bar=2)
3851
Yury Selivanov86872752015-05-19 00:27:49 -04003852 with self.assertRaisesRegex(
3853 TypeError, "got an unexpected keyword argument 'spam'"):
3854
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003855 self.call(test, 1, bar=2, spam='ham')
3856
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003857 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003858 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003859 self.call(test, 1)
3860
3861 def test(foo, *, bar, **bin):
3862 return foo, bar, bin
3863 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3864 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3865 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3866 (1, 2, {'spam': 'ham'}))
3867 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3868 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003869 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003870 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003871 self.call(test, spam='ham', bar=2)
3872 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3873 (1, 2, {'bin': 1, 'spam': 10}))
3874
3875 def test_signature_bind_arguments(self):
3876 def test(a, *args, b, z=100, **kwargs):
3877 pass
3878 sig = inspect.signature(test)
3879 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3880 # we won't have 'z' argument in the bound arguments object, as we didn't
3881 # pass it to the 'bind'
3882 self.assertEqual(tuple(ba.arguments.items()),
3883 (('a', 10), ('args', (20,)), ('b', 30),
3884 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3885 self.assertEqual(ba.kwargs,
3886 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3887 self.assertEqual(ba.args, (10, 20))
3888
3889 def test_signature_bind_positional_only(self):
3890 P = inspect.Parameter
3891
3892 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3893 return a_po, b_po, c_po, foo, bar, kwargs
3894
3895 sig = inspect.signature(test)
3896 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3897 for name in ('a_po', 'b_po', 'c_po'):
3898 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3899 new_sig = sig.replace(parameters=new_params.values())
3900 test.__signature__ = new_sig
3901
3902 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3903 (1, 2, 4, 5, 6, {}))
3904
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003905 self.assertEqual(self.call(test, 1, 2),
3906 (1, 2, 3, 42, 50, {}))
3907
3908 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3909 (1, 2, 3, 4, 5, {}))
3910
3911 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3912 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3913
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003914 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003915 self.call(test, 1, 2, c_po=4)
3916
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003917 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003918 self.call(test, a_po=1, b_po=2)
3919
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003920 def test_signature_bind_with_self_arg(self):
3921 # Issue #17071: one of the parameters is named "self
3922 def test(a, self, b):
3923 pass
3924 sig = inspect.signature(test)
3925 ba = sig.bind(1, 2, 3)
3926 self.assertEqual(ba.args, (1, 2, 3))
3927 ba = sig.bind(1, self=2, b=3)
3928 self.assertEqual(ba.args, (1, 2, 3))
3929
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003930 def test_signature_bind_vararg_name(self):
3931 def test(a, *args):
3932 return a, args
3933 sig = inspect.signature(test)
3934
Yury Selivanov86872752015-05-19 00:27:49 -04003935 with self.assertRaisesRegex(
3936 TypeError, "got an unexpected keyword argument 'args'"):
3937
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003938 sig.bind(a=0, args=1)
3939
3940 def test(*args, **kwargs):
3941 return args, kwargs
3942 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3943
3944 sig = inspect.signature(test)
3945 ba = sig.bind(args=1)
3946 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3947
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003948 @cpython_only
3949 def test_signature_bind_implicit_arg(self):
3950 # Issue #19611: getcallargs should work with set comprehensions
3951 def make_set():
3952 return {z * z for z in range(5)}
3953 setcomp_code = make_set.__code__.co_consts[1]
3954 setcomp_func = types.FunctionType(setcomp_code, {})
3955
3956 iterator = iter(range(5))
3957 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3958
Pablo Galindof3ef06a2019-10-15 12:40:02 +01003959 def test_signature_bind_posonly_kwargs(self):
3960 def foo(bar, /, **kwargs):
3961 return bar, kwargs.get(bar)
3962
3963 sig = inspect.signature(foo)
3964 result = sig.bind("pos-only", bar="keyword")
3965
3966 self.assertEqual(result.kwargs, {"bar": "keyword"})
3967 self.assertIn(("bar", "pos-only"), result.arguments.items())
3968
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003969
3970class TestBoundArguments(unittest.TestCase):
3971 def test_signature_bound_arguments_unhashable(self):
3972 def foo(a): pass
3973 ba = inspect.signature(foo).bind(1)
3974
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003975 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003976 hash(ba)
3977
3978 def test_signature_bound_arguments_equality(self):
3979 def foo(a): pass
3980 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003981 self.assertTrue(ba == ba)
3982 self.assertFalse(ba != ba)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003983 self.assertTrue(ba == ALWAYS_EQ)
3984 self.assertFalse(ba != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003985
3986 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003987 self.assertTrue(ba == ba2)
3988 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003989
3990 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003991 self.assertFalse(ba == ba3)
3992 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003993 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003994 self.assertTrue(ba == ba3)
3995 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003996
3997 def bar(b): pass
3998 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003999 self.assertFalse(ba == ba4)
4000 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004001
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04004002 def foo(*, a, b): pass
4003 sig = inspect.signature(foo)
4004 ba1 = sig.bind(a=1, b=2)
4005 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03004006 self.assertTrue(ba1 == ba2)
4007 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04004008
Yury Selivanova5d63dd2014-03-27 11:31:43 -04004009 def test_signature_bound_arguments_pickle(self):
4010 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
4011 sig = inspect.signature(foo)
4012 ba = sig.bind(20, 30, z={})
4013
4014 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
4015 with self.subTest(pickle_ver=ver):
4016 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
4017 self.assertEqual(ba, ba_pickled)
4018
Yury Selivanov3f6538f2015-05-14 18:47:17 -04004019 def test_signature_bound_arguments_repr(self):
4020 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
4021 sig = inspect.signature(foo)
4022 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04004023 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04004024
Yury Selivanovb907a512015-05-16 13:45:09 -04004025 def test_signature_bound_arguments_apply_defaults(self):
4026 def foo(a, b=1, *args, c:1={}, **kw): pass
4027 sig = inspect.signature(foo)
4028
4029 ba = sig.bind(20)
4030 ba.apply_defaults()
4031 self.assertEqual(
4032 list(ba.arguments.items()),
4033 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
4034
4035 # Make sure that we preserve the order:
4036 # i.e. 'c' should be *before* 'kw'.
4037 ba = sig.bind(10, 20, 30, d=1)
4038 ba.apply_defaults()
4039 self.assertEqual(
4040 list(ba.arguments.items()),
4041 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
4042
4043 # Make sure that BoundArguments produced by bind_partial()
4044 # are supported.
4045 def foo(a, b): pass
4046 sig = inspect.signature(foo)
4047 ba = sig.bind_partial(20)
4048 ba.apply_defaults()
4049 self.assertEqual(
4050 list(ba.arguments.items()),
4051 [('a', 20)])
4052
4053 # Test no args
4054 def foo(): pass
4055 sig = inspect.signature(foo)
4056 ba = sig.bind()
4057 ba.apply_defaults()
4058 self.assertEqual(list(ba.arguments.items()), [])
4059
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05004060 # Make sure a no-args binding still acquires proper defaults.
4061 def foo(a='spam'): pass
4062 sig = inspect.signature(foo)
4063 ba = sig.bind()
4064 ba.apply_defaults()
4065 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
4066
Rémi Lapeyre2cca8ef2020-01-28 13:47:03 +01004067 def test_signature_bound_arguments_arguments_type(self):
4068 def foo(a): pass
4069 ba = inspect.signature(foo).bind(1)
4070 self.assertIs(type(ba.arguments), dict)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004071
Yury Selivanovd82eddc2014-01-29 11:24:39 -05004072class TestSignaturePrivateHelpers(unittest.TestCase):
4073 def test_signature_get_bound_param(self):
4074 getter = inspect._signature_get_bound_param
4075
4076 self.assertEqual(getter('($self)'), 'self')
4077 self.assertEqual(getter('($self, obj)'), 'self')
4078 self.assertEqual(getter('($cls, /, obj)'), 'cls')
4079
Larry Hastings2623c8c2014-02-08 22:15:29 -08004080 def _strip_non_python_syntax(self, input,
4081 clean_signature, self_parameter, last_positional_only):
4082 computed_clean_signature, \
4083 computed_self_parameter, \
4084 computed_last_positional_only = \
4085 inspect._signature_strip_non_python_syntax(input)
4086 self.assertEqual(computed_clean_signature, clean_signature)
4087 self.assertEqual(computed_self_parameter, self_parameter)
4088 self.assertEqual(computed_last_positional_only, last_positional_only)
4089
4090 def test_signature_strip_non_python_syntax(self):
4091 self._strip_non_python_syntax(
4092 "($module, /, path, mode, *, dir_fd=None, " +
4093 "effective_ids=False,\n follow_symlinks=True)",
4094 "(module, path, mode, *, dir_fd=None, " +
4095 "effective_ids=False, follow_symlinks=True)",
4096 0,
4097 0)
4098
4099 self._strip_non_python_syntax(
4100 "($module, word, salt, /)",
4101 "(module, word, salt)",
4102 0,
4103 2)
4104
4105 self._strip_non_python_syntax(
4106 "(x, y=None, z=None, /)",
4107 "(x, y=None, z=None)",
4108 None,
4109 2)
4110
4111 self._strip_non_python_syntax(
4112 "(x, y=None, z=None)",
4113 "(x, y=None, z=None)",
4114 None,
4115 None)
4116
4117 self._strip_non_python_syntax(
4118 "(x,\n y=None,\n z = None )",
4119 "(x, y=None, z=None)",
4120 None,
4121 None)
4122
4123 self._strip_non_python_syntax(
4124 "",
4125 "",
4126 None,
4127 None)
4128
4129 self._strip_non_python_syntax(
4130 None,
4131 None,
4132 None,
4133 None)
4134
Nick Coghlan9c680b02015-04-13 12:54:54 -04004135class TestSignatureDefinitions(unittest.TestCase):
4136 # This test case provides a home for checking that particular APIs
4137 # have signatures available for introspection
4138
4139 @cpython_only
4140 @unittest.skipIf(MISSING_C_DOCSTRINGS,
4141 "Signature information for builtins requires docstrings")
4142 def test_builtins_have_signatures(self):
4143 # This checks all builtin callables in CPython have signatures
4144 # A few have signatures Signature can't yet handle, so we skip those
4145 # since they will have to wait until PEP 457 adds the required
4146 # introspection support to the inspect module
4147 # Some others also haven't been converted yet for various other
4148 # reasons, so we also skip those for the time being, but design
4149 # the test to fail in order to indicate when it needs to be
4150 # updated.
4151 no_signature = set()
4152 # These need PEP 457 groups
4153 needs_groups = {"range", "slice", "dir", "getattr",
4154 "next", "iter", "vars"}
4155 no_signature |= needs_groups
Joshua Bronsonf0a6fde2021-03-23 18:47:21 -04004156 # These have unrepresentable parameter default values of NULL
4157 needs_null = {"anext"}
4158 no_signature |= needs_null
Nick Coghlan9c680b02015-04-13 12:54:54 -04004159 # These need PEP 457 groups or a signature change to accept None
4160 needs_semantic_update = {"round"}
4161 no_signature |= needs_semantic_update
4162 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04004163 needs_varargs = {"breakpoint", "min", "max", "print",
4164 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04004165 no_signature |= needs_varargs
4166 # These simply weren't covered in the initial AC conversion
4167 # for builtin callables
4168 not_converted_yet = {"open", "__import__"}
4169 no_signature |= not_converted_yet
4170 # These builtin types are expected to provide introspection info
4171 types_with_signatures = set()
4172 # Check the signatures we expect to be there
4173 ns = vars(builtins)
4174 for name, obj in sorted(ns.items()):
4175 if not callable(obj):
4176 continue
4177 # The builtin types haven't been converted to AC yet
4178 if isinstance(obj, type) and (name not in types_with_signatures):
4179 # Note that this also skips all the exception types
4180 no_signature.add(name)
4181 if (name in no_signature):
4182 # Not yet converted
4183 continue
4184 with self.subTest(builtin=name):
4185 self.assertIsNotNone(inspect.signature(obj))
4186 # Check callables that haven't been converted don't claim a signature
4187 # This ensures this test will start failing as more signatures are
4188 # added, so the affected items can be moved into the scope of the
4189 # regression test above
4190 for name in no_signature:
4191 with self.subTest(builtin=name):
4192 self.assertIsNone(obj.__text_signature__)
4193
Serhiy Storchakad53cf992019-05-06 22:40:27 +03004194 def test_python_function_override_signature(self):
4195 def func(*args, **kwargs):
4196 pass
4197 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
4198 sig = inspect.signature(func)
4199 self.assertIsNotNone(sig)
4200 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
4201 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
4202 sig = inspect.signature(func)
4203 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
4204
Yury Selivanovd82eddc2014-01-29 11:24:39 -05004205
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01004206class NTimesUnwrappable:
4207 def __init__(self, n):
4208 self.n = n
4209 self._next = None
4210
4211 @property
4212 def __wrapped__(self):
4213 if self.n <= 0:
4214 raise Exception("Unwrapped too many times")
4215 if self._next is None:
4216 self._next = NTimesUnwrappable(self.n - 1)
4217 return self._next
4218
Nick Coghlane8c45d62013-07-28 20:00:01 +10004219class TestUnwrap(unittest.TestCase):
4220
4221 def test_unwrap_one(self):
4222 def func(a, b):
4223 return a + b
4224 wrapper = functools.lru_cache(maxsize=20)(func)
4225 self.assertIs(inspect.unwrap(wrapper), func)
4226
4227 def test_unwrap_several(self):
4228 def func(a, b):
4229 return a + b
4230 wrapper = func
4231 for __ in range(10):
4232 @functools.wraps(wrapper)
4233 def wrapper():
4234 pass
4235 self.assertIsNot(wrapper.__wrapped__, func)
4236 self.assertIs(inspect.unwrap(wrapper), func)
4237
4238 def test_stop(self):
4239 def func1(a, b):
4240 return a + b
4241 @functools.wraps(func1)
4242 def func2():
4243 pass
4244 @functools.wraps(func2)
4245 def wrapper():
4246 pass
4247 func2.stop_here = 1
4248 unwrapped = inspect.unwrap(wrapper,
4249 stop=(lambda f: hasattr(f, "stop_here")))
4250 self.assertIs(unwrapped, func2)
4251
4252 def test_cycle(self):
4253 def func1(): pass
4254 func1.__wrapped__ = func1
4255 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4256 inspect.unwrap(func1)
4257
4258 def func2(): pass
4259 func2.__wrapped__ = func1
4260 func1.__wrapped__ = func2
4261 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4262 inspect.unwrap(func1)
4263 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4264 inspect.unwrap(func2)
4265
4266 def test_unhashable(self):
4267 def func(): pass
4268 func.__wrapped__ = None
4269 class C:
4270 __hash__ = None
4271 __wrapped__ = func
4272 self.assertIsNone(inspect.unwrap(C()))
4273
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01004274 def test_recursion_limit(self):
4275 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
4276 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4277 inspect.unwrap(obj)
4278
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004279class TestMain(unittest.TestCase):
4280 def test_only_source(self):
4281 module = importlib.import_module('unittest')
4282 rc, out, err = assert_python_ok('-m', 'inspect',
4283 'unittest')
4284 lines = out.decode().splitlines()
4285 # ignore the final newline
4286 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
4287 self.assertEqual(err, b'')
4288
Yury Selivanov42407ab2014-06-23 10:23:50 -07004289 def test_custom_getattr(self):
4290 def foo():
4291 pass
4292 foo.__signature__ = 42
4293 with self.assertRaises(TypeError):
4294 inspect.signature(foo)
4295
Brett Cannon634a8fc2013-10-02 10:25:42 -04004296 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04004297 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004298 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004299 rc, out, err = assert_python_ok('-m', 'inspect',
4300 'concurrent.futures:ThreadPoolExecutor')
4301 lines = out.decode().splitlines()
4302 # ignore the final newline
4303 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04004304 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004305 self.assertEqual(err, b'')
4306
4307 def test_builtins(self):
4308 module = importlib.import_module('unittest')
4309 _, out, err = assert_python_failure('-m', 'inspect',
4310 'sys')
4311 lines = err.decode().splitlines()
4312 self.assertEqual(lines, ["Can't get info for builtin modules."])
4313
4314 def test_details(self):
4315 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01004316 args = support.optim_args_from_interpreter_flags()
4317 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004318 'unittest', '--details')
4319 output = out.decode()
4320 # Just a quick sanity check on the output
4321 self.assertIn(module.__name__, output)
4322 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01004323 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004324 self.assertEqual(err, b'')
4325
4326
Yury Selivanovef1e7502014-12-08 16:05:34 -05004327class TestReload(unittest.TestCase):
4328
4329 src_before = textwrap.dedent("""\
4330def foo():
4331 print("Bla")
4332 """)
4333
4334 src_after = textwrap.dedent("""\
4335def foo():
4336 print("Oh no!")
4337 """)
4338
4339 def assertInspectEqual(self, path, source):
4340 inspected_src = inspect.getsource(source)
Inada Naokifb786922021-04-06 11:18:41 +09004341 with open(path, encoding='utf-8') as src:
Yury Selivanovef1e7502014-12-08 16:05:34 -05004342 self.assertEqual(
4343 src.read().splitlines(True),
4344 inspected_src.splitlines(True)
4345 )
4346
4347 def test_getsource_reload(self):
4348 # see issue 1218234
4349 with _ready_to_import('reload_bug', self.src_before) as (name, path):
4350 module = importlib.import_module(name)
4351 self.assertInspectEqual(path, module)
Inada Naokifb786922021-04-06 11:18:41 +09004352 with open(path, 'w', encoding='utf-8') as src:
Yury Selivanovef1e7502014-12-08 16:05:34 -05004353 src.write(self.src_after)
4354 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004355
Nick Coghlane8c45d62013-07-28 20:00:01 +10004356
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004357def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00004358 run_unittest(
Irit Katriel6e1eec72020-12-04 16:45:38 +00004359 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBlockComments,
4360 TestBuggyCases, TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00004361 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00004362 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004363 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04004364 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04004365 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04004366 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Miss Islington (bot)f468ede2021-07-30 10:46:42 -07004367 TestGetCoroutineState, TestGettingSourceOfToplevelFrames,
4368 TestGetsourceInteractive,
Michael Foord95fc51d2010-11-20 15:07:30 +00004369 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00004370
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004371if __name__ == "__main__":
4372 test_main()