blob: a9778282d90a4ea0e5f61dbc14d5d365b5951976 [file] [log] [blame]
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001import builtins
Guido van Rossum813b0e52007-05-21 18:11:34 +00002import collections
Larry Hastings5c661892014-01-24 06:17:25 -08003import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10004import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10005import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08006import inspect
7import io
8import linecache
9import os
Christian Heimesa3538eb2007-11-06 11:44:48 +000010from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080011import _pickle
Yury Selivanova5d63dd2014-03-27 11:31:43 -040012import pickle
Larry Hastings5c661892014-01-24 06:17:25 -080013import shutil
14import sys
15import types
Yury Selivanovef1e7502014-12-08 16:05:34 -050016import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080017import unicodedata
18import unittest
Yury Selivanova773de02014-02-21 18:30:53 -050019import unittest.mock
Yury Selivanov75445082015-05-11 22:57:16 -040020import warnings
Larry Hastings5c661892014-01-24 06:17:25 -080021
Brett Cannon634a8fc2013-10-02 10:25:42 -040022try:
23 from concurrent.futures import ThreadPoolExecutor
24except ImportError:
25 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000026
Hai Shic7decc22020-08-04 23:53:12 +080027from test.support import run_unittest, cpython_only
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +030028from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ
Hai Shic7decc22020-08-04 23:53:12 +080029from test.support.import_helper import DirsOnSysPath
30from test.support.os_helper import TESTFN
Berker Peksagce643912015-05-06 06:33:17 +030031from test.support.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000032from test import inspect_fodder as mod
33from test import inspect_fodder2 as mod2
Victor Stinner9def2842016-01-18 12:15:08 +010034from test import support
larryhastings74613a42021-04-29 21:16:28 -070035from test import inspect_stock_annotations
36from test import inspect_stringized_annotations
37from test import inspect_stringized_annotations_2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000038
Yury Selivanovef1e7502014-12-08 16:05:34 -050039from test.test_import import _ready_to_import
40
R. David Murray74b89242009-05-13 17:33:03 +000041
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000042# Functions tested in this suite:
43# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000044# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
45# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
Berker Peksagfa3922c2015-07-31 04:11:29 +030046# getclasstree, getargvalues, formatargspec, formatargvalues,
Christian Heimes7131fd92008-02-19 14:21:46 +000047# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000048
Nick Coghlanf088e5e2008-12-14 11:50:48 +000049# NOTE: There are some additional tests relating to interaction with
50# zipimport in the test_zipimport_support test module.
51
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000052modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000053if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000054 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000055
Christian Heimesa3538eb2007-11-06 11:44:48 +000056# Normalize file names: on Windows, the case of file names of compiled
57# modules depends on the path used to start the python executable.
58modfile = normcase(modfile)
59
60def revise(filename, *args):
61 return (normcase(filename),) + args
62
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000063git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000064
larryhastingsf36ba122018-01-28 11:13:09 -080065
66def signatures_with_lexicographic_keyword_only_parameters():
67 """
68 Yields a whole bunch of functions with only keyword-only parameters,
69 where those parameters are always in lexicographically sorted order.
70 """
71 parameters = ['a', 'bar', 'c', 'delta', 'ephraim', 'magical', 'yoyo', 'z']
72 for i in range(1, 2**len(parameters)):
73 p = []
74 bit = 1
75 for j in range(len(parameters)):
76 if i & (bit << j):
77 p.append(parameters[j])
78 fn_text = "def foo(*, " + ", ".join(p) + "): pass"
79 symbols = {}
80 exec(fn_text, symbols, symbols)
81 yield symbols['foo']
82
83
84def unsorted_keyword_only_parameters_fn(*, throw, out, the, baby, with_,
85 the_, bathwater):
86 pass
87
88unsorted_keyword_only_parameters = 'throw out the baby with_ the_ bathwater'.split()
89
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000090class IsTestBase(unittest.TestCase):
91 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
92 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000093 inspect.ismodule, inspect.istraceback,
Yury Selivanov75445082015-05-11 22:57:16 -040094 inspect.isgenerator, inspect.isgeneratorfunction,
Yury Selivanoveb636452016-09-08 22:01:51 -070095 inspect.iscoroutine, inspect.iscoroutinefunction,
96 inspect.isasyncgen, inspect.isasyncgenfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000097
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000098 def istest(self, predicate, exp):
99 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000100 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000101
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000102 for other in self.predicates - set([predicate]):
Yury Selivanov75445082015-05-11 22:57:16 -0400103 if (predicate == inspect.isgeneratorfunction or \
Yury Selivanoveb636452016-09-08 22:01:51 -0700104 predicate == inspect.isasyncgenfunction or \
Yury Selivanov75445082015-05-11 22:57:16 -0400105 predicate == inspect.iscoroutinefunction) and \
Christian Heimes7131fd92008-02-19 14:21:46 +0000106 other == inspect.isfunction:
107 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000108 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000109
Christian Heimes7131fd92008-02-19 14:21:46 +0000110def generator_function_example(self):
111 for i in range(2):
112 yield i
113
Yury Selivanoveb636452016-09-08 22:01:51 -0700114async def async_generator_function_example(self):
115 async for i in range(2):
116 yield i
117
Yury Selivanov75445082015-05-11 22:57:16 -0400118async def coroutine_function_example(self):
119 return 'spam'
120
121@types.coroutine
122def gen_coroutine_function_example(self):
123 yield
124 return 'spam'
125
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000126class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +0000127
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000128 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200129 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000130 self.istest(inspect.isbuiltin, 'sys.exit')
131 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +0000132 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200133 try:
134 1/0
135 except:
136 tb = sys.exc_info()[2]
137 self.istest(inspect.isframe, 'tb.tb_frame')
138 self.istest(inspect.istraceback, 'tb')
139 if hasattr(types, 'GetSetDescriptorType'):
140 self.istest(inspect.isgetsetdescriptor,
141 'type(tb.tb_frame).f_locals')
142 else:
143 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
144 finally:
145 # Clear traceback and all the frames and local variables hanging to it.
146 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000147 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000148 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000149 self.istest(inspect.ismethod, 'git.argue')
Jeroen Demeyerfcef60f2019-04-02 16:03:42 +0200150 self.istest(inspect.ismethod, 'mod.custom_method')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000151 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000152 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000153 self.istest(inspect.isgenerator, '(x for x in range(2))')
154 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanoveb636452016-09-08 22:01:51 -0700155 self.istest(inspect.isasyncgen,
156 'async_generator_function_example(1)')
157 self.istest(inspect.isasyncgenfunction,
158 'async_generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400159
160 with warnings.catch_warnings():
161 warnings.simplefilter("ignore")
162 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
163 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
164
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000165 if hasattr(types, 'MemberDescriptorType'):
166 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
167 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000168 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000169
Yury Selivanov75445082015-05-11 22:57:16 -0400170 def test_iscoroutine(self):
Pablo Galindo7cd25432018-10-26 12:19:14 +0100171 async_gen_coro = async_generator_function_example(1)
Yury Selivanov75445082015-05-11 22:57:16 -0400172 gen_coro = gen_coroutine_function_example(1)
173 coro = coroutine_function_example(1)
174
Yury Selivanov5376ba92015-06-22 12:19:30 -0400175 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400176 inspect.iscoroutinefunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100177 self.assertFalse(
178 inspect.iscoroutinefunction(
179 functools.partial(functools.partial(
180 gen_coroutine_function_example))))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400181 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400182
183 self.assertTrue(
184 inspect.isgeneratorfunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100185 self.assertTrue(
186 inspect.isgeneratorfunction(
187 functools.partial(functools.partial(
188 gen_coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400189 self.assertTrue(inspect.isgenerator(gen_coro))
190
191 self.assertTrue(
192 inspect.iscoroutinefunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100193 self.assertTrue(
194 inspect.iscoroutinefunction(
195 functools.partial(functools.partial(
196 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400197 self.assertTrue(inspect.iscoroutine(coro))
198
199 self.assertFalse(
200 inspect.isgeneratorfunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100201 self.assertFalse(
202 inspect.isgeneratorfunction(
203 functools.partial(functools.partial(
204 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400205 self.assertFalse(inspect.isgenerator(coro))
206
Pablo Galindo7cd25432018-10-26 12:19:14 +0100207 self.assertTrue(
208 inspect.isasyncgenfunction(async_generator_function_example))
209 self.assertTrue(
210 inspect.isasyncgenfunction(
211 functools.partial(functools.partial(
212 async_generator_function_example))))
213 self.assertTrue(inspect.isasyncgen(async_gen_coro))
214
215 coro.close(); gen_coro.close(); # silence warnings
Yury Selivanov75445082015-05-11 22:57:16 -0400216
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400217 def test_isawaitable(self):
218 def gen(): yield
219 self.assertFalse(inspect.isawaitable(gen()))
220
221 coro = coroutine_function_example(1)
222 gen_coro = gen_coroutine_function_example(1)
223
224 self.assertTrue(inspect.isawaitable(coro))
225 self.assertTrue(inspect.isawaitable(gen_coro))
226
227 class Future:
228 def __await__():
229 pass
230 self.assertTrue(inspect.isawaitable(Future()))
231 self.assertFalse(inspect.isawaitable(Future))
232
233 class NotFuture: pass
234 not_fut = NotFuture()
235 not_fut.__await__ = lambda: None
236 self.assertFalse(inspect.isawaitable(not_fut))
237
238 coro.close(); gen_coro.close() # silence warnings
239
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000240 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000241 self.assertTrue(inspect.isroutine(mod.spam))
242 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000243
Benjamin Petersonc4656002009-01-17 22:41:18 +0000244 def test_isclass(self):
245 self.istest(inspect.isclass, 'mod.StupidGit')
246 self.assertTrue(inspect.isclass(list))
247
248 class CustomGetattr(object):
249 def __getattr__(self, attr):
250 return None
251 self.assertFalse(inspect.isclass(CustomGetattr()))
252
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000253 def test_get_slot_members(self):
254 class C(object):
255 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000256 x = C()
257 x.a = 42
258 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000259 self.assertIn('a', members)
260 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000261
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000262 def test_isabstract(self):
263 from abc import ABCMeta, abstractmethod
264
265 class AbstractClassExample(metaclass=ABCMeta):
266
267 @abstractmethod
268 def foo(self):
269 pass
270
271 class ClassExample(AbstractClassExample):
272 def foo(self):
273 pass
274
275 a = ClassExample()
276
277 # Test general behaviour.
278 self.assertTrue(inspect.isabstract(AbstractClassExample))
279 self.assertFalse(inspect.isabstract(ClassExample))
280 self.assertFalse(inspect.isabstract(a))
281 self.assertFalse(inspect.isabstract(int))
282 self.assertFalse(inspect.isabstract(5))
283
Natefcfe80e2017-04-24 10:06:15 -0700284 def test_isabstract_during_init_subclass(self):
285 from abc import ABCMeta, abstractmethod
286 isabstract_checks = []
287 class AbstractChecker(metaclass=ABCMeta):
288 def __init_subclass__(cls):
289 isabstract_checks.append(inspect.isabstract(cls))
290 class AbstractClassExample(AbstractChecker):
291 @abstractmethod
292 def foo(self):
293 pass
294 class ClassExample(AbstractClassExample):
295 def foo(self):
296 pass
297 self.assertEqual(isabstract_checks, [True, False])
298
299 isabstract_checks.clear()
300 class AbstractChild(AbstractClassExample):
301 pass
302 class AbstractGrandchild(AbstractChild):
303 pass
304 class ConcreteGrandchild(ClassExample):
305 pass
306 self.assertEqual(isabstract_checks, [True, True, False])
307
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000308
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000309class TestInterpreterStack(IsTestBase):
310 def __init__(self, *args, **kwargs):
311 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000312
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000313 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000314
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000315 def test_abuse_done(self):
316 self.istest(inspect.istraceback, 'git.ex[2]')
317 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000318
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000319 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000320 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000321 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000322 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000323 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000324 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000325 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000326 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000327 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000328 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400329 # Test named tuple fields
330 record = mod.st[0]
331 self.assertIs(record.frame, mod.fr)
332 self.assertEqual(record.lineno, 16)
333 self.assertEqual(record.filename, mod.__file__)
334 self.assertEqual(record.function, 'eggs')
335 self.assertIn('inspect.stack()', record.code_context[0])
336 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000337
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000338 def test_trace(self):
339 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000340 self.assertEqual(revise(*git.tr[0][1:]),
341 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
342 self.assertEqual(revise(*git.tr[1][1:]),
343 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
344 self.assertEqual(revise(*git.tr[2][1:]),
345 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000346
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000347 def test_frame(self):
348 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
349 self.assertEqual(args, ['x', 'y'])
350 self.assertEqual(varargs, None)
351 self.assertEqual(varkw, None)
352 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
353 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
354 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000355
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000356 def test_previous_frame(self):
357 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000358 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000359 self.assertEqual(varargs, 'g')
360 self.assertEqual(varkw, 'h')
361 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000362 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000363
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000364class GetSourceBase(unittest.TestCase):
365 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000366 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000367
Yury Selivanov6738b112015-05-16 10:10:21 -0400368 def setUp(self):
Inada Naokifb786922021-04-06 11:18:41 +0900369 with open(inspect.getsourcefile(self.fodderModule), encoding="utf-8") as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000370 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000371
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000372 def sourcerange(self, top, bottom):
373 lines = self.source.split("\n")
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700374 return "\n".join(lines[top-1:bottom]) + ("\n" if bottom else "")
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000375
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000376 def assertSourceEqual(self, obj, top, bottom):
377 self.assertEqual(inspect.getsource(obj),
378 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000379
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700380class SlotUser:
381 'Docstrings for __slots__'
382 __slots__ = {'power': 'measured in kilowatts',
383 'distance': 'measured in kilometers'}
384
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000385class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000386 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000387
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000388 def test_getclasses(self):
389 classes = inspect.getmembers(mod, inspect.isclass)
390 self.assertEqual(classes,
391 [('FesteringGob', mod.FesteringGob),
392 ('MalodorousPervert', mod.MalodorousPervert),
393 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300394 ('StupidGit', mod.StupidGit),
395 ('Tit', mod.MalodorousPervert),
Irit Katriel6e1eec72020-12-04 16:45:38 +0000396 ('WhichComments', mod.WhichComments),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300397 ])
398 tree = inspect.getclasstree([cls[1] for cls in classes])
399 self.assertEqual(tree,
400 [(object, ()),
401 [(mod.ParrotDroppings, (object,)),
402 [(mod.FesteringGob, (mod.MalodorousPervert,
403 mod.ParrotDroppings))
404 ],
405 (mod.StupidGit, (object,)),
406 [(mod.MalodorousPervert, (mod.StupidGit,)),
407 [(mod.FesteringGob, (mod.MalodorousPervert,
408 mod.ParrotDroppings))
409 ]
Irit Katriel6e1eec72020-12-04 16:45:38 +0000410 ],
411 (mod.WhichComments, (object,),)
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300412 ]
413 ])
414 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000415 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000416 [(object, ()),
417 [(mod.ParrotDroppings, (object,)),
418 (mod.StupidGit, (object,)),
419 [(mod.MalodorousPervert, (mod.StupidGit,)),
420 [(mod.FesteringGob, (mod.MalodorousPervert,
421 mod.ParrotDroppings))
422 ]
Irit Katriel6e1eec72020-12-04 16:45:38 +0000423 ],
424 (mod.WhichComments, (object,),)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000425 ]
426 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000427
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000428 def test_getfunctions(self):
429 functions = inspect.getmembers(mod, inspect.isfunction)
430 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300431 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000432 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000433
R. David Murray378c0cf2010-02-24 01:46:21 +0000434 @unittest.skipIf(sys.flags.optimize >= 2,
435 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000436 def test_getdoc(self):
437 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
438 self.assertEqual(inspect.getdoc(mod.StupidGit),
439 'A longer,\n\nindented\n\ndocstring.')
440 self.assertEqual(inspect.getdoc(git.abuse),
441 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700442 self.assertEqual(inspect.getdoc(SlotUser.power),
443 'measured in kilowatts')
444 self.assertEqual(inspect.getdoc(SlotUser.distance),
445 'measured in kilometers')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000446
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300447 @unittest.skipIf(sys.flags.optimize >= 2,
448 "Docstrings are omitted with -O2 and above")
449 def test_getdoc_inherited(self):
Serhiy Storchaka08b47c32020-05-18 20:25:07 +0300450 self.assertEqual(inspect.getdoc(mod.FesteringGob),
451 'A longer,\n\nindented\n\ndocstring.')
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300452 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
453 'Another\n\ndocstring\n\ncontaining\n\ntabs')
454 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
455 'Another\n\ndocstring\n\ncontaining\n\ntabs')
456 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
457 'The automatic gainsaying.')
458
459 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
460 def test_finddoc(self):
461 finddoc = inspect._finddoc
Serhiy Storchaka08b47c32020-05-18 20:25:07 +0300462 self.assertEqual(finddoc(int), int.__doc__)
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300463 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
464 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
465 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
466 self.assertEqual(finddoc(int.real), int.real.__doc__)
467
Georg Brandl0c77a822008-06-10 16:37:50 +0000468 def test_cleandoc(self):
469 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
470 'An\nindented\ndocstring.')
471
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000472 def test_getcomments(self):
473 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
474 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530475 self.assertEqual(inspect.getcomments(mod2.cls160), '# line 159\n')
Marco Buttu3f2155f2017-03-17 09:50:23 +0100476 # If the object source file is not available, return None.
477 co = compile('x=1', '_non_existing_filename.py', 'exec')
478 self.assertIsNone(inspect.getcomments(co))
479 # If the object has been defined in C, return None.
480 self.assertIsNone(inspect.getcomments(list))
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000481
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000482 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000483 # Check actual module
484 self.assertEqual(inspect.getmodule(mod), mod)
485 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000486 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000487 # Check a method (no __module__ attribute, falls back to filename)
488 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
489 # Do it again (check the caching isn't broken)
490 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
491 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000492 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000493 # Check filename override
494 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000495
Berker Peksagff0e3b72017-01-02 06:57:43 +0300496 def test_getframeinfo_get_first_line(self):
497 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
498 self.assertEqual(frame_info.code_context[0], "# line 1\n")
499 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
500
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000501 def test_getsource(self):
502 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200503 self.assertSourceEqual(mod.StupidGit, 21, 51)
504 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000505
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000506 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000507 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
508 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000509 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100510 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000511 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000512 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200513 try:
514 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
515 finally:
516 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000517
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000518 def test_getfile(self):
519 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000520
Philipp Ad407d2a2019-06-08 14:05:46 +0200521 def test_getfile_builtin_module(self):
522 with self.assertRaises(TypeError) as e:
523 inspect.getfile(sys)
524 self.assertTrue(str(e.exception).startswith('<module'))
525
526 def test_getfile_builtin_class(self):
527 with self.assertRaises(TypeError) as e:
528 inspect.getfile(int)
529 self.assertTrue(str(e.exception).startswith('<class'))
530
531 def test_getfile_builtin_function_or_method(self):
532 with self.assertRaises(TypeError) as e_abs:
533 inspect.getfile(abs)
534 self.assertIn('expected, got', str(e_abs.exception))
535 with self.assertRaises(TypeError) as e_append:
536 inspect.getfile(list.append)
537 self.assertIn('expected, got', str(e_append.exception))
538
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500539 def test_getfile_class_without_module(self):
540 class CM(type):
541 @property
542 def __module__(cls):
543 raise AttributeError
544 class C(metaclass=CM):
545 pass
546 with self.assertRaises(TypeError):
547 inspect.getfile(C)
548
Thomas Kluyvere968bc732017-10-24 13:42:36 +0100549 def test_getfile_broken_repr(self):
550 class ErrorRepr:
551 def __repr__(self):
552 raise Exception('xyz')
553 er = ErrorRepr()
554 with self.assertRaises(TypeError):
555 inspect.getfile(er)
556
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000557 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000558 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000559 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000560 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000561 m.__file__ = "<string>" # hopefully not a real filename...
562 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000563 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000564 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000565 del sys.modules[name]
566 inspect.getmodule(compile('a=10','','single'))
567
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500568 def test_proceed_with_fake_filename(self):
569 '''doctest monkeypatches linecache to enable inspection'''
570 fn, source = '<test>', 'def x(): pass\n'
571 getlines = linecache.getlines
572 def monkey(filename, module_globals=None):
573 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300574 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500575 else:
576 return getlines(filename, module_globals)
577 linecache.getlines = monkey
578 try:
579 ns = {}
580 exec(compile(source, fn, 'single'), ns)
581 inspect.getsource(ns["x"])
582 finally:
583 linecache.getlines = getlines
584
Antoine Pitroua8723a02015-04-15 00:41:29 +0200585 def test_getsource_on_code_object(self):
586 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
587
Miss Islington (bot)f468ede2021-07-30 10:46:42 -0700588class TestGetsourceInteractive(unittest.TestCase):
Miss Islington (bot)f468ede2021-07-30 10:46:42 -0700589 def test_getclasses_interactive(self):
Miss Islington (bot)bc2841c2021-08-03 06:07:59 -0700590 # bpo-44648: simulate a REPL session;
591 # there is no `__file__` in the __main__ module
592 code = "import sys, inspect; \
593 assert not hasattr(sys.modules['__main__'], '__file__'); \
594 A = type('A', (), {}); \
595 inspect.getsource(A)"
596 _, _, stderr = assert_python_failure("-c", code, __isolated=True)
597 self.assertIn(b'OSError: source code not available', stderr)
Miss Islington (bot)f468ede2021-07-30 10:46:42 -0700598
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700599class TestGettingSourceOfToplevelFrames(GetSourceBase):
600 fodderModule = mod
601
602 def test_range_toplevel_frame(self):
603 self.maxDiff = None
604 self.assertSourceEqual(mod.currentframe, 1, None)
605
606 def test_range_traceback_toplevel_frame(self):
607 self.assertSourceEqual(mod.tb, 1, None)
608
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000609class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000610 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000611
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000612 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000613 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000614
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000615 def test_replacing_decorator(self):
616 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000617
Yury Selivanov081bbf62014-09-26 17:34:54 -0400618 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200619 self.assertSourceEqual(mod2.real, 130, 132)
620
621 def test_decorator_with_lambda(self):
622 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400623
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000624class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000625 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000626 def test_oneline_lambda(self):
627 # Test inspect.getsource with a one-line lambda function.
628 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000629
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000630 def test_threeline_lambda(self):
631 # Test inspect.getsource with a three-line lambda function,
632 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000633 self.assertSourceEqual(mod2.tll, 28, 30)
634
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000635 def test_twoline_indented_lambda(self):
636 # Test inspect.getsource with a two-line lambda function,
637 # where the second line _is_ indented.
638 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000639
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000640 def test_onelinefunc(self):
641 # Test inspect.getsource with a regular one-line function.
642 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000643
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000644 def test_manyargs(self):
645 # Test inspect.getsource with a regular function where
646 # the arguments are on two lines and _not_ indented and
647 # the body on the second line with the last arguments.
648 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000649
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000650 def test_twolinefunc(self):
651 # Test inspect.getsource with a regular function where
652 # the body is on two lines, following the argument list and
653 # continued on the next line by a \\.
654 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000655
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000656 def test_lambda_in_list(self):
657 # Test inspect.getsource with a one-line lambda function
658 # defined in a list, indented.
659 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000660
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000661 def test_anonymous(self):
662 # Test inspect.getsource with a lambda function defined
663 # as argument to another function.
664 self.assertSourceEqual(mod2.anonymous, 55, 55)
665
Irit Katriel6e1eec72020-12-04 16:45:38 +0000666class TestBlockComments(GetSourceBase):
667 fodderModule = mod
668
669 def test_toplevel_class(self):
670 self.assertSourceEqual(mod.WhichComments, 96, 114)
671
672 def test_class_method(self):
673 self.assertSourceEqual(mod.WhichComments.f, 99, 104)
674
675 def test_class_async_method(self):
676 self.assertSourceEqual(mod.WhichComments.asyncf, 109, 112)
677
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000678class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000679 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000680
681 def test_with_comment(self):
682 self.assertSourceEqual(mod2.with_comment, 58, 59)
683
684 def test_multiline_sig(self):
685 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
686
Armin Rigodd5c0232005-09-25 11:45:45 +0000687 def test_nested_class(self):
688 self.assertSourceEqual(mod2.func69().func71, 71, 72)
689
690 def test_one_liner_followed_by_non_name(self):
691 self.assertSourceEqual(mod2.func77, 77, 77)
692
693 def test_one_liner_dedent_non_name(self):
694 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
695
696 def test_with_comment_instead_of_docstring(self):
697 self.assertSourceEqual(mod2.func88, 88, 90)
698
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000699 def test_method_in_dynamic_class(self):
700 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
701
R David Murray32562d72014-10-03 11:15:38 -0400702 # This should not skip for CPython, but might on a repackaged python where
703 # unicodedata is not an external module, or on pypy.
704 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
705 unicodedata.__file__.endswith('.py'),
706 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000707 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200708 self.assertRaises(OSError, inspect.getsource, unicodedata)
709 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000710
R. David Murraya1b37402010-06-17 02:04:29 +0000711 def test_findsource_code_in_linecache(self):
712 lines = ["x=1"]
713 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200714 self.assertRaises(OSError, inspect.findsource, co)
715 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000716 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200717 try:
718 self.assertEqual(inspect.findsource(co), (lines,0))
719 self.assertEqual(inspect.getsource(co), lines[0])
720 finally:
721 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000722
Ezio Melotti1b145922013-03-30 05:17:24 +0200723 def test_findsource_without_filename(self):
724 for fname in ['', '<string>']:
725 co = compile('x=1', fname, "exec")
726 self.assertRaises(IOError, inspect.findsource, co)
727 self.assertRaises(IOError, inspect.getsource, co)
728
Irit Katriel2e0760b2020-12-04 21:22:03 +0000729 def test_findsource_with_out_of_bounds_lineno(self):
730 mod_len = len(inspect.getsource(mod))
731 src = '\n' * 2* mod_len + "def f(): pass"
732 co = compile(src, mod.__file__, "exec")
733 g, l = {}, {}
734 eval(co, g, l)
735 func = l['f']
736 self.assertEqual(func.__code__.co_firstlineno, 1+2*mod_len)
737 with self.assertRaisesRegex(IOError, "lineno is out of bounds"):
738 inspect.findsource(func)
739
Antoine Pitroua8723a02015-04-15 00:41:29 +0200740 def test_getsource_on_method(self):
741 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
742
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300743 def test_nested_func(self):
744 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
745
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530746 def test_class_definition_in_multiline_string_definition(self):
747 self.assertSourceEqual(mod2.cls149, 149, 152)
748
749 def test_class_definition_in_multiline_comment(self):
750 self.assertSourceEqual(mod2.cls160, 160, 163)
751
752 def test_nested_class_definition_indented_string(self):
753 self.assertSourceEqual(mod2.cls173.cls175, 175, 176)
754
755 def test_nested_class_definition(self):
756 self.assertSourceEqual(mod2.cls183, 183, 188)
757 self.assertSourceEqual(mod2.cls183.cls185, 185, 188)
758
759 def test_class_decorator(self):
760 self.assertSourceEqual(mod2.cls196, 194, 201)
761 self.assertSourceEqual(mod2.cls196.cls200, 198, 201)
762
763 def test_class_inside_conditional(self):
764 self.assertSourceEqual(mod2.cls238, 238, 240)
765 self.assertSourceEqual(mod2.cls238.cls239, 239, 240)
766
767 def test_multiple_children_classes(self):
768 self.assertSourceEqual(mod2.cls203, 203, 209)
769 self.assertSourceEqual(mod2.cls203.cls204, 204, 206)
770 self.assertSourceEqual(mod2.cls203.cls204.cls205, 205, 206)
771 self.assertSourceEqual(mod2.cls203.cls207, 207, 209)
772 self.assertSourceEqual(mod2.cls203.cls207.cls205, 208, 209)
773
774 def test_nested_class_definition_inside_function(self):
775 self.assertSourceEqual(mod2.func212(), 213, 214)
776 self.assertSourceEqual(mod2.cls213, 218, 222)
777 self.assertSourceEqual(mod2.cls213().func219(), 220, 221)
778
779 def test_nested_class_definition_inside_async_function(self):
780 import asyncio
781 self.addCleanup(asyncio.set_event_loop_policy, None)
782 self.assertSourceEqual(asyncio.run(mod2.func225()), 226, 227)
783 self.assertSourceEqual(mod2.cls226, 231, 235)
784 self.assertSourceEqual(asyncio.run(mod2.cls226().func232()), 233, 234)
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300785
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000786class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400787 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000788 self.tempdir = TESTFN + '_dir'
789 os.mkdir(self.tempdir)
Inada Naokifb786922021-04-06 11:18:41 +0900790 with open(os.path.join(self.tempdir, 'inspect_fodder3%spy' % os.extsep),
791 'w', encoding='utf-8') as f:
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000792 f.write("class X:\n pass # No EOL")
793 with DirsOnSysPath(self.tempdir):
794 import inspect_fodder3 as mod3
795 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400796 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000797
798 def tearDown(self):
799 shutil.rmtree(self.tempdir)
800
801 def test_class(self):
802 self.assertSourceEqual(self.fodderModule.X, 1, 2)
803
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100804
805class _BrokenDataDescriptor(object):
806 """
807 A broken data descriptor. See bug #1785.
808 """
809 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700810 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100811
812 def __set__(*args):
813 raise RuntimeError
814
815 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700816 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100817
818
819class _BrokenMethodDescriptor(object):
820 """
821 A broken method descriptor. See bug #1785.
822 """
823 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700824 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100825
826 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700827 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100828
829
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000830# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000831def attrs_wo_objs(cls):
832 return [t[:3] for t in inspect.classify_class_attrs(cls)]
833
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100834
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000835class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000836 def test_newstyle_mro(self):
837 # The same w/ new-class MRO.
838 class A(object): pass
839 class B(A): pass
840 class C(A): pass
841 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000842
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000843 expected = (D, B, C, A, object)
844 got = inspect.getmro(D)
845 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000846
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500847 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
848 varkw_e=None, defaults_e=None, formatted=None):
Xtreak6d0b7472019-05-30 17:31:39 +0530849 with self.assertWarns(DeprecationWarning):
850 args, varargs, varkw, defaults = inspect.getargspec(routine)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500851 self.assertEqual(args, args_e)
852 self.assertEqual(varargs, varargs_e)
853 self.assertEqual(varkw, varkw_e)
854 self.assertEqual(defaults, defaults_e)
855 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530856 with self.assertWarns(DeprecationWarning):
857 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
858 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500859
Christian Heimes3795b532007-11-08 13:48:53 +0000860 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
861 varkw_e=None, defaults_e=None,
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100862 posonlyargs_e=[], kwonlyargs_e=[],
863 kwonlydefaults_e=None,
Christian Heimes3795b532007-11-08 13:48:53 +0000864 ann_e={}, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100865 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
866 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000867 self.assertEqual(args, args_e)
868 self.assertEqual(varargs, varargs_e)
869 self.assertEqual(varkw, varkw_e)
870 self.assertEqual(defaults, defaults_e)
871 self.assertEqual(kwonlyargs, kwonlyargs_e)
872 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
873 self.assertEqual(ann, ann_e)
874 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530875 with self.assertWarns(DeprecationWarning):
876 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
877 kwonlyargs, kwonlydefaults, ann),
878 formatted)
Christian Heimes3795b532007-11-08 13:48:53 +0000879
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500880 def test_getargspec(self):
881 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
882
Pablo Galindod5d2b452019-04-30 02:01:14 +0100883 self.assertArgSpecEquals(mod.spam,
884 ['a', 'b', 'c', 'd', 'e', 'f'],
885 'g', 'h', (3, 4, 5),
886 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500887
888 self.assertRaises(ValueError, self.assertArgSpecEquals,
889 mod2.keyworded, [])
890
891 self.assertRaises(ValueError, self.assertArgSpecEquals,
892 mod2.annotated, [])
893 self.assertRaises(ValueError, self.assertArgSpecEquals,
894 mod2.keyword_only_arg, [])
895
896
Christian Heimes3795b532007-11-08 13:48:53 +0000897 def test_getfullargspec(self):
898 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
899 kwonlyargs_e=['arg2'],
900 kwonlydefaults_e={'arg2':1},
901 formatted='(*arg1, arg2=1)')
902
903 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000904 ann_e={'arg1' : list},
Pablo Galindob0544ba2021-04-21 12:41:19 +0100905 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000906 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
907 kwonlyargs_e=['arg'],
908 formatted='(*, arg)')
909
Pablo Galindod5d2b452019-04-30 02:01:14 +0100910 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100911 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100912 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100913
914 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100915 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100916 varargs_e='args',
917 varkw_e='kwargs',
918 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100919 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100920
Pablo Galindod5d2b452019-04-30 02:01:14 +0100921 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100922 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100923 kwonlyargs_e=['e', 'f'],
924 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100925 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100926
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500927 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500928 # Issue 20684: low level introspection API must ignore __wrapped__
929 @functools.wraps(mod.spam)
930 def ham(x, y):
931 pass
932 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500933 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500934 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
935 self.assertFullArgSpecEquals(functools.partial(ham),
936 ['x', 'y'], formatted='(x, y)')
937 # Other variants
938 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500939 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
940 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500941 class C:
942 @functools.wraps(mod.spam)
943 def ham(self, x, y):
944 pass
945 pham = functools.partialmethod(ham)
946 @functools.wraps(mod.spam)
947 def __call__(self, x, y):
948 pass
949 check_method(C())
950 check_method(C.ham)
951 check_method(C().ham)
952 check_method(C.pham)
953 check_method(C().pham)
954
955 class C_new:
956 @functools.wraps(mod.spam)
957 def __new__(self, x, y):
958 pass
959 check_method(C_new)
960
961 class C_init:
962 @functools.wraps(mod.spam)
963 def __init__(self, x, y):
964 pass
965 check_method(C_init)
966
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500967 def test_getfullargspec_signature_attr(self):
968 def test():
969 pass
970 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
971 test.__signature__ = inspect.Signature(parameters=(spam_param,))
972
Pablo Galindod5d2b452019-04-30 02:01:14 +0100973 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500974
Yury Selivanov4cb93912014-01-29 11:54:12 -0500975 def test_getfullargspec_signature_annos(self):
976 def test(a:'spam') -> 'ham': pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100977 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500978 self.assertEqual(test.__annotations__, spec.annotations)
979
980 def test(): 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
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500984 @unittest.skipIf(MISSING_C_DOCSTRINGS,
985 "Signature information for builtins requires docstrings")
986 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100987 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
988 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500989
Pablo Galindod5d2b452019-04-30 02:01:14 +0100990 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
991 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500992
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500993 self.assertFullArgSpecEquals(
994 os.stat,
995 args_e=['path'],
996 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
997 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
998 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
999
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001000 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001001 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1002 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +08001003 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001004 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001005 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindoaee19f52019-05-16 21:08:15 +01001006 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001007 self.assertEqual(spec.defaults[0], 'avocado')
1008
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001009 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001010 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1011 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +08001012 def test_getfullargspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001013 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001014 builtin = _testcapi.docstring_no_signature
Pablo Galindoaee19f52019-05-16 21:08:15 +01001015 with self.assertRaises(TypeError):
1016 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +00001017
larryhastingsf36ba122018-01-28 11:13:09 -08001018 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
1019 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindoaee19f52019-05-16 21:08:15 +01001020 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -08001021 l = list(signature.kwonlyargs)
1022 sorted_l = sorted(l)
1023 self.assertTrue(l)
1024 self.assertEqual(l, sorted_l)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001025 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -08001026 l = list(signature.kwonlyargs)
1027 self.assertEqual(l, unsorted_keyword_only_parameters)
1028
Yury Selivanov37dc2b22016-01-11 15:15:01 -05001029 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001030 class A(object):
1031 def m(self):
1032 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -05001033 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +00001034
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001035 def test_classify_newstyle(self):
1036 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +00001037
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001038 def s(): pass
1039 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +00001040
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001041 def c(cls): pass
1042 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +00001043
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001044 def getp(self): pass
1045 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +00001046
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001047 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001048
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001049 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001050
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001051 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +00001052
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001053 dd = _BrokenDataDescriptor()
1054 md = _BrokenMethodDescriptor()
1055
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001056 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001057
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001058 self.assertIn(('__new__', 'static method', object), attrs,
1059 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001060 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
1061
Benjamin Peterson577473f2010-01-19 00:09:57 +00001062 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1063 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1064 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001065 self.assertIn(('m', 'method', A), attrs,
1066 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001067 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1068 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001069 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1070 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001071
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001072 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001073
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001074 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001075
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001076 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001077 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1078 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1079 self.assertIn(('p', 'property', A), attrs, 'missing property')
1080 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1081 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1082 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001083 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1084 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001085
1086
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001087 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001088
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001089 def m(self): pass
1090 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001091
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001092 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001093 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1094 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1095 self.assertIn(('p', 'property', A), attrs, 'missing property')
1096 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
1097 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1098 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001099 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1100 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001101
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001102 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001103
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001104 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001105
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001106 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001107 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1108 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1109 self.assertIn(('p', 'property', A), attrs, 'missing property')
1110 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1111 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1112 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001113 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1114 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1115
1116 def test_classify_builtin_types(self):
1117 # Simple sanity check that all built-in types can have their
1118 # attributes classified.
1119 for name in dir(__builtins__):
1120 builtin = getattr(__builtins__, name)
1121 if isinstance(builtin, type):
1122 inspect.classify_class_attrs(builtin)
1123
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001124 attrs = attrs_wo_objs(bool)
1125 self.assertIn(('__new__', 'static method', bool), attrs,
1126 'missing __new__')
1127 self.assertIn(('from_bytes', 'class method', int), attrs,
1128 'missing class method')
1129 self.assertIn(('to_bytes', 'method', int), attrs,
1130 'missing plain method')
1131 self.assertIn(('__add__', 'method', int), attrs,
1132 'missing plain method')
1133 self.assertIn(('__and__', 'method', bool), attrs,
1134 'missing plain method')
1135
Ethan Furman63c141c2013-10-18 00:27:39 -07001136 def test_classify_DynamicClassAttribute(self):
1137 class Meta(type):
1138 def __getattr__(self, name):
1139 if name == 'ham':
1140 return 'spam'
1141 return super().__getattr__(name)
1142 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001143 @types.DynamicClassAttribute
1144 def ham(self):
1145 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001146 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1147 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001148 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001149 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1150
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001151 def test_classify_overrides_bool(self):
1152 class NoBool(object):
1153 def __eq__(self, other):
1154 return NoBool()
1155
1156 def __bool__(self):
1157 raise NotImplementedError(
1158 "This object does not specify a boolean value")
1159
1160 class HasNB(object):
1161 dd = NoBool()
1162
1163 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1164 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1165
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001166 def test_classify_metaclass_class_attribute(self):
1167 class Meta(type):
1168 fish = 'slap'
1169 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001170 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001171 class Class(metaclass=Meta):
1172 pass
1173 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1174 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1175
Ethan Furman63c141c2013-10-18 00:27:39 -07001176 def test_classify_VirtualAttribute(self):
1177 class Meta(type):
1178 def __dir__(cls):
1179 return ['__class__', '__module__', '__name__', 'BOOM']
1180 def __getattr__(self, name):
1181 if name =='BOOM':
1182 return 42
1183 return super().__getattr(name)
1184 class Class(metaclass=Meta):
1185 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001186 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001187 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1188
1189 def test_classify_VirtualAttribute_multi_classes(self):
1190 class Meta1(type):
1191 def __dir__(cls):
1192 return ['__class__', '__module__', '__name__', 'one']
1193 def __getattr__(self, name):
1194 if name =='one':
1195 return 1
1196 return super().__getattr__(name)
1197 class Meta2(type):
1198 def __dir__(cls):
1199 return ['__class__', '__module__', '__name__', 'two']
1200 def __getattr__(self, name):
1201 if name =='two':
1202 return 2
1203 return super().__getattr__(name)
1204 class Meta3(Meta1, Meta2):
1205 def __dir__(cls):
1206 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1207 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1208 def __getattr__(self, name):
1209 if name =='three':
1210 return 3
1211 return super().__getattr__(name)
1212 class Class1(metaclass=Meta1):
1213 pass
1214 class Class2(Class1, metaclass=Meta3):
1215 pass
1216
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001217 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1218 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1219 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001220 cca = inspect.classify_class_attrs(Class2)
1221 for sf in (should_find1, should_find2, should_find3):
1222 self.assertIn(sf, cca)
1223
1224 def test_classify_class_attrs_with_buggy_dir(self):
1225 class M(type):
1226 def __dir__(cls):
1227 return ['__class__', '__name__', 'missing']
1228 class C(metaclass=M):
1229 pass
1230 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1231 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001232
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001233 def test_getmembers_descriptors(self):
1234 class A(object):
1235 dd = _BrokenDataDescriptor()
1236 md = _BrokenMethodDescriptor()
1237
1238 def pred_wrapper(pred):
1239 # A quick'n'dirty way to discard standard attributes of new-style
1240 # classes.
1241 class Empty(object):
1242 pass
1243 def wrapped(x):
1244 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1245 return False
1246 return pred(x)
1247 return wrapped
1248
1249 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1250 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1251
1252 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1253 [('md', A.__dict__['md'])])
1254 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1255 [('dd', A.__dict__['dd'])])
1256
1257 class B(A):
1258 pass
1259
1260 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1261 [('md', A.__dict__['md'])])
1262 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1263 [('dd', A.__dict__['dd'])])
1264
Antoine Pitrou0c603812012-01-18 17:40:18 +01001265 def test_getmembers_method(self):
1266 class B:
1267 def f(self):
1268 pass
1269
1270 self.assertIn(('f', B.f), inspect.getmembers(B))
1271 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1272 b = B()
1273 self.assertIn(('f', b.f), inspect.getmembers(b))
1274 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1275
Ethan Furmane03ea372013-09-25 07:14:41 -07001276 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001277 class M(type):
1278 def __getattr__(cls, name):
1279 if name == 'eggs':
1280 return 'scrambled'
1281 return super().__getattr__(name)
1282 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001283 @types.DynamicClassAttribute
1284 def eggs(self):
1285 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001286 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1287 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1288
1289 def test_getmembers_with_buggy_dir(self):
1290 class M(type):
1291 def __dir__(cls):
1292 return ['__class__', '__name__', 'missing']
1293 class C(metaclass=M):
1294 pass
1295 attrs = [a[0] for a in inspect.getmembers(C)]
1296 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001297
larryhastings74613a42021-04-29 21:16:28 -07001298 def test_get_annotations_with_stock_annotations(self):
1299 def foo(a:int, b:str): pass
1300 self.assertEqual(inspect.get_annotations(foo), {'a': int, 'b': str})
1301
1302 foo.__annotations__ = {'a': 'foo', 'b':'str'}
1303 self.assertEqual(inspect.get_annotations(foo), {'a': 'foo', 'b': 'str'})
1304
1305 self.assertEqual(inspect.get_annotations(foo, eval_str=True, locals=locals()), {'a': foo, 'b': str})
1306 self.assertEqual(inspect.get_annotations(foo, eval_str=True, globals=locals()), {'a': foo, 'b': str})
1307
1308 isa = inspect_stock_annotations
1309 self.assertEqual(inspect.get_annotations(isa), {'a': int, 'b': str})
1310 self.assertEqual(inspect.get_annotations(isa.MyClass), {'a': int, 'b': str})
1311 self.assertEqual(inspect.get_annotations(isa.function), {'a': int, 'b': str, 'return': isa.MyClass})
1312 self.assertEqual(inspect.get_annotations(isa.function2), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1313 self.assertEqual(inspect.get_annotations(isa.function3), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1314 self.assertEqual(inspect.get_annotations(inspect), {}) # inspect module has no annotations
1315 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass), {})
1316 self.assertEqual(inspect.get_annotations(isa.unannotated_function), {})
1317
1318 self.assertEqual(inspect.get_annotations(isa, eval_str=True), {'a': int, 'b': str})
1319 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=True), {'a': int, 'b': str})
1320 self.assertEqual(inspect.get_annotations(isa.function, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1321 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=True), {'a': int, 'b': str, 'c': isa.MyClass, 'return': isa.MyClass})
1322 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=True), {'a': int, 'b': str, 'c': isa.MyClass})
1323 self.assertEqual(inspect.get_annotations(inspect, eval_str=True), {})
1324 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=True), {})
1325 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=True), {})
1326
1327 self.assertEqual(inspect.get_annotations(isa, eval_str=False), {'a': int, 'b': str})
1328 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=False), {'a': int, 'b': str})
1329 self.assertEqual(inspect.get_annotations(isa.function, eval_str=False), {'a': int, 'b': str, 'return': isa.MyClass})
1330 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=False), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1331 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=False), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1332 self.assertEqual(inspect.get_annotations(inspect, eval_str=False), {})
1333 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=False), {})
1334 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=False), {})
1335
1336 def times_three(fn):
1337 @functools.wraps(fn)
1338 def wrapper(a, b):
1339 return fn(a*3, b*3)
1340 return wrapper
1341
1342 wrapped = times_three(isa.function)
1343 self.assertEqual(wrapped(1, 'x'), isa.MyClass(3, 'xxx'))
1344 self.assertIsNot(wrapped.__globals__, isa.function.__globals__)
1345 self.assertEqual(inspect.get_annotations(wrapped), {'a': int, 'b': str, 'return': isa.MyClass})
1346 self.assertEqual(inspect.get_annotations(wrapped, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1347 self.assertEqual(inspect.get_annotations(wrapped, eval_str=False), {'a': int, 'b': str, 'return': isa.MyClass})
1348
1349 def test_get_annotations_with_stringized_annotations(self):
1350 isa = inspect_stringized_annotations
1351 self.assertEqual(inspect.get_annotations(isa), {'a': 'int', 'b': 'str'})
1352 self.assertEqual(inspect.get_annotations(isa.MyClass), {'a': 'int', 'b': 'str'})
1353 self.assertEqual(inspect.get_annotations(isa.function), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1354 self.assertEqual(inspect.get_annotations(isa.function2), {'a': 'int', 'b': "'str'", 'c': 'MyClass', 'return': 'MyClass'})
1355 self.assertEqual(inspect.get_annotations(isa.function3), {'a': "'int'", 'b': "'str'", 'c': "'MyClass'"})
1356 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass), {})
1357 self.assertEqual(inspect.get_annotations(isa.unannotated_function), {})
1358
1359 self.assertEqual(inspect.get_annotations(isa, eval_str=True), {'a': int, 'b': str})
1360 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=True), {'a': int, 'b': str})
1361 self.assertEqual(inspect.get_annotations(isa.function, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1362 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=True), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1363 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=True), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1364 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=True), {})
1365 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=True), {})
1366
1367 self.assertEqual(inspect.get_annotations(isa, eval_str=False), {'a': 'int', 'b': 'str'})
1368 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=False), {'a': 'int', 'b': 'str'})
1369 self.assertEqual(inspect.get_annotations(isa.function, eval_str=False), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1370 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=False), {'a': 'int', 'b': "'str'", 'c': 'MyClass', 'return': 'MyClass'})
1371 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=False), {'a': "'int'", 'b': "'str'", 'c': "'MyClass'"})
1372 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=False), {})
1373 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=False), {})
1374
1375 isa2 = inspect_stringized_annotations_2
1376 self.assertEqual(inspect.get_annotations(isa2), {})
1377 self.assertEqual(inspect.get_annotations(isa2, eval_str=True), {})
1378 self.assertEqual(inspect.get_annotations(isa2, eval_str=False), {})
1379
1380 def times_three(fn):
1381 @functools.wraps(fn)
1382 def wrapper(a, b):
1383 return fn(a*3, b*3)
1384 return wrapper
1385
1386 wrapped = times_three(isa.function)
1387 self.assertEqual(wrapped(1, 'x'), isa.MyClass(3, 'xxx'))
1388 self.assertIsNot(wrapped.__globals__, isa.function.__globals__)
1389 self.assertEqual(inspect.get_annotations(wrapped), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1390 self.assertEqual(inspect.get_annotations(wrapped, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1391 self.assertEqual(inspect.get_annotations(wrapped, eval_str=False), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1392
1393 # test that local namespace lookups work
1394 self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations), {'x': 'mytype'})
1395 self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations, eval_str=True), {'x': int})
1396
1397
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001398class TestIsDataDescriptor(unittest.TestCase):
1399
1400 def test_custom_descriptors(self):
1401 class NonDataDescriptor:
1402 def __get__(self, value, type=None): pass
1403 class DataDescriptor0:
1404 def __set__(self, name, value): pass
1405 class DataDescriptor1:
1406 def __delete__(self, name): pass
1407 class DataDescriptor2:
1408 __set__ = None
1409 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1410 'class with only __get__ not a data descriptor')
1411 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1412 'class with __set__ is a data descriptor')
1413 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1414 'class with __delete__ is a data descriptor')
1415 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1416 'class with __set__ = None is a data descriptor')
1417
1418 def test_slot(self):
1419 class Slotted:
1420 __slots__ = 'foo',
1421 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1422 'a slot is a data descriptor')
1423
1424 def test_property(self):
1425 class Propertied:
1426 @property
1427 def a_property(self):
1428 pass
1429 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1430 'a property is a data descriptor')
1431
1432 def test_functions(self):
1433 class Test(object):
1434 def instance_method(self): pass
1435 @classmethod
1436 def class_method(cls): pass
1437 @staticmethod
1438 def static_method(): pass
1439 def function():
1440 pass
1441 a_lambda = lambda: None
1442 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1443 'a instance method is not a data descriptor')
1444 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1445 'a class method is not a data descriptor')
1446 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1447 'a static method is not a data descriptor')
1448 self.assertFalse(inspect.isdatadescriptor(function),
1449 'a function is not a data descriptor')
1450 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1451 'a lambda is not a data descriptor')
1452
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001453
Nick Coghlan2f92e542012-06-23 19:39:55 +10001454_global_ref = object()
1455class TestGetClosureVars(unittest.TestCase):
1456
1457 def test_name_resolution(self):
1458 # Basic test of the 4 different resolution mechanisms
1459 def f(nonlocal_ref):
1460 def g(local_ref):
1461 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1462 return g
1463 _arg = object()
1464 nonlocal_vars = {"nonlocal_ref": _arg}
1465 global_vars = {"_global_ref": _global_ref}
1466 builtin_vars = {"print": print}
1467 unbound_names = {"unbound_ref"}
1468 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1469 builtin_vars, unbound_names)
1470 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1471
1472 def test_generator_closure(self):
1473 def f(nonlocal_ref):
1474 def g(local_ref):
1475 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1476 yield
1477 return g
1478 _arg = object()
1479 nonlocal_vars = {"nonlocal_ref": _arg}
1480 global_vars = {"_global_ref": _global_ref}
1481 builtin_vars = {"print": print}
1482 unbound_names = {"unbound_ref"}
1483 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1484 builtin_vars, unbound_names)
1485 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1486
1487 def test_method_closure(self):
1488 class C:
1489 def f(self, nonlocal_ref):
1490 def g(local_ref):
1491 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1492 return g
1493 _arg = object()
1494 nonlocal_vars = {"nonlocal_ref": _arg}
1495 global_vars = {"_global_ref": _global_ref}
1496 builtin_vars = {"print": print}
1497 unbound_names = {"unbound_ref"}
1498 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1499 builtin_vars, unbound_names)
1500 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1501
1502 def test_nonlocal_vars(self):
1503 # More complex tests of nonlocal resolution
1504 def _nonlocal_vars(f):
1505 return inspect.getclosurevars(f).nonlocals
1506
1507 def make_adder(x):
1508 def add(y):
1509 return x + y
1510 return add
1511
1512 def curry(func, arg1):
1513 return lambda arg2: func(arg1, arg2)
1514
1515 def less_than(a, b):
1516 return a < b
1517
1518 # The infamous Y combinator.
1519 def Y(le):
1520 def g(f):
1521 return le(lambda x: f(f)(x))
1522 Y.g_ref = g
1523 return g(g)
1524
1525 def check_y_combinator(func):
1526 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1527
1528 inc = make_adder(1)
1529 add_two = make_adder(2)
1530 greater_than_five = curry(less_than, 5)
1531
1532 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1533 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1534 self.assertEqual(_nonlocal_vars(greater_than_five),
1535 {'arg1': 5, 'func': less_than})
1536 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1537 {'x': 3})
1538 Y(check_y_combinator)
1539
1540 def test_getclosurevars_empty(self):
1541 def foo(): pass
1542 _empty = inspect.ClosureVars({}, {}, {}, set())
1543 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1544 self.assertEqual(inspect.getclosurevars(foo), _empty)
1545
1546 def test_getclosurevars_error(self):
1547 class T: pass
1548 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1549 self.assertRaises(TypeError, inspect.getclosurevars, list)
1550 self.assertRaises(TypeError, inspect.getclosurevars, {})
1551
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001552 def _private_globals(self):
1553 code = """def f(): print(path)"""
1554 ns = {}
1555 exec(code, ns)
1556 return ns["f"], ns
1557
1558 def test_builtins_fallback(self):
1559 f, ns = self._private_globals()
1560 ns.pop("__builtins__", None)
1561 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1562 self.assertEqual(inspect.getclosurevars(f), expected)
1563
1564 def test_builtins_as_dict(self):
1565 f, ns = self._private_globals()
1566 ns["__builtins__"] = {"path":1}
1567 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1568 self.assertEqual(inspect.getclosurevars(f), expected)
1569
1570 def test_builtins_as_module(self):
1571 f, ns = self._private_globals()
1572 ns["__builtins__"] = os
1573 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1574 self.assertEqual(inspect.getclosurevars(f), expected)
1575
Nick Coghlan2f92e542012-06-23 19:39:55 +10001576
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001577class TestGetcallargsFunctions(unittest.TestCase):
1578
1579 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1580 locs = dict(locs or {}, func=func)
1581 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001582 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1583 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001584 self.assertEqual(r1, r2)
1585
1586 def assertEqualException(self, func, call_param_string, locs=None):
1587 locs = dict(locs or {}, func=func)
1588 try:
1589 eval('func(%s)' % call_param_string, None, locs)
1590 except Exception as e:
1591 ex1 = e
1592 else:
1593 self.fail('Exception not raised')
1594 try:
Pablo Galindoaee19f52019-05-16 21:08:15 +01001595 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1596 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001597 except Exception as e:
1598 ex2 = e
1599 else:
1600 self.fail('Exception not raised')
1601 self.assertIs(type(ex1), type(ex2))
1602 self.assertEqual(str(ex1), str(ex2))
1603 del ex1, ex2
1604
1605 def makeCallable(self, signature):
1606 """Create a function that returns its locals()"""
1607 code = "lambda %s: locals()"
1608 return eval(code % signature)
1609
1610 def test_plain(self):
1611 f = self.makeCallable('a, b=1')
1612 self.assertEqualCallArgs(f, '2')
1613 self.assertEqualCallArgs(f, '2, 3')
1614 self.assertEqualCallArgs(f, 'a=2')
1615 self.assertEqualCallArgs(f, 'b=3, a=2')
1616 self.assertEqualCallArgs(f, '2, b=3')
1617 # expand *iterable / **mapping
1618 self.assertEqualCallArgs(f, '*(2,)')
1619 self.assertEqualCallArgs(f, '*[2]')
1620 self.assertEqualCallArgs(f, '*(2, 3)')
1621 self.assertEqualCallArgs(f, '*[2, 3]')
1622 self.assertEqualCallArgs(f, '**{"a":2}')
1623 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1624 self.assertEqualCallArgs(f, '2, **{"b":3}')
1625 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1626 # expand UserList / UserDict
1627 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1628 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1629 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1630 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1631 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1632
1633 def test_varargs(self):
1634 f = self.makeCallable('a, b=1, *c')
1635 self.assertEqualCallArgs(f, '2')
1636 self.assertEqualCallArgs(f, '2, 3')
1637 self.assertEqualCallArgs(f, '2, 3, 4')
1638 self.assertEqualCallArgs(f, '*(2,3,4)')
1639 self.assertEqualCallArgs(f, '2, *[3,4]')
1640 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1641
1642 def test_varkw(self):
1643 f = self.makeCallable('a, b=1, **c')
1644 self.assertEqualCallArgs(f, 'a=2')
1645 self.assertEqualCallArgs(f, '2, b=3, c=4')
1646 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1647 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1648 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1649 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1650 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1651 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1652 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1653
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001654 def test_varkw_only(self):
1655 # issue11256:
1656 f = self.makeCallable('**c')
1657 self.assertEqualCallArgs(f, '')
1658 self.assertEqualCallArgs(f, 'a=1')
1659 self.assertEqualCallArgs(f, 'a=1, b=2')
1660 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1661 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1662 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1663
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001664 def test_keyword_only(self):
1665 f = self.makeCallable('a=3, *, c, d=2')
1666 self.assertEqualCallArgs(f, 'c=3')
1667 self.assertEqualCallArgs(f, 'c=3, a=3')
1668 self.assertEqualCallArgs(f, 'a=2, c=4')
1669 self.assertEqualCallArgs(f, '4, c=4')
1670 self.assertEqualException(f, '')
1671 self.assertEqualException(f, '3')
1672 self.assertEqualException(f, 'a=3')
1673 self.assertEqualException(f, 'd=4')
1674
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001675 f = self.makeCallable('*, c, d=2')
1676 self.assertEqualCallArgs(f, 'c=3')
1677 self.assertEqualCallArgs(f, 'c=3, d=4')
1678 self.assertEqualCallArgs(f, 'd=4, c=3')
1679
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001680 def test_multiple_features(self):
1681 f = self.makeCallable('a, b=2, *f, **g')
1682 self.assertEqualCallArgs(f, '2, 3, 7')
1683 self.assertEqualCallArgs(f, '2, 3, x=8')
1684 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1685 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1686 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1687 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1688 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1689 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1690 '(4,[5,6])]), **collections.UserDict('
1691 'y=9, z=10)')
1692
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001693 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1694 self.assertEqualCallArgs(f, '2, 3, x=8')
1695 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1696 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1697 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1698 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1699 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1700 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1701 '(4,[5,6])]), q=0, **collections.UserDict('
1702 'y=9, z=10)')
1703
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001704 def test_errors(self):
1705 f0 = self.makeCallable('')
1706 f1 = self.makeCallable('a, b')
1707 f2 = self.makeCallable('a, b=1')
1708 # f0 takes no arguments
1709 self.assertEqualException(f0, '1')
1710 self.assertEqualException(f0, 'x=1')
1711 self.assertEqualException(f0, '1,x=1')
1712 # f1 takes exactly 2 arguments
1713 self.assertEqualException(f1, '')
1714 self.assertEqualException(f1, '1')
1715 self.assertEqualException(f1, 'a=2')
1716 self.assertEqualException(f1, 'b=3')
1717 # f2 takes at least 1 argument
1718 self.assertEqualException(f2, '')
1719 self.assertEqualException(f2, 'b=3')
1720 for f in f1, f2:
1721 # f1/f2 takes exactly/at most 2 arguments
1722 self.assertEqualException(f, '2, 3, 4')
1723 self.assertEqualException(f, '1, 2, 3, a=1')
1724 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001725 # XXX: success of this one depends on dict order
1726 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001727 # f got an unexpected keyword argument
1728 self.assertEqualException(f, 'c=2')
1729 self.assertEqualException(f, '2, c=3')
1730 self.assertEqualException(f, '2, 3, c=4')
1731 self.assertEqualException(f, '2, c=4, b=3')
1732 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1733 # f got multiple values for keyword argument
1734 self.assertEqualException(f, '1, a=2')
1735 self.assertEqualException(f, '1, **{"a":2}')
1736 self.assertEqualException(f, '1, 2, b=3')
1737 # XXX: Python inconsistency
1738 # - for functions and bound methods: unexpected keyword 'c'
1739 # - for unbound methods: multiple values for keyword 'a'
1740 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001741 # issue11256:
1742 f3 = self.makeCallable('**c')
1743 self.assertEqualException(f3, '1, 2')
1744 self.assertEqualException(f3, '1, 2, a=1, b=2')
1745 f4 = self.makeCallable('*, a, b=0')
1746 self.assertEqualException(f3, '1, 2')
1747 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001748
Yury Selivanov875df202014-03-27 18:23:03 -04001749 # issue #20816: getcallargs() fails to iterate over non-existent
1750 # kwonlydefaults and raises a wrong TypeError
1751 def f5(*, a): pass
1752 with self.assertRaisesRegex(TypeError,
1753 'missing 1 required keyword-only'):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001754 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001755
1756
Yury Selivanovdccfa132014-03-27 18:42:52 -04001757 # issue20817:
1758 def f6(a, b, c):
1759 pass
1760 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001761 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001762
Dong-hee Naa9cab432018-05-30 00:04:08 +09001763 # bpo-33197
1764 with self.assertRaisesRegex(ValueError,
1765 'variadic keyword parameters cannot'
1766 ' have default values'):
1767 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1768 default=42)
1769 with self.assertRaisesRegex(ValueError,
1770 "value 5 is not a valid Parameter.kind"):
1771 inspect.Parameter("bar", kind=5, default=42)
1772
1773 with self.assertRaisesRegex(TypeError,
1774 'name must be a str, not a int'):
1775 inspect.Parameter(123, kind=4)
1776
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001777class TestGetcallargsMethods(TestGetcallargsFunctions):
1778
1779 def setUp(self):
1780 class Foo(object):
1781 pass
1782 self.cls = Foo
1783 self.inst = Foo()
1784
1785 def makeCallable(self, signature):
1786 assert 'self' not in signature
1787 mk = super(TestGetcallargsMethods, self).makeCallable
1788 self.cls.method = mk('self, ' + signature)
1789 return self.inst.method
1790
1791class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1792
1793 def makeCallable(self, signature):
1794 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1795 return self.cls.method
1796
1797 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1798 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1799 *self._getAssertEqualParams(func, call_params_string, locs))
1800
1801 def assertEqualException(self, func, call_params_string, locs=None):
1802 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1803 *self._getAssertEqualParams(func, call_params_string, locs))
1804
1805 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1806 assert 'inst' not in call_params_string
1807 locs = dict(locs or {}, inst=self.inst)
1808 return (func, 'inst,' + call_params_string, locs)
1809
Michael Foord95fc51d2010-11-20 15:07:30 +00001810
1811class TestGetattrStatic(unittest.TestCase):
1812
1813 def test_basic(self):
1814 class Thing(object):
1815 x = object()
1816
1817 thing = Thing()
1818 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1819 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1820 with self.assertRaises(AttributeError):
1821 inspect.getattr_static(thing, 'y')
1822
1823 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1824
1825 def test_inherited(self):
1826 class Thing(object):
1827 x = object()
1828 class OtherThing(Thing):
1829 pass
1830
1831 something = OtherThing()
1832 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1833
1834 def test_instance_attr(self):
1835 class Thing(object):
1836 x = 2
1837 def __init__(self, x):
1838 self.x = x
1839 thing = Thing(3)
1840 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1841 del thing.x
1842 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1843
1844 def test_property(self):
1845 class Thing(object):
1846 @property
1847 def x(self):
1848 raise AttributeError("I'm pretending not to exist")
1849 thing = Thing()
1850 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1851
Ezio Melotti75cbd732011-04-28 00:59:29 +03001852 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001853 class descriptor(object):
1854 def __get__(*_):
1855 raise AttributeError("I'm pretending not to exist")
1856 desc = descriptor()
1857 class Thing(object):
1858 x = desc
1859 thing = Thing()
1860 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1861
1862 def test_classAttribute(self):
1863 class Thing(object):
1864 x = object()
1865
1866 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1867
Ethan Furmane03ea372013-09-25 07:14:41 -07001868 def test_classVirtualAttribute(self):
1869 class Thing(object):
1870 @types.DynamicClassAttribute
1871 def x(self):
1872 return self._x
1873 _x = object()
1874
1875 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1876
Michael Foord95fc51d2010-11-20 15:07:30 +00001877 def test_inherited_classattribute(self):
1878 class Thing(object):
1879 x = object()
1880 class OtherThing(Thing):
1881 pass
1882
1883 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1884
1885 def test_slots(self):
1886 class Thing(object):
1887 y = 'bar'
1888 __slots__ = ['x']
1889 def __init__(self):
1890 self.x = 'foo'
1891 thing = Thing()
1892 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1893 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1894
1895 del thing.x
1896 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1897
1898 def test_metaclass(self):
1899 class meta(type):
1900 attr = 'foo'
1901 class Thing(object, metaclass=meta):
1902 pass
1903 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1904
1905 class sub(meta):
1906 pass
1907 class OtherThing(object, metaclass=sub):
1908 x = 3
1909 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1910
1911 class OtherOtherThing(OtherThing):
1912 pass
1913 # this test is odd, but it was added as it exposed a bug
1914 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1915
1916 def test_no_dict_no_slots(self):
1917 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1918 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1919
1920 def test_no_dict_no_slots_instance_member(self):
1921 # returns descriptor
Inada Naokifb786922021-04-06 11:18:41 +09001922 with open(__file__, encoding='utf-8') as handle:
Michael Foord95fc51d2010-11-20 15:07:30 +00001923 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1924
1925 def test_inherited_slots(self):
1926 # returns descriptor
1927 class Thing(object):
1928 __slots__ = ['x']
1929 def __init__(self):
1930 self.x = 'foo'
1931
1932 class OtherThing(Thing):
1933 pass
1934 # it would be nice if this worked...
1935 # we get the descriptor instead of the instance attribute
1936 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1937
1938 def test_descriptor(self):
1939 class descriptor(object):
1940 def __get__(self, instance, owner):
1941 return 3
1942 class Foo(object):
1943 d = descriptor()
1944
1945 foo = Foo()
1946
1947 # for a non data descriptor we return the instance attribute
1948 foo.__dict__['d'] = 1
1949 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1950
Mike53f7a7c2017-12-14 14:04:53 +03001951 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001952 # descriptor
1953 descriptor.__set__ = lambda s, i, v: None
1954 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1955
1956
1957 def test_metaclass_with_descriptor(self):
1958 class descriptor(object):
1959 def __get__(self, instance, owner):
1960 return 3
1961 class meta(type):
1962 d = descriptor()
1963 class Thing(object, metaclass=meta):
1964 pass
1965 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1966
1967
Michael Foordcc7ebb82010-11-20 16:20:16 +00001968 def test_class_as_property(self):
1969 class Base(object):
1970 foo = 3
1971
1972 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001973 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001974 @property
1975 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001976 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001977 return object
1978
Michael Foord35184ed2010-11-20 16:58:30 +00001979 instance = Something()
1980 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1981 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001982 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1983
Michael Foorde5162652010-11-20 16:40:44 +00001984 def test_mro_as_property(self):
1985 class Meta(type):
1986 @property
1987 def __mro__(self):
1988 return (object,)
1989
1990 class Base(object):
1991 foo = 3
1992
1993 class Something(Base, metaclass=Meta):
1994 pass
1995
1996 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1997 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1998
Michael Foorddcebe0f2011-03-15 19:20:44 -04001999 def test_dict_as_property(self):
2000 test = self
2001 test.called = False
2002
2003 class Foo(dict):
2004 a = 3
2005 @property
2006 def __dict__(self):
2007 test.called = True
2008 return {}
2009
2010 foo = Foo()
2011 foo.a = 4
2012 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
2013 self.assertFalse(test.called)
2014
2015 def test_custom_object_dict(self):
2016 test = self
2017 test.called = False
2018
2019 class Custom(dict):
2020 def get(self, key, default=None):
2021 test.called = True
2022 super().get(key, default)
2023
2024 class Foo(object):
2025 a = 3
2026 foo = Foo()
2027 foo.__dict__ = Custom()
2028 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
2029 self.assertFalse(test.called)
2030
2031 def test_metaclass_dict_as_property(self):
2032 class Meta(type):
2033 @property
2034 def __dict__(self):
2035 self.executed = True
2036
2037 class Thing(metaclass=Meta):
2038 executed = False
2039
2040 def __init__(self):
2041 self.spam = 42
2042
2043 instance = Thing()
2044 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
2045 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00002046
Michael Foorda51623b2011-12-18 22:01:40 +00002047 def test_module(self):
2048 sentinel = object()
2049 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
2050 sentinel)
2051
Michael Foord3ba95f82011-12-22 01:13:37 +00002052 def test_metaclass_with_metaclass_with_dict_as_property(self):
2053 class MetaMeta(type):
2054 @property
2055 def __dict__(self):
2056 self.executed = True
2057 return dict(spam=42)
2058
2059 class Meta(type, metaclass=MetaMeta):
2060 executed = False
2061
2062 class Thing(metaclass=Meta):
2063 pass
2064
2065 with self.assertRaises(AttributeError):
2066 inspect.getattr_static(Thing, "spam")
2067 self.assertFalse(Thing.executed)
2068
Nick Coghlane0f04652010-11-21 03:44:04 +00002069class TestGetGeneratorState(unittest.TestCase):
2070
2071 def setUp(self):
2072 def number_generator():
2073 for number in range(5):
2074 yield number
2075 self.generator = number_generator()
2076
2077 def _generatorstate(self):
2078 return inspect.getgeneratorstate(self.generator)
2079
2080 def test_created(self):
2081 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
2082
2083 def test_suspended(self):
2084 next(self.generator)
2085 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
2086
2087 def test_closed_after_exhaustion(self):
2088 for i in self.generator:
2089 pass
2090 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
2091
2092 def test_closed_after_immediate_exception(self):
2093 with self.assertRaises(RuntimeError):
2094 self.generator.throw(RuntimeError)
2095 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
2096
2097 def test_running(self):
2098 # As mentioned on issue #10220, checking for the RUNNING state only
2099 # makes sense inside the generator itself.
2100 # The following generator checks for this by using the closure's
2101 # reference to self and the generator state checking helper method
2102 def running_check_generator():
2103 for number in range(5):
2104 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
2105 yield number
2106 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
2107 self.generator = running_check_generator()
2108 # Running up to the first yield
2109 next(self.generator)
2110 # Running after the first yield
2111 next(self.generator)
2112
Nick Coghlan7921b9f2010-11-30 06:36:04 +00002113 def test_easy_debugging(self):
2114 # repr() and str() of a generator state should contain the state name
2115 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
2116 for name in names:
2117 state = getattr(inspect, name)
2118 self.assertIn(name, repr(state))
2119 self.assertIn(name, str(state))
2120
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10002121 def test_getgeneratorlocals(self):
2122 def each(lst, a=None):
2123 b=(1, 2, 3)
2124 for v in lst:
2125 if v == 3:
2126 c = 12
2127 yield v
2128
2129 numbers = each([1, 2, 3])
2130 self.assertEqual(inspect.getgeneratorlocals(numbers),
2131 {'a': None, 'lst': [1, 2, 3]})
2132 next(numbers)
2133 self.assertEqual(inspect.getgeneratorlocals(numbers),
2134 {'a': None, 'lst': [1, 2, 3], 'v': 1,
2135 'b': (1, 2, 3)})
2136 next(numbers)
2137 self.assertEqual(inspect.getgeneratorlocals(numbers),
2138 {'a': None, 'lst': [1, 2, 3], 'v': 2,
2139 'b': (1, 2, 3)})
2140 next(numbers)
2141 self.assertEqual(inspect.getgeneratorlocals(numbers),
2142 {'a': None, 'lst': [1, 2, 3], 'v': 3,
2143 'b': (1, 2, 3), 'c': 12})
2144 try:
2145 next(numbers)
2146 except StopIteration:
2147 pass
2148 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
2149
2150 def test_getgeneratorlocals_empty(self):
2151 def yield_one():
2152 yield 1
2153 one = yield_one()
2154 self.assertEqual(inspect.getgeneratorlocals(one), {})
2155 try:
2156 next(one)
2157 except StopIteration:
2158 pass
2159 self.assertEqual(inspect.getgeneratorlocals(one), {})
2160
2161 def test_getgeneratorlocals_error(self):
2162 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
2163 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
2164 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
2165 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
2166
Nick Coghlane0f04652010-11-21 03:44:04 +00002167
Yury Selivanov5376ba92015-06-22 12:19:30 -04002168class TestGetCoroutineState(unittest.TestCase):
2169
2170 def setUp(self):
2171 @types.coroutine
2172 def number_coroutine():
2173 for number in range(5):
2174 yield number
2175 async def coroutine():
2176 await number_coroutine()
2177 self.coroutine = coroutine()
2178
2179 def tearDown(self):
2180 self.coroutine.close()
2181
2182 def _coroutinestate(self):
2183 return inspect.getcoroutinestate(self.coroutine)
2184
2185 def test_created(self):
2186 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
2187
2188 def test_suspended(self):
2189 self.coroutine.send(None)
2190 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
2191
2192 def test_closed_after_exhaustion(self):
2193 while True:
2194 try:
2195 self.coroutine.send(None)
2196 except StopIteration:
2197 break
2198
2199 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2200
2201 def test_closed_after_immediate_exception(self):
2202 with self.assertRaises(RuntimeError):
2203 self.coroutine.throw(RuntimeError)
2204 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2205
2206 def test_easy_debugging(self):
2207 # repr() and str() of a coroutine state should contain the state name
2208 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2209 for name in names:
2210 state = getattr(inspect, name)
2211 self.assertIn(name, repr(state))
2212 self.assertIn(name, str(state))
2213
2214 def test_getcoroutinelocals(self):
2215 @types.coroutine
2216 def gencoro():
2217 yield
2218
2219 gencoro = gencoro()
2220 async def func(a=None):
2221 b = 'spam'
2222 await gencoro
2223
2224 coro = func()
2225 self.assertEqual(inspect.getcoroutinelocals(coro),
2226 {'a': None, 'gencoro': gencoro})
2227 coro.send(None)
2228 self.assertEqual(inspect.getcoroutinelocals(coro),
2229 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2230
2231
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002232class MySignature(inspect.Signature):
2233 # Top-level to make it picklable;
2234 # used in test_signature_object_pickle
2235 pass
2236
2237class MyParameter(inspect.Parameter):
2238 # Top-level to make it picklable;
2239 # used in test_signature_object_pickle
2240 pass
2241
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002242
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002243
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002244class TestSignatureObject(unittest.TestCase):
2245 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002246 def signature(func, **kw):
2247 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002248 return (tuple((param.name,
2249 (... if param.default is param.empty else param.default),
2250 (... if param.annotation is param.empty
2251 else param.annotation),
2252 str(param.kind).lower())
2253 for param in sig.parameters.values()),
2254 (... if sig.return_annotation is sig.empty
2255 else sig.return_annotation))
2256
2257 def test_signature_object(self):
2258 S = inspect.Signature
2259 P = inspect.Parameter
2260
2261 self.assertEqual(str(S()), '()')
Jens Reidel611836a2020-03-18 03:22:46 +01002262 self.assertEqual(repr(S().parameters), 'mappingproxy(OrderedDict())')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002263
Yury Selivanov07a9e452014-01-29 10:58:16 -05002264 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002265 pass
2266 sig = inspect.signature(test)
2267 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002268 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002269 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002270 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002271 args = sig.parameters['args']
2272 ko = sig.parameters['ko']
2273 kwargs = sig.parameters['kwargs']
2274
2275 S((po, pk, args, ko, kwargs))
2276
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002277 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002278 S((pk, po, args, ko, kwargs))
2279
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002280 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002281 S((po, args, pk, ko, kwargs))
2282
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002283 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002284 S((args, po, pk, ko, kwargs))
2285
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002286 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002287 S((po, pk, args, kwargs, ko))
2288
2289 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002290 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002291 S((po, pk, args, kwargs2, ko))
2292
Yury Selivanov07a9e452014-01-29 10:58:16 -05002293 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2294 S((pod, po))
2295
2296 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2297 S((po, pkd, pk))
2298
2299 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2300 S((pkd, pk))
2301
Yury Selivanov374375d2014-03-27 12:41:53 -04002302 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002303 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002304
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002305 def test_signature_object_pickle(self):
2306 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2307 foo_partial = functools.partial(foo, a=1)
2308
2309 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002310
2311 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2312 with self.subTest(pickle_ver=ver, subclass=False):
2313 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2314 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002315
2316 # Test that basic sub-classing works
2317 sig = inspect.signature(foo)
2318 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2319 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2320 mysig = MySignature().replace(parameters=myparams.values(),
2321 return_annotation=sig.return_annotation)
2322 self.assertTrue(isinstance(mysig, MySignature))
2323 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2324
2325 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2326 with self.subTest(pickle_ver=ver, subclass=True):
2327 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2328 self.assertEqual(mysig, sig_pickled)
2329 self.assertTrue(isinstance(sig_pickled, MySignature))
2330 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2331 MyParameter))
2332
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002333 def test_signature_immutability(self):
2334 def test(a):
2335 pass
2336 sig = inspect.signature(test)
2337
2338 with self.assertRaises(AttributeError):
2339 sig.foo = 'bar'
2340
2341 with self.assertRaises(TypeError):
2342 sig.parameters['a'] = None
2343
2344 def test_signature_on_noarg(self):
2345 def test():
2346 pass
2347 self.assertEqual(self.signature(test), ((), ...))
2348
2349 def test_signature_on_wargs(self):
2350 def test(a, b:'foo') -> 123:
2351 pass
2352 self.assertEqual(self.signature(test),
2353 ((('a', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002354 ('b', ..., 'foo', "positional_or_keyword")),
2355 123))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002356
2357 def test_signature_on_wkwonly(self):
2358 def test(*, a:float, b:str) -> int:
2359 pass
2360 self.assertEqual(self.signature(test),
2361 ((('a', ..., float, "keyword_only"),
2362 ('b', ..., str, "keyword_only")),
2363 int))
2364
2365 def test_signature_on_complex_args(self):
2366 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2367 pass
2368 self.assertEqual(self.signature(test),
2369 ((('a', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002370 ('b', 10, 'foo', "positional_or_keyword"),
2371 ('args', ..., 'bar', "var_positional"),
2372 ('spam', ..., 'baz', "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002373 ('ham', 123, ..., "keyword_only"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002374 ('kwargs', ..., int, "var_keyword")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002375 ...))
2376
Dong-hee Na378d7062017-05-18 04:00:51 +09002377 def test_signature_without_self(self):
2378 def test_args_only(*args): # NOQA
2379 pass
2380
2381 def test_args_kwargs_only(*args, **kwargs): # NOQA
2382 pass
2383
2384 class A:
2385 @classmethod
2386 def test_classmethod(*args): # NOQA
2387 pass
2388
2389 @staticmethod
2390 def test_staticmethod(*args): # NOQA
2391 pass
2392
2393 f1 = functools.partialmethod((test_classmethod), 1)
2394 f2 = functools.partialmethod((test_args_only), 1)
2395 f3 = functools.partialmethod((test_staticmethod), 1)
2396 f4 = functools.partialmethod((test_args_kwargs_only),1)
2397
2398 self.assertEqual(self.signature(test_args_only),
2399 ((('args', ..., ..., 'var_positional'),), ...))
2400 self.assertEqual(self.signature(test_args_kwargs_only),
2401 ((('args', ..., ..., 'var_positional'),
2402 ('kwargs', ..., ..., 'var_keyword')), ...))
2403 self.assertEqual(self.signature(A.f1),
2404 ((('args', ..., ..., 'var_positional'),), ...))
2405 self.assertEqual(self.signature(A.f2),
2406 ((('args', ..., ..., 'var_positional'),), ...))
2407 self.assertEqual(self.signature(A.f3),
2408 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002409 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002410 ((('args', ..., ..., 'var_positional'),
2411 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002412 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002413 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2414 "Signature information for builtins requires docstrings")
2415 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002416 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002417
Larry Hastings5c661892014-01-24 06:17:25 -08002418 def test_unbound_method(o):
2419 """Use this to test unbound methods (things that should have a self)"""
2420 signature = inspect.signature(o)
2421 self.assertTrue(isinstance(signature, inspect.Signature))
2422 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2423 return signature
2424
2425 def test_callable(o):
2426 """Use this to test bound methods or normal callables (things that don't expect self)"""
2427 signature = inspect.signature(o)
2428 self.assertTrue(isinstance(signature, inspect.Signature))
2429 if signature.parameters:
2430 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2431 return signature
2432
2433 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002434 def p(name): return signature.parameters[name].default
2435 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002436 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002437 self.assertEqual(p('d'), 3.14)
2438 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002439 self.assertEqual(p('n'), None)
2440 self.assertEqual(p('t'), True)
2441 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002442 self.assertEqual(p('local'), 3)
2443 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002444 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002445
Larry Hastings5c661892014-01-24 06:17:25 -08002446 test_callable(object)
2447
2448 # normal method
2449 # (PyMethodDescr_Type, "method_descriptor")
2450 test_unbound_method(_pickle.Pickler.dump)
2451 d = _pickle.Pickler(io.StringIO())
2452 test_callable(d.dump)
2453
2454 # static method
Serhiy Storchaka279f4462019-09-14 12:24:05 +03002455 test_callable(bytes.maketrans)
2456 test_callable(b'abc'.maketrans)
Larry Hastings5c661892014-01-24 06:17:25 -08002457
2458 # class method
2459 test_callable(dict.fromkeys)
2460 test_callable({}.fromkeys)
2461
2462 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2463 test_unbound_method(type.__call__)
2464 test_unbound_method(int.__add__)
2465 test_callable((3).__add__)
2466
2467 # _PyMethodWrapper_Type
2468 # support for 'method-wrapper'
2469 test_callable(min.__call__)
2470
Larry Hastings2623c8c2014-02-08 22:15:29 -08002471 # This doesn't work now.
2472 # (We don't have a valid signature for "type" in 3.4)
2473 with self.assertRaisesRegex(ValueError, "no signature found"):
2474 class ThisWorksNow:
2475 __call__ = type
2476 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002477
Yury Selivanov056e2652014-03-02 12:25:27 -05002478 # Regression test for issue #20786
2479 test_unbound_method(dict.__delitem__)
2480 test_unbound_method(property.__delete__)
2481
Zachary Ware8ef887c2015-04-13 18:22:35 -05002482 # Regression test for issue #20586
2483 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2484
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002485 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002486 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2487 "Signature information for builtins requires docstrings")
2488 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002489 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002490 func = _testcapi.docstring_with_signature_with_defaults
2491
2492 def decorator(func):
2493 @functools.wraps(func)
2494 def wrapper(*args, **kwargs) -> int:
2495 return func(*args, **kwargs)
2496 return wrapper
2497
2498 decorated_func = decorator(func)
2499
2500 self.assertEqual(inspect.signature(func),
2501 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002502
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002503 def wrapper_like(*args, **kwargs) -> int: pass
2504 self.assertEqual(inspect.signature(decorated_func,
2505 follow_wrapped=False),
2506 inspect.signature(wrapper_like))
2507
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002508 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002509 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002510 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002511 with self.assertRaisesRegex(ValueError,
2512 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002513 inspect.signature(_testcapi.docstring_no_signature)
2514
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002515 with self.assertRaisesRegex(ValueError,
2516 'no signature found for builtin'):
2517 inspect.signature(str)
2518
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002519 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002520 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002521 inspect.signature(42)
2522
Yury Selivanov63da7c72014-01-31 14:48:37 -05002523 def test_signature_from_functionlike_object(self):
2524 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2525 pass
2526
2527 class funclike:
2528 # Has to be callable, and have correct
2529 # __code__, __annotations__, __defaults__, __name__,
2530 # and __kwdefaults__ attributes
2531
2532 def __init__(self, func):
2533 self.__name__ = func.__name__
2534 self.__code__ = func.__code__
2535 self.__annotations__ = func.__annotations__
2536 self.__defaults__ = func.__defaults__
2537 self.__kwdefaults__ = func.__kwdefaults__
2538 self.func = func
2539
2540 def __call__(self, *args, **kwargs):
2541 return self.func(*args, **kwargs)
2542
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002543 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002544
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002545 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002546 self.assertEqual(sig_funclike, sig_func)
2547
2548 sig_funclike = inspect.signature(funclike(func))
2549 self.assertEqual(sig_funclike, sig_func)
2550
2551 # If object is not a duck type of function, then
2552 # signature will try to get a signature for its '__call__'
2553 # method
2554 fl = funclike(func)
2555 del fl.__defaults__
2556 self.assertEqual(self.signature(fl),
2557 ((('args', ..., ..., "var_positional"),
2558 ('kwargs', ..., ..., "var_keyword")),
2559 ...))
2560
Yury Selivanova773de02014-02-21 18:30:53 -05002561 # Test with cython-like builtins:
2562 _orig_isdesc = inspect.ismethoddescriptor
2563 def _isdesc(obj):
2564 if hasattr(obj, '_builtinmock'):
2565 return True
2566 return _orig_isdesc(obj)
2567
2568 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2569 builtin_func = funclike(func)
2570 # Make sure that our mock setup is working
2571 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2572 builtin_func._builtinmock = True
2573 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2574 self.assertEqual(inspect.signature(builtin_func), sig_func)
2575
Yury Selivanov63da7c72014-01-31 14:48:37 -05002576 def test_signature_functionlike_class(self):
2577 # We only want to duck type function-like objects,
2578 # not classes.
2579
2580 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2581 pass
2582
2583 class funclike:
2584 def __init__(self, marker):
2585 pass
2586
2587 __name__ = func.__name__
2588 __code__ = func.__code__
2589 __annotations__ = func.__annotations__
2590 __defaults__ = func.__defaults__
2591 __kwdefaults__ = func.__kwdefaults__
2592
Yury Selivanov63da7c72014-01-31 14:48:37 -05002593 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2594
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002595 def test_signature_on_method(self):
2596 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002597 def __init__(*args):
2598 pass
2599 def m1(self, arg1, arg2=1) -> int:
2600 pass
2601 def m2(*args):
2602 pass
2603 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002604 pass
2605
Yury Selivanov62560fb2014-01-28 12:26:24 -05002606 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002607 ((('arg1', ..., ..., "positional_or_keyword"),
2608 ('arg2', 1, ..., "positional_or_keyword")),
2609 int))
2610
Yury Selivanov62560fb2014-01-28 12:26:24 -05002611 self.assertEqual(self.signature(Test().m2),
2612 ((('args', ..., ..., "var_positional"),),
2613 ...))
2614
2615 self.assertEqual(self.signature(Test),
2616 ((('args', ..., ..., "var_positional"),),
2617 ...))
2618
2619 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2620 self.signature(Test())
2621
Yury Selivanov46c759d2015-05-27 21:56:53 -04002622 def test_signature_wrapped_bound_method(self):
2623 # Issue 24298
2624 class Test:
2625 def m1(self, arg1, arg2=1) -> int:
2626 pass
2627 @functools.wraps(Test().m1)
2628 def m1d(*args, **kwargs):
2629 pass
2630 self.assertEqual(self.signature(m1d),
2631 ((('arg1', ..., ..., "positional_or_keyword"),
2632 ('arg2', 1, ..., "positional_or_keyword")),
2633 int))
2634
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002635 def test_signature_on_classmethod(self):
2636 class Test:
2637 @classmethod
2638 def foo(cls, arg1, *, arg2=1):
2639 pass
2640
2641 meth = Test().foo
2642 self.assertEqual(self.signature(meth),
2643 ((('arg1', ..., ..., "positional_or_keyword"),
2644 ('arg2', 1, ..., "keyword_only")),
2645 ...))
2646
2647 meth = Test.foo
2648 self.assertEqual(self.signature(meth),
2649 ((('arg1', ..., ..., "positional_or_keyword"),
2650 ('arg2', 1, ..., "keyword_only")),
2651 ...))
2652
2653 def test_signature_on_staticmethod(self):
2654 class Test:
2655 @staticmethod
2656 def foo(cls, *, arg):
2657 pass
2658
2659 meth = Test().foo
2660 self.assertEqual(self.signature(meth),
2661 ((('cls', ..., ..., "positional_or_keyword"),
2662 ('arg', ..., ..., "keyword_only")),
2663 ...))
2664
2665 meth = Test.foo
2666 self.assertEqual(self.signature(meth),
2667 ((('cls', ..., ..., "positional_or_keyword"),
2668 ('arg', ..., ..., "keyword_only")),
2669 ...))
2670
2671 def test_signature_on_partial(self):
2672 from functools import partial
2673
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002674 Parameter = inspect.Parameter
2675
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002676 def test():
2677 pass
2678
2679 self.assertEqual(self.signature(partial(test)), ((), ...))
2680
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002681 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002682 inspect.signature(partial(test, 1))
2683
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002684 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002685 inspect.signature(partial(test, a=1))
2686
2687 def test(a, b, *, c, d):
2688 pass
2689
2690 self.assertEqual(self.signature(partial(test)),
2691 ((('a', ..., ..., "positional_or_keyword"),
2692 ('b', ..., ..., "positional_or_keyword"),
2693 ('c', ..., ..., "keyword_only"),
2694 ('d', ..., ..., "keyword_only")),
2695 ...))
2696
2697 self.assertEqual(self.signature(partial(test, 1)),
2698 ((('b', ..., ..., "positional_or_keyword"),
2699 ('c', ..., ..., "keyword_only"),
2700 ('d', ..., ..., "keyword_only")),
2701 ...))
2702
2703 self.assertEqual(self.signature(partial(test, 1, c=2)),
2704 ((('b', ..., ..., "positional_or_keyword"),
2705 ('c', 2, ..., "keyword_only"),
2706 ('d', ..., ..., "keyword_only")),
2707 ...))
2708
2709 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2710 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002711 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002712 ('c', 2, ..., "keyword_only"),
2713 ('d', ..., ..., "keyword_only")),
2714 ...))
2715
2716 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002717 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002718 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002719 ('d', ..., ..., "keyword_only")),
2720 ...))
2721
2722 self.assertEqual(self.signature(partial(test, a=1)),
2723 ((('a', 1, ..., "keyword_only"),
2724 ('b', ..., ..., "keyword_only"),
2725 ('c', ..., ..., "keyword_only"),
2726 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002727 ...))
2728
2729 def test(a, *args, b, **kwargs):
2730 pass
2731
2732 self.assertEqual(self.signature(partial(test, 1)),
2733 ((('args', ..., ..., "var_positional"),
2734 ('b', ..., ..., "keyword_only"),
2735 ('kwargs', ..., ..., "var_keyword")),
2736 ...))
2737
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002738 self.assertEqual(self.signature(partial(test, a=1)),
2739 ((('a', 1, ..., "keyword_only"),
2740 ('b', ..., ..., "keyword_only"),
2741 ('kwargs', ..., ..., "var_keyword")),
2742 ...))
2743
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002744 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2745 ((('args', ..., ..., "var_positional"),
2746 ('b', ..., ..., "keyword_only"),
2747 ('kwargs', ..., ..., "var_keyword")),
2748 ...))
2749
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002750 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2751 ((('args', ..., ..., "var_positional"),
2752 ('b', ..., ..., "keyword_only"),
2753 ('kwargs', ..., ..., "var_keyword")),
2754 ...))
2755
2756 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2757 ((('args', ..., ..., "var_positional"),
2758 ('b', 0, ..., "keyword_only"),
2759 ('kwargs', ..., ..., "var_keyword")),
2760 ...))
2761
2762 self.assertEqual(self.signature(partial(test, b=0)),
2763 ((('a', ..., ..., "positional_or_keyword"),
2764 ('args', ..., ..., "var_positional"),
2765 ('b', 0, ..., "keyword_only"),
2766 ('kwargs', ..., ..., "var_keyword")),
2767 ...))
2768
2769 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2770 ((('a', ..., ..., "positional_or_keyword"),
2771 ('args', ..., ..., "var_positional"),
2772 ('b', 0, ..., "keyword_only"),
2773 ('kwargs', ..., ..., "var_keyword")),
2774 ...))
2775
2776 def test(a, b, c:int) -> 42:
2777 pass
2778
2779 sig = test.__signature__ = inspect.signature(test)
2780
2781 self.assertEqual(self.signature(partial(partial(test, 1))),
2782 ((('b', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002783 ('c', ..., int, "positional_or_keyword")),
2784 42))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002785
2786 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002787 ((('c', ..., int, "positional_or_keyword"),),
2788 42))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002789
2790 psig = inspect.signature(partial(partial(test, 1), 2))
2791
2792 def foo(a):
2793 return a
2794 _foo = partial(partial(foo, a=10), a=20)
2795 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002796 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002797 ...))
2798 # check that we don't have any side-effects in signature(),
2799 # and the partial object is still functioning
2800 self.assertEqual(_foo(), 20)
2801
2802 def foo(a, b, c):
2803 return a, b, c
2804 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002805
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002806 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002807 ((('b', 30, ..., "keyword_only"),
2808 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002809 ...))
2810 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002811
2812 def foo(a, b, c, *, d):
2813 return a, b, c, d
2814 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2815 self.assertEqual(self.signature(_foo),
2816 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002817 ('b', 10, ..., "keyword_only"),
2818 ('c', 20, ..., "keyword_only"),
2819 ('d', 30, ..., "keyword_only"),
2820 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002821 ...))
2822 ba = inspect.signature(_foo).bind(a=200, b=11)
2823 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2824
2825 def foo(a=1, b=2, c=3):
2826 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002827 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2828
2829 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002830 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002831
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002832 ba = inspect.signature(_foo).bind(11, 12)
2833 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002834
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002835 ba = inspect.signature(_foo).bind(11, b=12)
2836 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002837
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002838 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002839 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2840
2841 _foo = partial(_foo, b=10, c=20)
2842 ba = inspect.signature(_foo).bind(12)
2843 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2844
2845
2846 def foo(a, b, c, d, **kwargs):
2847 pass
2848 sig = inspect.signature(foo)
2849 params = sig.parameters.copy()
2850 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2851 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2852 foo.__signature__ = inspect.Signature(params.values())
2853 sig = inspect.signature(foo)
2854 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2855
2856 self.assertEqual(self.signature(partial(foo, 1)),
2857 ((('b', ..., ..., 'positional_only'),
2858 ('c', ..., ..., 'positional_or_keyword'),
2859 ('d', ..., ..., 'positional_or_keyword'),
2860 ('kwargs', ..., ..., 'var_keyword')),
2861 ...))
2862
2863 self.assertEqual(self.signature(partial(foo, 1, 2)),
2864 ((('c', ..., ..., 'positional_or_keyword'),
2865 ('d', ..., ..., 'positional_or_keyword'),
2866 ('kwargs', ..., ..., 'var_keyword')),
2867 ...))
2868
2869 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2870 ((('d', ..., ..., 'positional_or_keyword'),
2871 ('kwargs', ..., ..., 'var_keyword')),
2872 ...))
2873
2874 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2875 ((('c', 3, ..., 'keyword_only'),
2876 ('d', ..., ..., 'keyword_only'),
2877 ('kwargs', ..., ..., 'var_keyword')),
2878 ...))
2879
2880 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2881 ((('b', ..., ..., 'positional_only'),
2882 ('c', 3, ..., 'keyword_only'),
2883 ('d', ..., ..., 'keyword_only'),
2884 ('kwargs', ..., ..., 'var_keyword')),
2885 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002886
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002887 def test_signature_on_partialmethod(self):
2888 from functools import partialmethod
2889
2890 class Spam:
2891 def test():
2892 pass
2893 ham = partialmethod(test)
2894
2895 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2896 inspect.signature(Spam.ham)
2897
2898 class Spam:
2899 def test(it, a, *, c) -> 'spam':
2900 pass
2901 ham = partialmethod(test, c=1)
2902
larryhastings74613a42021-04-29 21:16:28 -07002903 self.assertEqual(self.signature(Spam.ham, eval_str=False),
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002904 ((('it', ..., ..., 'positional_or_keyword'),
2905 ('a', ..., ..., 'positional_or_keyword'),
2906 ('c', 1, ..., 'keyword_only')),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002907 'spam'))
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002908
larryhastings74613a42021-04-29 21:16:28 -07002909 self.assertEqual(self.signature(Spam().ham, eval_str=False),
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002910 ((('a', ..., ..., 'positional_or_keyword'),
2911 ('c', 1, ..., 'keyword_only')),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002912 'spam'))
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002913
Yury Selivanov8a387212018-03-06 12:59:45 -05002914 class Spam:
2915 def test(self: 'anno', x):
2916 pass
2917
2918 g = partialmethod(test, 1)
2919
larryhastings74613a42021-04-29 21:16:28 -07002920 self.assertEqual(self.signature(Spam.g, eval_str=False),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002921 ((('self', ..., 'anno', 'positional_or_keyword'),),
Yury Selivanov8a387212018-03-06 12:59:45 -05002922 ...))
2923
Yury Selivanov0486f812014-01-29 12:18:59 -05002924 def test_signature_on_fake_partialmethod(self):
2925 def foo(a): pass
2926 foo._partialmethod = 'spam'
2927 self.assertEqual(str(inspect.signature(foo)), '(a)')
2928
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002929 def test_signature_on_decorated(self):
2930 import functools
2931
2932 def decorator(func):
2933 @functools.wraps(func)
2934 def wrapper(*args, **kwargs) -> int:
2935 return func(*args, **kwargs)
2936 return wrapper
2937
2938 class Foo:
2939 @decorator
2940 def bar(self, a, b):
2941 pass
2942
2943 self.assertEqual(self.signature(Foo.bar),
2944 ((('self', ..., ..., "positional_or_keyword"),
2945 ('a', ..., ..., "positional_or_keyword"),
2946 ('b', ..., ..., "positional_or_keyword")),
2947 ...))
2948
2949 self.assertEqual(self.signature(Foo().bar),
2950 ((('a', ..., ..., "positional_or_keyword"),
2951 ('b', ..., ..., "positional_or_keyword")),
2952 ...))
2953
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002954 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2955 ((('args', ..., ..., "var_positional"),
2956 ('kwargs', ..., ..., "var_keyword")),
2957 ...)) # functools.wraps will copy __annotations__
2958 # from "func" to "wrapper", hence no
2959 # return_annotation
2960
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002961 # Test that we handle method wrappers correctly
2962 def decorator(func):
2963 @functools.wraps(func)
2964 def wrapper(*args, **kwargs) -> int:
2965 return func(42, *args, **kwargs)
2966 sig = inspect.signature(func)
2967 new_params = tuple(sig.parameters.values())[1:]
2968 wrapper.__signature__ = sig.replace(parameters=new_params)
2969 return wrapper
2970
2971 class Foo:
2972 @decorator
2973 def __call__(self, a, b):
2974 pass
2975
2976 self.assertEqual(self.signature(Foo.__call__),
2977 ((('a', ..., ..., "positional_or_keyword"),
2978 ('b', ..., ..., "positional_or_keyword")),
2979 ...))
2980
2981 self.assertEqual(self.signature(Foo().__call__),
2982 ((('b', ..., ..., "positional_or_keyword"),),
2983 ...))
2984
Nick Coghlane8c45d62013-07-28 20:00:01 +10002985 # Test we handle __signature__ partway down the wrapper stack
2986 def wrapped_foo_call():
2987 pass
2988 wrapped_foo_call.__wrapped__ = Foo.__call__
2989
2990 self.assertEqual(self.signature(wrapped_foo_call),
2991 ((('a', ..., ..., "positional_or_keyword"),
2992 ('b', ..., ..., "positional_or_keyword")),
2993 ...))
2994
2995
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002996 def test_signature_on_class(self):
2997 class C:
2998 def __init__(self, a):
2999 pass
3000
3001 self.assertEqual(self.signature(C),
3002 ((('a', ..., ..., "positional_or_keyword"),),
3003 ...))
3004
3005 class CM(type):
3006 def __call__(cls, a):
3007 pass
3008 class C(metaclass=CM):
3009 def __init__(self, b):
3010 pass
3011
3012 self.assertEqual(self.signature(C),
3013 ((('a', ..., ..., "positional_or_keyword"),),
3014 ...))
3015
3016 class CM(type):
3017 def __new__(mcls, name, bases, dct, *, foo=1):
3018 return super().__new__(mcls, name, bases, dct)
3019 class C(metaclass=CM):
3020 def __init__(self, b):
3021 pass
3022
3023 self.assertEqual(self.signature(C),
3024 ((('b', ..., ..., "positional_or_keyword"),),
3025 ...))
3026
3027 self.assertEqual(self.signature(CM),
3028 ((('name', ..., ..., "positional_or_keyword"),
3029 ('bases', ..., ..., "positional_or_keyword"),
3030 ('dct', ..., ..., "positional_or_keyword"),
3031 ('foo', 1, ..., "keyword_only")),
3032 ...))
3033
3034 class CMM(type):
3035 def __new__(mcls, name, bases, dct, *, foo=1):
3036 return super().__new__(mcls, name, bases, dct)
3037 def __call__(cls, nm, bs, dt):
3038 return type(nm, bs, dt)
3039 class CM(type, metaclass=CMM):
3040 def __new__(mcls, name, bases, dct, *, bar=2):
3041 return super().__new__(mcls, name, bases, dct)
3042 class C(metaclass=CM):
3043 def __init__(self, b):
3044 pass
3045
3046 self.assertEqual(self.signature(CMM),
3047 ((('name', ..., ..., "positional_or_keyword"),
3048 ('bases', ..., ..., "positional_or_keyword"),
3049 ('dct', ..., ..., "positional_or_keyword"),
3050 ('foo', 1, ..., "keyword_only")),
3051 ...))
3052
3053 self.assertEqual(self.signature(CM),
3054 ((('nm', ..., ..., "positional_or_keyword"),
3055 ('bs', ..., ..., "positional_or_keyword"),
3056 ('dt', ..., ..., "positional_or_keyword")),
3057 ...))
3058
3059 self.assertEqual(self.signature(C),
3060 ((('b', ..., ..., "positional_or_keyword"),),
3061 ...))
3062
3063 class CM(type):
3064 def __init__(cls, name, bases, dct, *, bar=2):
3065 return super().__init__(name, bases, dct)
3066 class C(metaclass=CM):
3067 def __init__(self, b):
3068 pass
3069
3070 self.assertEqual(self.signature(CM),
3071 ((('name', ..., ..., "positional_or_keyword"),
3072 ('bases', ..., ..., "positional_or_keyword"),
3073 ('dct', ..., ..., "positional_or_keyword"),
3074 ('bar', 2, ..., "keyword_only")),
3075 ...))
3076
Miss Islington (bot)948e39a2021-07-16 06:25:57 -07003077 def test_signature_on_subclass(self):
3078 class A:
3079 def __new__(cls, a=1, *args, **kwargs):
3080 return object.__new__(cls)
3081 class B(A):
3082 def __init__(self, b):
3083 pass
3084 class C(A):
3085 def __new__(cls, a=1, b=2, *args, **kwargs):
3086 return object.__new__(cls)
3087 class D(A):
3088 pass
3089
3090 self.assertEqual(self.signature(B),
3091 ((('b', ..., ..., "positional_or_keyword"),),
3092 ...))
3093 self.assertEqual(self.signature(C),
3094 ((('a', 1, ..., 'positional_or_keyword'),
3095 ('b', 2, ..., 'positional_or_keyword'),
3096 ('args', ..., ..., 'var_positional'),
3097 ('kwargs', ..., ..., 'var_keyword')),
3098 ...))
3099 self.assertEqual(self.signature(D),
3100 ((('a', 1, ..., 'positional_or_keyword'),
3101 ('args', ..., ..., 'var_positional'),
3102 ('kwargs', ..., ..., 'var_keyword')),
3103 ...))
3104
3105 def test_signature_on_generic_subclass(self):
3106 from typing import Generic, TypeVar
3107
3108 T = TypeVar('T')
3109
3110 class A(Generic[T]):
3111 def __init__(self, *, a: int) -> None:
3112 pass
3113
3114 self.assertEqual(self.signature(A),
3115 ((('a', ..., int, 'keyword_only'),),
3116 None))
3117
Yury Selivanov145dff82014-02-01 13:49:29 -05003118 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3119 "Signature information for builtins requires docstrings")
3120 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003121 # Test classes without user-defined __init__ or __new__
3122 class C: pass
3123 self.assertEqual(str(inspect.signature(C)), '()')
3124 class D(C): pass
3125 self.assertEqual(str(inspect.signature(D)), '()')
3126
3127 # Test meta-classes without user-defined __init__ or __new__
3128 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003129 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08003130 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
3131 self.assertEqual(inspect.signature(C), None)
3132 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
3133 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003134
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003135 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3136 "Signature information for builtins requires docstrings")
3137 def test_signature_on_builtin_class(self):
Antoine Pitrou91f43802019-05-26 17:10:09 +02003138 expected = ('(file, protocol=None, fix_imports=True, '
3139 'buffer_callback=None)')
3140 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003141
3142 class P(_pickle.Pickler): pass
3143 class EmptyTrait: pass
3144 class P2(EmptyTrait, P): pass
Antoine Pitrou91f43802019-05-26 17:10:09 +02003145 self.assertEqual(str(inspect.signature(P)), expected)
3146 self.assertEqual(str(inspect.signature(P2)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003147
3148 class P3(P2):
3149 def __init__(self, spam):
3150 pass
3151 self.assertEqual(str(inspect.signature(P3)), '(spam)')
3152
3153 class MetaP(type):
3154 def __call__(cls, foo, bar):
3155 pass
3156 class P4(P2, metaclass=MetaP):
3157 pass
3158 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
3159
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003160 def test_signature_on_callable_objects(self):
3161 class Foo:
3162 def __call__(self, a):
3163 pass
3164
3165 self.assertEqual(self.signature(Foo()),
3166 ((('a', ..., ..., "positional_or_keyword"),),
3167 ...))
3168
3169 class Spam:
3170 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003171 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003172 inspect.signature(Spam())
3173
3174 class Bar(Spam, Foo):
3175 pass
3176
3177 self.assertEqual(self.signature(Bar()),
3178 ((('a', ..., ..., "positional_or_keyword"),),
3179 ...))
3180
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003181 class Wrapped:
3182 pass
3183 Wrapped.__wrapped__ = lambda a: None
3184 self.assertEqual(self.signature(Wrapped),
3185 ((('a', ..., ..., "positional_or_keyword"),),
3186 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10003187 # wrapper loop:
3188 Wrapped.__wrapped__ = Wrapped
3189 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3190 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003191
3192 def test_signature_on_lambdas(self):
3193 self.assertEqual(self.signature((lambda a=10: a)),
3194 ((('a', 10, ..., "positional_or_keyword"),),
3195 ...))
3196
3197 def test_signature_equality(self):
3198 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003199 self.assertFalse(inspect.signature(foo) == 42)
3200 self.assertTrue(inspect.signature(foo) != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003201 self.assertTrue(inspect.signature(foo) == ALWAYS_EQ)
3202 self.assertFalse(inspect.signature(foo) != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003203
3204 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003205 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3206 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003207 self.assertEqual(
3208 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003209
3210 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003211 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3212 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003213 self.assertNotEqual(
3214 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003215
3216 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003217 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3218 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003219 self.assertNotEqual(
3220 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003221
3222 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003223 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3224 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003225 self.assertNotEqual(
3226 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003227
3228 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003229 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3230 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003231 self.assertNotEqual(
3232 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003233
3234 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003235 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3236 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003237 self.assertNotEqual(
3238 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003239 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003240 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3241 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003242 self.assertNotEqual(
3243 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003244
3245 def foo(*, a, b, c): pass
3246 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003247 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3248 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003249 self.assertEqual(
3250 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003251
3252 def foo(*, a=1, b, c): pass
3253 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003254 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3255 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003256 self.assertEqual(
3257 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003258
3259 def foo(pos, *, a=1, b, c): pass
3260 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003261 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3262 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003263 self.assertEqual(
3264 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003265
3266 def foo(pos, *, a, b, c): pass
3267 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003268 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3269 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003270 self.assertNotEqual(
3271 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003272
3273 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3274 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003275 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3276 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003277 self.assertEqual(
3278 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003279
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003280 def test_signature_hashable(self):
3281 S = inspect.Signature
3282 P = inspect.Parameter
3283
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003284 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003285 foo_sig = inspect.signature(foo)
3286
3287 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3288
3289 self.assertEqual(hash(foo_sig), hash(manual_sig))
3290 self.assertNotEqual(hash(foo_sig),
3291 hash(manual_sig.replace(return_annotation='spam')))
3292
3293 def bar(a) -> 1: pass
3294 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3295
3296 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003297 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003298 hash(inspect.signature(foo))
3299
Pablo Galindob0544ba2021-04-21 12:41:19 +01003300 def foo(a) -> {}: pass
3301 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3302 hash(inspect.signature(foo))
3303
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003304 def test_signature_str(self):
3305 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3306 pass
3307 self.assertEqual(str(inspect.signature(foo)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003308 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003309
3310 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3311 pass
3312 self.assertEqual(str(inspect.signature(foo)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003313 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003314
3315 def foo():
3316 pass
3317 self.assertEqual(str(inspect.signature(foo)), '()')
3318
3319 def test_signature_str_positional_only(self):
3320 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003321 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003322
3323 def test(a_po, *, b, **kwargs):
3324 return a_po, kwargs
3325
3326 sig = inspect.signature(test)
3327 new_params = list(sig.parameters.values())
3328 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3329 test.__signature__ = sig.replace(parameters=new_params)
3330
3331 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003332 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003333
Yury Selivanov2393dca2014-01-27 15:07:58 -05003334 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3335 '(foo, /)')
3336
3337 self.assertEqual(str(S(parameters=[
3338 P('foo', P.POSITIONAL_ONLY),
3339 P('bar', P.VAR_KEYWORD)])),
3340 '(foo, /, **bar)')
3341
3342 self.assertEqual(str(S(parameters=[
3343 P('foo', P.POSITIONAL_ONLY),
3344 P('bar', P.VAR_POSITIONAL)])),
3345 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003346
3347 def test_signature_replace_anno(self):
3348 def test() -> 42:
3349 pass
3350
3351 sig = inspect.signature(test)
3352 sig = sig.replace(return_annotation=None)
3353 self.assertIs(sig.return_annotation, None)
3354 sig = sig.replace(return_annotation=sig.empty)
3355 self.assertIs(sig.return_annotation, sig.empty)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003356 sig = sig.replace(return_annotation=42)
3357 self.assertEqual(sig.return_annotation, 42)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003358 self.assertEqual(sig, inspect.signature(test))
3359
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003360 def test_signature_on_mangled_parameters(self):
3361 class Spam:
3362 def foo(self, __p1:1=2, *, __p2:2=3):
3363 pass
3364 class Ham(Spam):
3365 pass
3366
3367 self.assertEqual(self.signature(Spam.foo),
3368 ((('self', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003369 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3370 ('_Spam__p2', 3, 2, "keyword_only")),
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003371 ...))
3372
3373 self.assertEqual(self.signature(Spam.foo),
3374 self.signature(Ham.foo))
3375
Yury Selivanovda396452014-03-27 12:09:24 -04003376 def test_signature_from_callable_python_obj(self):
3377 class MySignature(inspect.Signature): pass
3378 def foo(a, *, b:1): pass
3379 foo_sig = MySignature.from_callable(foo)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003380 self.assertIsInstance(foo_sig, MySignature)
3381
3382 def test_signature_from_callable_class(self):
3383 # A regression test for a class inheriting its signature from `object`.
3384 class MySignature(inspect.Signature): pass
3385 class foo: pass
3386 foo_sig = MySignature.from_callable(foo)
3387 self.assertIsInstance(foo_sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003388
3389 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3390 "Signature information for builtins requires docstrings")
3391 def test_signature_from_callable_builtin_obj(self):
3392 class MySignature(inspect.Signature): pass
3393 sig = MySignature.from_callable(_pickle.Pickler)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003394 self.assertIsInstance(sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003395
larryhastingsf36ba122018-01-28 11:13:09 -08003396 def test_signature_definition_order_preserved_on_kwonly(self):
3397 for fn in signatures_with_lexicographic_keyword_only_parameters():
3398 signature = inspect.signature(fn)
3399 l = list(signature.parameters)
3400 sorted_l = sorted(l)
3401 self.assertTrue(l)
3402 self.assertEqual(l, sorted_l)
3403 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3404 l = list(signature.parameters)
3405 self.assertEqual(l, unsorted_keyword_only_parameters)
3406
Jens Reidel611836a2020-03-18 03:22:46 +01003407 def test_signater_parameters_is_ordered(self):
3408 p1 = inspect.signature(lambda x, y: None).parameters
3409 p2 = inspect.signature(lambda y, x: None).parameters
3410 self.assertNotEqual(p1, p2)
3411
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003412 def test_signature_annotations_with_local_namespaces(self):
3413 class Foo: ...
3414 def func(foo: Foo) -> int: pass
Pablo Galindob0544ba2021-04-21 12:41:19 +01003415 def func2(foo: Foo, bar: 'Bar') -> int: pass
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003416
3417 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3418 with self.subTest(signature_func = signature_func):
3419 sig1 = signature_func(func)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003420 self.assertEqual(sig1.return_annotation, int)
3421 self.assertEqual(sig1.parameters['foo'].annotation, Foo)
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003422
larryhastings74613a42021-04-29 21:16:28 -07003423 sig2 = signature_func(func, locals=locals())
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003424 self.assertEqual(sig2.return_annotation, int)
3425 self.assertEqual(sig2.parameters['foo'].annotation, Foo)
3426
larryhastings74613a42021-04-29 21:16:28 -07003427 sig3 = signature_func(func2, globals={'Bar': int}, locals=locals())
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003428 self.assertEqual(sig3.return_annotation, int)
3429 self.assertEqual(sig3.parameters['foo'].annotation, Foo)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003430 self.assertEqual(sig3.parameters['bar'].annotation, 'Bar')
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003431
larryhastings74613a42021-04-29 21:16:28 -07003432 def test_signature_eval_str(self):
3433 isa = inspect_stringized_annotations
3434 sig = inspect.Signature
3435 par = inspect.Parameter
3436 PORK = inspect.Parameter.POSITIONAL_OR_KEYWORD
3437 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3438 with self.subTest(signature_func = signature_func):
3439 self.assertEqual(
3440 signature_func(isa.MyClass),
3441 sig(
3442 parameters=(
3443 par('a', PORK),
3444 par('b', PORK),
3445 )))
3446 self.assertEqual(
3447 signature_func(isa.function),
3448 sig(
3449 return_annotation='MyClass',
3450 parameters=(
3451 par('a', PORK, annotation='int'),
3452 par('b', PORK, annotation='str'),
3453 )))
3454 self.assertEqual(
3455 signature_func(isa.function2),
3456 sig(
3457 return_annotation='MyClass',
3458 parameters=(
3459 par('a', PORK, annotation='int'),
3460 par('b', PORK, annotation="'str'"),
3461 par('c', PORK, annotation="MyClass"),
3462 )))
3463 self.assertEqual(
3464 signature_func(isa.function3),
3465 sig(
3466 parameters=(
3467 par('a', PORK, annotation="'int'"),
3468 par('b', PORK, annotation="'str'"),
3469 par('c', PORK, annotation="'MyClass'"),
3470 )))
3471
3472 self.assertEqual(signature_func(isa.UnannotatedClass), sig())
3473 self.assertEqual(signature_func(isa.unannotated_function),
3474 sig(
3475 parameters=(
3476 par('a', PORK),
3477 par('b', PORK),
3478 par('c', PORK),
3479 )))
3480
3481 self.assertEqual(
3482 signature_func(isa.MyClass, eval_str=True),
3483 sig(
3484 parameters=(
3485 par('a', PORK),
3486 par('b', PORK),
3487 )))
3488 self.assertEqual(
3489 signature_func(isa.function, eval_str=True),
3490 sig(
3491 return_annotation=isa.MyClass,
3492 parameters=(
3493 par('a', PORK, annotation=int),
3494 par('b', PORK, annotation=str),
3495 )))
3496 self.assertEqual(
3497 signature_func(isa.function2, eval_str=True),
3498 sig(
3499 return_annotation=isa.MyClass,
3500 parameters=(
3501 par('a', PORK, annotation=int),
3502 par('b', PORK, annotation='str'),
3503 par('c', PORK, annotation=isa.MyClass),
3504 )))
3505 self.assertEqual(
3506 signature_func(isa.function3, eval_str=True),
3507 sig(
3508 parameters=(
3509 par('a', PORK, annotation='int'),
3510 par('b', PORK, annotation='str'),
3511 par('c', PORK, annotation='MyClass'),
3512 )))
3513
3514 globalns = {'int': float, 'str': complex}
3515 localns = {'str': tuple, 'MyClass': dict}
3516 with self.assertRaises(NameError):
3517 signature_func(isa.function, eval_str=True, globals=globalns)
3518
3519 self.assertEqual(
3520 signature_func(isa.function, eval_str=True, locals=localns),
3521 sig(
3522 return_annotation=dict,
3523 parameters=(
3524 par('a', PORK, annotation=int),
3525 par('b', PORK, annotation=tuple),
3526 )))
3527
3528 self.assertEqual(
3529 signature_func(isa.function, eval_str=True, globals=globalns, locals=localns),
3530 sig(
3531 return_annotation=dict,
3532 parameters=(
3533 par('a', PORK, annotation=float),
3534 par('b', PORK, annotation=tuple),
3535 )))
3536
3537 def test_signature_none_annotation(self):
3538 class funclike:
3539 # Has to be callable, and have correct
3540 # __code__, __annotations__, __defaults__, __name__,
3541 # and __kwdefaults__ attributes
3542
3543 def __init__(self, func):
3544 self.__name__ = func.__name__
3545 self.__code__ = func.__code__
3546 self.__annotations__ = func.__annotations__
3547 self.__defaults__ = func.__defaults__
3548 self.__kwdefaults__ = func.__kwdefaults__
3549 self.func = func
3550
3551 def __call__(self, *args, **kwargs):
3552 return self.func(*args, **kwargs)
3553
3554 def foo(): pass
3555 foo = funclike(foo)
3556 foo.__annotations__ = None
3557 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3558 with self.subTest(signature_func = signature_func):
3559 self.assertEqual(signature_func(foo), inspect.Signature())
3560 self.assertEqual(inspect.get_annotations(foo), {})
3561
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003562
3563class TestParameterObject(unittest.TestCase):
3564 def test_signature_parameter_kinds(self):
3565 P = inspect.Parameter
3566 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3567 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3568
3569 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3570 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3571
3572 def test_signature_parameter_object(self):
3573 p = inspect.Parameter('foo', default=10,
3574 kind=inspect.Parameter.POSITIONAL_ONLY)
3575 self.assertEqual(p.name, 'foo')
3576 self.assertEqual(p.default, 10)
3577 self.assertIs(p.annotation, p.empty)
3578 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3579
Dong-hee Naa9cab432018-05-30 00:04:08 +09003580 with self.assertRaisesRegex(ValueError, "value '123' is "
3581 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003582 inspect.Parameter('foo', default=10, kind='123')
3583
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003584 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003585 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3586
Yury Selivanov2393dca2014-01-27 15:07:58 -05003587 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003588 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3589
Yury Selivanov2393dca2014-01-27 15:07:58 -05003590 with self.assertRaisesRegex(ValueError,
3591 'is not a valid parameter name'):
3592 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3593
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003594 with self.assertRaisesRegex(ValueError,
3595 'is not a valid parameter name'):
3596 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3597
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003598 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003599 inspect.Parameter('a', default=42,
3600 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_POSITIONAL)
3605
3606 p = inspect.Parameter('a', default=42,
3607 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003608 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003609 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3610
3611 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003612 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003613
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003614 def test_signature_parameter_hashable(self):
3615 P = inspect.Parameter
3616 foo = P('foo', kind=P.POSITIONAL_ONLY)
3617 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3618 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3619 default=42)))
3620 self.assertNotEqual(hash(foo),
3621 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3622
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003623 def test_signature_parameter_equality(self):
3624 P = inspect.Parameter
3625 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3626
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003627 self.assertTrue(p == p)
3628 self.assertFalse(p != p)
3629 self.assertFalse(p == 42)
3630 self.assertTrue(p != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003631 self.assertTrue(p == ALWAYS_EQ)
3632 self.assertFalse(p != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003633
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003634 self.assertTrue(p == P('foo', default=42,
3635 kind=inspect.Parameter.KEYWORD_ONLY))
3636 self.assertFalse(p != P('foo', default=42,
3637 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003638
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003639 def test_signature_parameter_replace(self):
3640 p = inspect.Parameter('foo', default=42,
3641 kind=inspect.Parameter.KEYWORD_ONLY)
3642
3643 self.assertIsNot(p, p.replace())
3644 self.assertEqual(p, p.replace())
3645
3646 p2 = p.replace(annotation=1)
3647 self.assertEqual(p2.annotation, 1)
3648 p2 = p2.replace(annotation=p2.empty)
3649 self.assertEqual(p, p2)
3650
3651 p2 = p2.replace(name='bar')
3652 self.assertEqual(p2.name, 'bar')
3653 self.assertNotEqual(p2, p)
3654
Yury Selivanov2393dca2014-01-27 15:07:58 -05003655 with self.assertRaisesRegex(ValueError,
3656 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003657 p2 = p2.replace(name=p2.empty)
3658
3659 p2 = p2.replace(name='foo', default=None)
3660 self.assertIs(p2.default, None)
3661 self.assertNotEqual(p2, p)
3662
3663 p2 = p2.replace(name='foo', default=p2.empty)
3664 self.assertIs(p2.default, p2.empty)
3665
3666
3667 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3668 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3669 self.assertNotEqual(p2, p)
3670
Dong-hee Naa9cab432018-05-30 00:04:08 +09003671 with self.assertRaisesRegex(ValueError,
3672 "value <class 'inspect._empty'> "
3673 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003674 p2 = p2.replace(kind=p2.empty)
3675
3676 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3677 self.assertEqual(p2, p)
3678
3679 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003680 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3681 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003682
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003683 @cpython_only
3684 def test_signature_parameter_implicit(self):
3685 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003686 'implicit arguments must be passed as '
3687 'positional or keyword arguments, '
3688 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003689 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3690
3691 param = inspect.Parameter(
3692 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3693 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3694 self.assertEqual(param.name, 'implicit0')
3695
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003696 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003697 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003698
3699 with self.assertRaises(AttributeError):
3700 p.foo = 'bar'
3701
3702 with self.assertRaises(AttributeError):
3703 p.kind = 123
3704
3705
3706class TestSignatureBind(unittest.TestCase):
3707 @staticmethod
3708 def call(func, *args, **kwargs):
3709 sig = inspect.signature(func)
3710 ba = sig.bind(*args, **kwargs)
3711 return func(*ba.args, **ba.kwargs)
3712
3713 def test_signature_bind_empty(self):
3714 def test():
3715 return 42
3716
3717 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003718 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003719 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003720 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003721 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003722 with self.assertRaisesRegex(
3723 TypeError, "got an unexpected keyword argument 'spam'"):
3724
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003725 self.call(test, spam=1)
3726
3727 def test_signature_bind_var(self):
3728 def test(*args, **kwargs):
3729 return args, kwargs
3730
3731 self.assertEqual(self.call(test), ((), {}))
3732 self.assertEqual(self.call(test, 1), ((1,), {}))
3733 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3734 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3735 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3736 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3737 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3738 ((1, 2), {'foo': 'bar'}))
3739
3740 def test_signature_bind_just_args(self):
3741 def test(a, b, c):
3742 return a, b, c
3743
3744 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3745
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003746 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003747 self.call(test, 1, 2, 3, 4)
3748
Yury Selivanov86872752015-05-19 00:27:49 -04003749 with self.assertRaisesRegex(TypeError,
3750 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003751 self.call(test, 1)
3752
Yury Selivanov86872752015-05-19 00:27:49 -04003753 with self.assertRaisesRegex(TypeError,
3754 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003755 self.call(test)
3756
3757 def test(a, b, c=10):
3758 return a, b, c
3759 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3760 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3761
3762 def test(a=1, b=2, c=3):
3763 return a, b, c
3764 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3765 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3766 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3767
3768 def test_signature_bind_varargs_order(self):
3769 def test(*args):
3770 return args
3771
3772 self.assertEqual(self.call(test), ())
3773 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3774
3775 def test_signature_bind_args_and_varargs(self):
3776 def test(a, b, c=3, *args):
3777 return a, b, c, args
3778
3779 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3780 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3781 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3782 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3783
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003784 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003785 "multiple values for argument 'c'"):
3786 self.call(test, 1, 2, 3, c=4)
3787
3788 def test_signature_bind_just_kwargs(self):
3789 def test(**kwargs):
3790 return kwargs
3791
3792 self.assertEqual(self.call(test), {})
3793 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3794 {'foo': 'bar', 'spam': 'ham'})
3795
3796 def test_signature_bind_args_and_kwargs(self):
3797 def test(a, b, c=3, **kwargs):
3798 return a, b, c, kwargs
3799
3800 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3801 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3802 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3803 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3804 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3805 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3806 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3807 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3808 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3809 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3810 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3811 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3812 (1, 2, 4, {'foo': 'bar'}))
3813 self.assertEqual(self.call(test, c=5, a=4, b=3),
3814 (4, 3, 5, {}))
3815
3816 def test_signature_bind_kwonly(self):
3817 def test(*, foo):
3818 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003819 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003820 'too many positional arguments'):
3821 self.call(test, 1)
3822 self.assertEqual(self.call(test, foo=1), 1)
3823
3824 def test(a, *, foo=1, bar):
3825 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003826 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003827 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003828 self.call(test, 1)
3829
3830 def test(foo, *, bar):
3831 return foo, bar
3832 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3833 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3834
Yury Selivanov86872752015-05-19 00:27:49 -04003835 with self.assertRaisesRegex(
3836 TypeError, "got an unexpected keyword argument 'spam'"):
3837
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003838 self.call(test, bar=2, foo=1, spam=10)
3839
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003840 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003841 'too many positional arguments'):
3842 self.call(test, 1, 2)
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, bar=2)
3847
Yury Selivanov86872752015-05-19 00:27:49 -04003848 with self.assertRaisesRegex(
3849 TypeError, "got an unexpected keyword argument 'spam'"):
3850
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003851 self.call(test, 1, bar=2, spam='ham')
3852
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003853 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003854 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003855 self.call(test, 1)
3856
3857 def test(foo, *, bar, **bin):
3858 return foo, bar, bin
3859 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3860 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3861 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3862 (1, 2, {'spam': 'ham'}))
3863 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3864 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003865 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003866 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003867 self.call(test, spam='ham', bar=2)
3868 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3869 (1, 2, {'bin': 1, 'spam': 10}))
3870
3871 def test_signature_bind_arguments(self):
3872 def test(a, *args, b, z=100, **kwargs):
3873 pass
3874 sig = inspect.signature(test)
3875 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3876 # we won't have 'z' argument in the bound arguments object, as we didn't
3877 # pass it to the 'bind'
3878 self.assertEqual(tuple(ba.arguments.items()),
3879 (('a', 10), ('args', (20,)), ('b', 30),
3880 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3881 self.assertEqual(ba.kwargs,
3882 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3883 self.assertEqual(ba.args, (10, 20))
3884
3885 def test_signature_bind_positional_only(self):
3886 P = inspect.Parameter
3887
3888 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3889 return a_po, b_po, c_po, foo, bar, kwargs
3890
3891 sig = inspect.signature(test)
3892 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3893 for name in ('a_po', 'b_po', 'c_po'):
3894 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3895 new_sig = sig.replace(parameters=new_params.values())
3896 test.__signature__ = new_sig
3897
3898 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3899 (1, 2, 4, 5, 6, {}))
3900
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003901 self.assertEqual(self.call(test, 1, 2),
3902 (1, 2, 3, 42, 50, {}))
3903
3904 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3905 (1, 2, 3, 4, 5, {}))
3906
3907 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3908 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3909
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003910 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003911 self.call(test, 1, 2, c_po=4)
3912
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003913 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003914 self.call(test, a_po=1, b_po=2)
3915
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003916 def test_signature_bind_with_self_arg(self):
3917 # Issue #17071: one of the parameters is named "self
3918 def test(a, self, b):
3919 pass
3920 sig = inspect.signature(test)
3921 ba = sig.bind(1, 2, 3)
3922 self.assertEqual(ba.args, (1, 2, 3))
3923 ba = sig.bind(1, self=2, b=3)
3924 self.assertEqual(ba.args, (1, 2, 3))
3925
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003926 def test_signature_bind_vararg_name(self):
3927 def test(a, *args):
3928 return a, args
3929 sig = inspect.signature(test)
3930
Yury Selivanov86872752015-05-19 00:27:49 -04003931 with self.assertRaisesRegex(
3932 TypeError, "got an unexpected keyword argument 'args'"):
3933
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003934 sig.bind(a=0, args=1)
3935
3936 def test(*args, **kwargs):
3937 return args, kwargs
3938 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3939
3940 sig = inspect.signature(test)
3941 ba = sig.bind(args=1)
3942 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3943
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003944 @cpython_only
3945 def test_signature_bind_implicit_arg(self):
3946 # Issue #19611: getcallargs should work with set comprehensions
3947 def make_set():
3948 return {z * z for z in range(5)}
3949 setcomp_code = make_set.__code__.co_consts[1]
3950 setcomp_func = types.FunctionType(setcomp_code, {})
3951
3952 iterator = iter(range(5))
3953 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3954
Pablo Galindof3ef06a2019-10-15 12:40:02 +01003955 def test_signature_bind_posonly_kwargs(self):
3956 def foo(bar, /, **kwargs):
3957 return bar, kwargs.get(bar)
3958
3959 sig = inspect.signature(foo)
3960 result = sig.bind("pos-only", bar="keyword")
3961
3962 self.assertEqual(result.kwargs, {"bar": "keyword"})
3963 self.assertIn(("bar", "pos-only"), result.arguments.items())
3964
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003965
3966class TestBoundArguments(unittest.TestCase):
3967 def test_signature_bound_arguments_unhashable(self):
3968 def foo(a): pass
3969 ba = inspect.signature(foo).bind(1)
3970
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003971 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003972 hash(ba)
3973
3974 def test_signature_bound_arguments_equality(self):
3975 def foo(a): pass
3976 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003977 self.assertTrue(ba == ba)
3978 self.assertFalse(ba != ba)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003979 self.assertTrue(ba == ALWAYS_EQ)
3980 self.assertFalse(ba != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003981
3982 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003983 self.assertTrue(ba == ba2)
3984 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003985
3986 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003987 self.assertFalse(ba == ba3)
3988 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003989 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003990 self.assertTrue(ba == ba3)
3991 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003992
3993 def bar(b): pass
3994 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003995 self.assertFalse(ba == ba4)
3996 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003997
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003998 def foo(*, a, b): pass
3999 sig = inspect.signature(foo)
4000 ba1 = sig.bind(a=1, b=2)
4001 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03004002 self.assertTrue(ba1 == ba2)
4003 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04004004
Yury Selivanova5d63dd2014-03-27 11:31:43 -04004005 def test_signature_bound_arguments_pickle(self):
4006 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
4007 sig = inspect.signature(foo)
4008 ba = sig.bind(20, 30, z={})
4009
4010 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
4011 with self.subTest(pickle_ver=ver):
4012 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
4013 self.assertEqual(ba, ba_pickled)
4014
Yury Selivanov3f6538f2015-05-14 18:47:17 -04004015 def test_signature_bound_arguments_repr(self):
4016 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
4017 sig = inspect.signature(foo)
4018 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04004019 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04004020
Yury Selivanovb907a512015-05-16 13:45:09 -04004021 def test_signature_bound_arguments_apply_defaults(self):
4022 def foo(a, b=1, *args, c:1={}, **kw): pass
4023 sig = inspect.signature(foo)
4024
4025 ba = sig.bind(20)
4026 ba.apply_defaults()
4027 self.assertEqual(
4028 list(ba.arguments.items()),
4029 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
4030
4031 # Make sure that we preserve the order:
4032 # i.e. 'c' should be *before* 'kw'.
4033 ba = sig.bind(10, 20, 30, d=1)
4034 ba.apply_defaults()
4035 self.assertEqual(
4036 list(ba.arguments.items()),
4037 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
4038
4039 # Make sure that BoundArguments produced by bind_partial()
4040 # are supported.
4041 def foo(a, b): pass
4042 sig = inspect.signature(foo)
4043 ba = sig.bind_partial(20)
4044 ba.apply_defaults()
4045 self.assertEqual(
4046 list(ba.arguments.items()),
4047 [('a', 20)])
4048
4049 # Test no args
4050 def foo(): pass
4051 sig = inspect.signature(foo)
4052 ba = sig.bind()
4053 ba.apply_defaults()
4054 self.assertEqual(list(ba.arguments.items()), [])
4055
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05004056 # Make sure a no-args binding still acquires proper defaults.
4057 def foo(a='spam'): pass
4058 sig = inspect.signature(foo)
4059 ba = sig.bind()
4060 ba.apply_defaults()
4061 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
4062
Rémi Lapeyre2cca8ef2020-01-28 13:47:03 +01004063 def test_signature_bound_arguments_arguments_type(self):
4064 def foo(a): pass
4065 ba = inspect.signature(foo).bind(1)
4066 self.assertIs(type(ba.arguments), dict)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004067
Yury Selivanovd82eddc2014-01-29 11:24:39 -05004068class TestSignaturePrivateHelpers(unittest.TestCase):
4069 def test_signature_get_bound_param(self):
4070 getter = inspect._signature_get_bound_param
4071
4072 self.assertEqual(getter('($self)'), 'self')
4073 self.assertEqual(getter('($self, obj)'), 'self')
4074 self.assertEqual(getter('($cls, /, obj)'), 'cls')
4075
Larry Hastings2623c8c2014-02-08 22:15:29 -08004076 def _strip_non_python_syntax(self, input,
4077 clean_signature, self_parameter, last_positional_only):
4078 computed_clean_signature, \
4079 computed_self_parameter, \
4080 computed_last_positional_only = \
4081 inspect._signature_strip_non_python_syntax(input)
4082 self.assertEqual(computed_clean_signature, clean_signature)
4083 self.assertEqual(computed_self_parameter, self_parameter)
4084 self.assertEqual(computed_last_positional_only, last_positional_only)
4085
4086 def test_signature_strip_non_python_syntax(self):
4087 self._strip_non_python_syntax(
4088 "($module, /, path, mode, *, dir_fd=None, " +
4089 "effective_ids=False,\n follow_symlinks=True)",
4090 "(module, path, mode, *, dir_fd=None, " +
4091 "effective_ids=False, follow_symlinks=True)",
4092 0,
4093 0)
4094
4095 self._strip_non_python_syntax(
4096 "($module, word, salt, /)",
4097 "(module, word, salt)",
4098 0,
4099 2)
4100
4101 self._strip_non_python_syntax(
4102 "(x, y=None, z=None, /)",
4103 "(x, y=None, z=None)",
4104 None,
4105 2)
4106
4107 self._strip_non_python_syntax(
4108 "(x, y=None, z=None)",
4109 "(x, y=None, z=None)",
4110 None,
4111 None)
4112
4113 self._strip_non_python_syntax(
4114 "(x,\n y=None,\n z = None )",
4115 "(x, y=None, z=None)",
4116 None,
4117 None)
4118
4119 self._strip_non_python_syntax(
4120 "",
4121 "",
4122 None,
4123 None)
4124
4125 self._strip_non_python_syntax(
4126 None,
4127 None,
4128 None,
4129 None)
4130
Nick Coghlan9c680b02015-04-13 12:54:54 -04004131class TestSignatureDefinitions(unittest.TestCase):
4132 # This test case provides a home for checking that particular APIs
4133 # have signatures available for introspection
4134
4135 @cpython_only
4136 @unittest.skipIf(MISSING_C_DOCSTRINGS,
4137 "Signature information for builtins requires docstrings")
4138 def test_builtins_have_signatures(self):
4139 # This checks all builtin callables in CPython have signatures
4140 # A few have signatures Signature can't yet handle, so we skip those
4141 # since they will have to wait until PEP 457 adds the required
4142 # introspection support to the inspect module
4143 # Some others also haven't been converted yet for various other
4144 # reasons, so we also skip those for the time being, but design
4145 # the test to fail in order to indicate when it needs to be
4146 # updated.
4147 no_signature = set()
4148 # These need PEP 457 groups
4149 needs_groups = {"range", "slice", "dir", "getattr",
4150 "next", "iter", "vars"}
4151 no_signature |= needs_groups
Joshua Bronsonf0a6fde2021-03-23 18:47:21 -04004152 # These have unrepresentable parameter default values of NULL
4153 needs_null = {"anext"}
4154 no_signature |= needs_null
Nick Coghlan9c680b02015-04-13 12:54:54 -04004155 # These need PEP 457 groups or a signature change to accept None
4156 needs_semantic_update = {"round"}
4157 no_signature |= needs_semantic_update
4158 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04004159 needs_varargs = {"breakpoint", "min", "max", "print",
4160 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04004161 no_signature |= needs_varargs
4162 # These simply weren't covered in the initial AC conversion
4163 # for builtin callables
4164 not_converted_yet = {"open", "__import__"}
4165 no_signature |= not_converted_yet
4166 # These builtin types are expected to provide introspection info
4167 types_with_signatures = set()
4168 # Check the signatures we expect to be there
4169 ns = vars(builtins)
4170 for name, obj in sorted(ns.items()):
4171 if not callable(obj):
4172 continue
4173 # The builtin types haven't been converted to AC yet
4174 if isinstance(obj, type) and (name not in types_with_signatures):
4175 # Note that this also skips all the exception types
4176 no_signature.add(name)
4177 if (name in no_signature):
4178 # Not yet converted
4179 continue
4180 with self.subTest(builtin=name):
4181 self.assertIsNotNone(inspect.signature(obj))
4182 # Check callables that haven't been converted don't claim a signature
4183 # This ensures this test will start failing as more signatures are
4184 # added, so the affected items can be moved into the scope of the
4185 # regression test above
4186 for name in no_signature:
4187 with self.subTest(builtin=name):
4188 self.assertIsNone(obj.__text_signature__)
4189
Serhiy Storchakad53cf992019-05-06 22:40:27 +03004190 def test_python_function_override_signature(self):
4191 def func(*args, **kwargs):
4192 pass
4193 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
4194 sig = inspect.signature(func)
4195 self.assertIsNotNone(sig)
4196 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
4197 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
4198 sig = inspect.signature(func)
4199 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
4200
Yury Selivanovd82eddc2014-01-29 11:24:39 -05004201
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01004202class NTimesUnwrappable:
4203 def __init__(self, n):
4204 self.n = n
4205 self._next = None
4206
4207 @property
4208 def __wrapped__(self):
4209 if self.n <= 0:
4210 raise Exception("Unwrapped too many times")
4211 if self._next is None:
4212 self._next = NTimesUnwrappable(self.n - 1)
4213 return self._next
4214
Nick Coghlane8c45d62013-07-28 20:00:01 +10004215class TestUnwrap(unittest.TestCase):
4216
4217 def test_unwrap_one(self):
4218 def func(a, b):
4219 return a + b
4220 wrapper = functools.lru_cache(maxsize=20)(func)
4221 self.assertIs(inspect.unwrap(wrapper), func)
4222
4223 def test_unwrap_several(self):
4224 def func(a, b):
4225 return a + b
4226 wrapper = func
4227 for __ in range(10):
4228 @functools.wraps(wrapper)
4229 def wrapper():
4230 pass
4231 self.assertIsNot(wrapper.__wrapped__, func)
4232 self.assertIs(inspect.unwrap(wrapper), func)
4233
4234 def test_stop(self):
4235 def func1(a, b):
4236 return a + b
4237 @functools.wraps(func1)
4238 def func2():
4239 pass
4240 @functools.wraps(func2)
4241 def wrapper():
4242 pass
4243 func2.stop_here = 1
4244 unwrapped = inspect.unwrap(wrapper,
4245 stop=(lambda f: hasattr(f, "stop_here")))
4246 self.assertIs(unwrapped, func2)
4247
4248 def test_cycle(self):
4249 def func1(): pass
4250 func1.__wrapped__ = func1
4251 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4252 inspect.unwrap(func1)
4253
4254 def func2(): pass
4255 func2.__wrapped__ = func1
4256 func1.__wrapped__ = func2
4257 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4258 inspect.unwrap(func1)
4259 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4260 inspect.unwrap(func2)
4261
4262 def test_unhashable(self):
4263 def func(): pass
4264 func.__wrapped__ = None
4265 class C:
4266 __hash__ = None
4267 __wrapped__ = func
4268 self.assertIsNone(inspect.unwrap(C()))
4269
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01004270 def test_recursion_limit(self):
4271 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
4272 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4273 inspect.unwrap(obj)
4274
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004275class TestMain(unittest.TestCase):
4276 def test_only_source(self):
4277 module = importlib.import_module('unittest')
4278 rc, out, err = assert_python_ok('-m', 'inspect',
4279 'unittest')
4280 lines = out.decode().splitlines()
4281 # ignore the final newline
4282 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
4283 self.assertEqual(err, b'')
4284
Yury Selivanov42407ab2014-06-23 10:23:50 -07004285 def test_custom_getattr(self):
4286 def foo():
4287 pass
4288 foo.__signature__ = 42
4289 with self.assertRaises(TypeError):
4290 inspect.signature(foo)
4291
Brett Cannon634a8fc2013-10-02 10:25:42 -04004292 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04004293 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004294 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004295 rc, out, err = assert_python_ok('-m', 'inspect',
4296 'concurrent.futures:ThreadPoolExecutor')
4297 lines = out.decode().splitlines()
4298 # ignore the final newline
4299 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04004300 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004301 self.assertEqual(err, b'')
4302
4303 def test_builtins(self):
4304 module = importlib.import_module('unittest')
4305 _, out, err = assert_python_failure('-m', 'inspect',
4306 'sys')
4307 lines = err.decode().splitlines()
4308 self.assertEqual(lines, ["Can't get info for builtin modules."])
4309
4310 def test_details(self):
4311 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01004312 args = support.optim_args_from_interpreter_flags()
4313 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004314 'unittest', '--details')
4315 output = out.decode()
4316 # Just a quick sanity check on the output
4317 self.assertIn(module.__name__, output)
4318 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01004319 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004320 self.assertEqual(err, b'')
4321
4322
Yury Selivanovef1e7502014-12-08 16:05:34 -05004323class TestReload(unittest.TestCase):
4324
4325 src_before = textwrap.dedent("""\
4326def foo():
4327 print("Bla")
4328 """)
4329
4330 src_after = textwrap.dedent("""\
4331def foo():
4332 print("Oh no!")
4333 """)
4334
4335 def assertInspectEqual(self, path, source):
4336 inspected_src = inspect.getsource(source)
Inada Naokifb786922021-04-06 11:18:41 +09004337 with open(path, encoding='utf-8') as src:
Yury Selivanovef1e7502014-12-08 16:05:34 -05004338 self.assertEqual(
4339 src.read().splitlines(True),
4340 inspected_src.splitlines(True)
4341 )
4342
4343 def test_getsource_reload(self):
4344 # see issue 1218234
4345 with _ready_to_import('reload_bug', self.src_before) as (name, path):
4346 module = importlib.import_module(name)
4347 self.assertInspectEqual(path, module)
Inada Naokifb786922021-04-06 11:18:41 +09004348 with open(path, 'w', encoding='utf-8') as src:
Yury Selivanovef1e7502014-12-08 16:05:34 -05004349 src.write(self.src_after)
4350 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004351
Nick Coghlane8c45d62013-07-28 20:00:01 +10004352
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004353def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00004354 run_unittest(
Irit Katriel6e1eec72020-12-04 16:45:38 +00004355 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBlockComments,
4356 TestBuggyCases, TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00004357 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00004358 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004359 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04004360 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04004361 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04004362 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Miss Islington (bot)f468ede2021-07-30 10:46:42 -07004363 TestGetCoroutineState, TestGettingSourceOfToplevelFrames,
4364 TestGetsourceInteractive,
Michael Foord95fc51d2010-11-20 15:07:30 +00004365 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00004366
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004367if __name__ == "__main__":
4368 test_main()