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