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