blob: b664c14020f35eab42339a519282ff3aed78545f [file] [log] [blame]
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001import builtins
Guido van Rossum813b0e52007-05-21 18:11:34 +00002import collections
Larry Hastings5c661892014-01-24 06:17:25 -08003import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10004import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10005import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08006import inspect
7import io
8import linecache
9import os
Christian Heimesa3538eb2007-11-06 11:44:48 +000010from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080011import _pickle
Yury Selivanova5d63dd2014-03-27 11:31:43 -040012import pickle
Larry Hastings5c661892014-01-24 06:17:25 -080013import shutil
14import sys
15import types
Yury Selivanovef1e7502014-12-08 16:05:34 -050016import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080017import unicodedata
18import unittest
Yury Selivanova773de02014-02-21 18:30:53 -050019import unittest.mock
Yury Selivanov75445082015-05-11 22:57:16 -040020import warnings
Larry Hastings5c661892014-01-24 06:17:25 -080021
Brett Cannon634a8fc2013-10-02 10:25:42 -040022try:
23 from concurrent.futures import ThreadPoolExecutor
24except ImportError:
25 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000026
Hai Shic7decc22020-08-04 23:53:12 +080027from test.support import run_unittest, cpython_only
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +030028from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ
Hai Shic7decc22020-08-04 23:53:12 +080029from test.support.import_helper import DirsOnSysPath
30from test.support.os_helper import TESTFN
Berker Peksagce643912015-05-06 06:33:17 +030031from test.support.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000032from test import inspect_fodder as mod
33from test import inspect_fodder2 as mod2
Victor Stinner9def2842016-01-18 12:15:08 +010034from test import support
larryhastings74613a42021-04-29 21:16:28 -070035from test import inspect_stock_annotations
36from test import inspect_stringized_annotations
37from test import inspect_stringized_annotations_2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000038
Yury Selivanovef1e7502014-12-08 16:05:34 -050039from test.test_import import _ready_to_import
40
R. David Murray74b89242009-05-13 17:33:03 +000041
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000042# Functions tested in this suite:
43# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000044# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
45# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
Berker Peksagfa3922c2015-07-31 04:11:29 +030046# getclasstree, getargvalues, formatargspec, formatargvalues,
Christian Heimes7131fd92008-02-19 14:21:46 +000047# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000048
Nick Coghlanf088e5e2008-12-14 11:50:48 +000049# NOTE: There are some additional tests relating to interaction with
50# zipimport in the test_zipimport_support test module.
51
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000052modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000053if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000054 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000055
Christian Heimesa3538eb2007-11-06 11:44:48 +000056# Normalize file names: on Windows, the case of file names of compiled
57# modules depends on the path used to start the python executable.
58modfile = normcase(modfile)
59
60def revise(filename, *args):
61 return (normcase(filename),) + args
62
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000063git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000064
larryhastingsf36ba122018-01-28 11:13:09 -080065
66def signatures_with_lexicographic_keyword_only_parameters():
67 """
68 Yields a whole bunch of functions with only keyword-only parameters,
69 where those parameters are always in lexicographically sorted order.
70 """
71 parameters = ['a', 'bar', 'c', 'delta', 'ephraim', 'magical', 'yoyo', 'z']
72 for i in range(1, 2**len(parameters)):
73 p = []
74 bit = 1
75 for j in range(len(parameters)):
76 if i & (bit << j):
77 p.append(parameters[j])
78 fn_text = "def foo(*, " + ", ".join(p) + "): pass"
79 symbols = {}
80 exec(fn_text, symbols, symbols)
81 yield symbols['foo']
82
83
84def unsorted_keyword_only_parameters_fn(*, throw, out, the, baby, with_,
85 the_, bathwater):
86 pass
87
88unsorted_keyword_only_parameters = 'throw out the baby with_ the_ bathwater'.split()
89
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000090class IsTestBase(unittest.TestCase):
91 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
92 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000093 inspect.ismodule, inspect.istraceback,
Yury Selivanov75445082015-05-11 22:57:16 -040094 inspect.isgenerator, inspect.isgeneratorfunction,
Yury Selivanoveb636452016-09-08 22:01:51 -070095 inspect.iscoroutine, inspect.iscoroutinefunction,
96 inspect.isasyncgen, inspect.isasyncgenfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000097
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000098 def istest(self, predicate, exp):
99 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000100 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000101
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000102 for other in self.predicates - set([predicate]):
Yury Selivanov75445082015-05-11 22:57:16 -0400103 if (predicate == inspect.isgeneratorfunction or \
Yury Selivanoveb636452016-09-08 22:01:51 -0700104 predicate == inspect.isasyncgenfunction or \
Yury Selivanov75445082015-05-11 22:57:16 -0400105 predicate == inspect.iscoroutinefunction) and \
Christian Heimes7131fd92008-02-19 14:21:46 +0000106 other == inspect.isfunction:
107 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000108 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000109
Christian Heimes7131fd92008-02-19 14:21:46 +0000110def generator_function_example(self):
111 for i in range(2):
112 yield i
113
Yury Selivanoveb636452016-09-08 22:01:51 -0700114async def async_generator_function_example(self):
115 async for i in range(2):
116 yield i
117
Yury Selivanov75445082015-05-11 22:57:16 -0400118async def coroutine_function_example(self):
119 return 'spam'
120
121@types.coroutine
122def gen_coroutine_function_example(self):
123 yield
124 return 'spam'
125
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000126class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +0000127
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000128 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200129 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000130 self.istest(inspect.isbuiltin, 'sys.exit')
131 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +0000132 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200133 try:
134 1/0
135 except:
136 tb = sys.exc_info()[2]
137 self.istest(inspect.isframe, 'tb.tb_frame')
138 self.istest(inspect.istraceback, 'tb')
139 if hasattr(types, 'GetSetDescriptorType'):
140 self.istest(inspect.isgetsetdescriptor,
141 'type(tb.tb_frame).f_locals')
142 else:
143 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
144 finally:
145 # Clear traceback and all the frames and local variables hanging to it.
146 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000147 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000148 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000149 self.istest(inspect.ismethod, 'git.argue')
Jeroen Demeyerfcef60f2019-04-02 16:03:42 +0200150 self.istest(inspect.ismethod, 'mod.custom_method')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000151 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000152 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000153 self.istest(inspect.isgenerator, '(x for x in range(2))')
154 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanoveb636452016-09-08 22:01:51 -0700155 self.istest(inspect.isasyncgen,
156 'async_generator_function_example(1)')
157 self.istest(inspect.isasyncgenfunction,
158 'async_generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400159
160 with warnings.catch_warnings():
161 warnings.simplefilter("ignore")
162 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
163 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
164
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000165 if hasattr(types, 'MemberDescriptorType'):
166 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
167 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000168 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000169
Yury Selivanov75445082015-05-11 22:57:16 -0400170 def test_iscoroutine(self):
Pablo Galindo7cd25432018-10-26 12:19:14 +0100171 async_gen_coro = async_generator_function_example(1)
Yury Selivanov75445082015-05-11 22:57:16 -0400172 gen_coro = gen_coroutine_function_example(1)
173 coro = coroutine_function_example(1)
174
Yury Selivanov5376ba92015-06-22 12:19:30 -0400175 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400176 inspect.iscoroutinefunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100177 self.assertFalse(
178 inspect.iscoroutinefunction(
179 functools.partial(functools.partial(
180 gen_coroutine_function_example))))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400181 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400182
183 self.assertTrue(
184 inspect.isgeneratorfunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100185 self.assertTrue(
186 inspect.isgeneratorfunction(
187 functools.partial(functools.partial(
188 gen_coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400189 self.assertTrue(inspect.isgenerator(gen_coro))
190
191 self.assertTrue(
192 inspect.iscoroutinefunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100193 self.assertTrue(
194 inspect.iscoroutinefunction(
195 functools.partial(functools.partial(
196 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400197 self.assertTrue(inspect.iscoroutine(coro))
198
199 self.assertFalse(
200 inspect.isgeneratorfunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100201 self.assertFalse(
202 inspect.isgeneratorfunction(
203 functools.partial(functools.partial(
204 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400205 self.assertFalse(inspect.isgenerator(coro))
206
Pablo Galindo7cd25432018-10-26 12:19:14 +0100207 self.assertTrue(
208 inspect.isasyncgenfunction(async_generator_function_example))
209 self.assertTrue(
210 inspect.isasyncgenfunction(
211 functools.partial(functools.partial(
212 async_generator_function_example))))
213 self.assertTrue(inspect.isasyncgen(async_gen_coro))
214
215 coro.close(); gen_coro.close(); # silence warnings
Yury Selivanov75445082015-05-11 22:57:16 -0400216
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400217 def test_isawaitable(self):
218 def gen(): yield
219 self.assertFalse(inspect.isawaitable(gen()))
220
221 coro = coroutine_function_example(1)
222 gen_coro = gen_coroutine_function_example(1)
223
224 self.assertTrue(inspect.isawaitable(coro))
225 self.assertTrue(inspect.isawaitable(gen_coro))
226
227 class Future:
228 def __await__():
229 pass
230 self.assertTrue(inspect.isawaitable(Future()))
231 self.assertFalse(inspect.isawaitable(Future))
232
233 class NotFuture: pass
234 not_fut = NotFuture()
235 not_fut.__await__ = lambda: None
236 self.assertFalse(inspect.isawaitable(not_fut))
237
238 coro.close(); gen_coro.close() # silence warnings
239
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000240 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000241 self.assertTrue(inspect.isroutine(mod.spam))
242 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000243
Benjamin Petersonc4656002009-01-17 22:41:18 +0000244 def test_isclass(self):
245 self.istest(inspect.isclass, 'mod.StupidGit')
246 self.assertTrue(inspect.isclass(list))
247
248 class CustomGetattr(object):
249 def __getattr__(self, attr):
250 return None
251 self.assertFalse(inspect.isclass(CustomGetattr()))
252
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000253 def test_get_slot_members(self):
254 class C(object):
255 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000256 x = C()
257 x.a = 42
258 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000259 self.assertIn('a', members)
260 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000261
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000262 def test_isabstract(self):
263 from abc import ABCMeta, abstractmethod
264
265 class AbstractClassExample(metaclass=ABCMeta):
266
267 @abstractmethod
268 def foo(self):
269 pass
270
271 class ClassExample(AbstractClassExample):
272 def foo(self):
273 pass
274
275 a = ClassExample()
276
277 # Test general behaviour.
278 self.assertTrue(inspect.isabstract(AbstractClassExample))
279 self.assertFalse(inspect.isabstract(ClassExample))
280 self.assertFalse(inspect.isabstract(a))
281 self.assertFalse(inspect.isabstract(int))
282 self.assertFalse(inspect.isabstract(5))
283
Natefcfe80e2017-04-24 10:06:15 -0700284 def test_isabstract_during_init_subclass(self):
285 from abc import ABCMeta, abstractmethod
286 isabstract_checks = []
287 class AbstractChecker(metaclass=ABCMeta):
288 def __init_subclass__(cls):
289 isabstract_checks.append(inspect.isabstract(cls))
290 class AbstractClassExample(AbstractChecker):
291 @abstractmethod
292 def foo(self):
293 pass
294 class ClassExample(AbstractClassExample):
295 def foo(self):
296 pass
297 self.assertEqual(isabstract_checks, [True, False])
298
299 isabstract_checks.clear()
300 class AbstractChild(AbstractClassExample):
301 pass
302 class AbstractGrandchild(AbstractChild):
303 pass
304 class ConcreteGrandchild(ClassExample):
305 pass
306 self.assertEqual(isabstract_checks, [True, True, False])
307
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000308
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000309class TestInterpreterStack(IsTestBase):
310 def __init__(self, *args, **kwargs):
311 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000312
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000313 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000314
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000315 def test_abuse_done(self):
316 self.istest(inspect.istraceback, 'git.ex[2]')
317 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000318
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000319 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000320 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000321 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000322 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000323 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000324 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000325 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000326 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000327 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000328 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400329 # Test named tuple fields
330 record = mod.st[0]
331 self.assertIs(record.frame, mod.fr)
332 self.assertEqual(record.lineno, 16)
333 self.assertEqual(record.filename, mod.__file__)
334 self.assertEqual(record.function, 'eggs')
335 self.assertIn('inspect.stack()', record.code_context[0])
336 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000337
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000338 def test_trace(self):
339 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000340 self.assertEqual(revise(*git.tr[0][1:]),
341 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
342 self.assertEqual(revise(*git.tr[1][1:]),
343 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
344 self.assertEqual(revise(*git.tr[2][1:]),
345 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000346
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000347 def test_frame(self):
348 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
349 self.assertEqual(args, ['x', 'y'])
350 self.assertEqual(varargs, None)
351 self.assertEqual(varkw, None)
352 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
353 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
354 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000355
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000356 def test_previous_frame(self):
357 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000358 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000359 self.assertEqual(varargs, 'g')
360 self.assertEqual(varkw, 'h')
361 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000362 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000363
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000364class GetSourceBase(unittest.TestCase):
365 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000366 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000367
Yury Selivanov6738b112015-05-16 10:10:21 -0400368 def setUp(self):
Inada Naokifb786922021-04-06 11:18:41 +0900369 with open(inspect.getsourcefile(self.fodderModule), encoding="utf-8") as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000370 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000371
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000372 def sourcerange(self, top, bottom):
373 lines = self.source.split("\n")
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700374 return "\n".join(lines[top-1:bottom]) + ("\n" if bottom else "")
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000375
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000376 def assertSourceEqual(self, obj, top, bottom):
377 self.assertEqual(inspect.getsource(obj),
378 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000379
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700380class SlotUser:
381 'Docstrings for __slots__'
382 __slots__ = {'power': 'measured in kilowatts',
383 'distance': 'measured in kilometers'}
384
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000385class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000386 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000387
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000388 def test_getclasses(self):
389 classes = inspect.getmembers(mod, inspect.isclass)
390 self.assertEqual(classes,
391 [('FesteringGob', mod.FesteringGob),
392 ('MalodorousPervert', mod.MalodorousPervert),
393 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300394 ('StupidGit', mod.StupidGit),
395 ('Tit', mod.MalodorousPervert),
Irit Katriel6e1eec72020-12-04 16:45:38 +0000396 ('WhichComments', mod.WhichComments),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300397 ])
398 tree = inspect.getclasstree([cls[1] for cls in classes])
399 self.assertEqual(tree,
400 [(object, ()),
401 [(mod.ParrotDroppings, (object,)),
402 [(mod.FesteringGob, (mod.MalodorousPervert,
403 mod.ParrotDroppings))
404 ],
405 (mod.StupidGit, (object,)),
406 [(mod.MalodorousPervert, (mod.StupidGit,)),
407 [(mod.FesteringGob, (mod.MalodorousPervert,
408 mod.ParrotDroppings))
409 ]
Irit Katriel6e1eec72020-12-04 16:45:38 +0000410 ],
411 (mod.WhichComments, (object,),)
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300412 ]
413 ])
414 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000415 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000416 [(object, ()),
417 [(mod.ParrotDroppings, (object,)),
418 (mod.StupidGit, (object,)),
419 [(mod.MalodorousPervert, (mod.StupidGit,)),
420 [(mod.FesteringGob, (mod.MalodorousPervert,
421 mod.ParrotDroppings))
422 ]
Irit Katriel6e1eec72020-12-04 16:45:38 +0000423 ],
424 (mod.WhichComments, (object,),)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000425 ]
426 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000427
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000428 def test_getfunctions(self):
429 functions = inspect.getmembers(mod, inspect.isfunction)
430 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300431 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000432 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000433
R. David Murray378c0cf2010-02-24 01:46:21 +0000434 @unittest.skipIf(sys.flags.optimize >= 2,
435 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000436 def test_getdoc(self):
437 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
438 self.assertEqual(inspect.getdoc(mod.StupidGit),
439 'A longer,\n\nindented\n\ndocstring.')
440 self.assertEqual(inspect.getdoc(git.abuse),
441 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700442 self.assertEqual(inspect.getdoc(SlotUser.power),
443 'measured in kilowatts')
444 self.assertEqual(inspect.getdoc(SlotUser.distance),
445 'measured in kilometers')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000446
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300447 @unittest.skipIf(sys.flags.optimize >= 2,
448 "Docstrings are omitted with -O2 and above")
449 def test_getdoc_inherited(self):
Serhiy Storchaka08b47c32020-05-18 20:25:07 +0300450 self.assertEqual(inspect.getdoc(mod.FesteringGob),
451 'A longer,\n\nindented\n\ndocstring.')
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300452 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
453 'Another\n\ndocstring\n\ncontaining\n\ntabs')
454 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
455 'Another\n\ndocstring\n\ncontaining\n\ntabs')
456 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
457 'The automatic gainsaying.')
458
459 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
460 def test_finddoc(self):
461 finddoc = inspect._finddoc
Serhiy Storchaka08b47c32020-05-18 20:25:07 +0300462 self.assertEqual(finddoc(int), int.__doc__)
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300463 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
464 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
465 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
466 self.assertEqual(finddoc(int.real), int.real.__doc__)
467
Georg Brandl0c77a822008-06-10 16:37:50 +0000468 def test_cleandoc(self):
469 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
470 'An\nindented\ndocstring.')
471
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000472 def test_getcomments(self):
473 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
474 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530475 self.assertEqual(inspect.getcomments(mod2.cls160), '# line 159\n')
Marco Buttu3f2155f2017-03-17 09:50:23 +0100476 # If the object source file is not available, return None.
477 co = compile('x=1', '_non_existing_filename.py', 'exec')
478 self.assertIsNone(inspect.getcomments(co))
479 # If the object has been defined in C, return None.
480 self.assertIsNone(inspect.getcomments(list))
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000481
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000482 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000483 # Check actual module
484 self.assertEqual(inspect.getmodule(mod), mod)
485 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000486 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000487 # Check a method (no __module__ attribute, falls back to filename)
488 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
489 # Do it again (check the caching isn't broken)
490 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
491 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000492 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000493 # Check filename override
494 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000495
Berker Peksagff0e3b72017-01-02 06:57:43 +0300496 def test_getframeinfo_get_first_line(self):
497 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
498 self.assertEqual(frame_info.code_context[0], "# line 1\n")
499 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
500
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000501 def test_getsource(self):
502 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200503 self.assertSourceEqual(mod.StupidGit, 21, 51)
504 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000505
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000506 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000507 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
508 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000509 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100510 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000511 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000512 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200513 try:
514 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
515 finally:
516 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000517
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000518 def test_getfile(self):
519 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000520
Philipp Ad407d2a2019-06-08 14:05:46 +0200521 def test_getfile_builtin_module(self):
522 with self.assertRaises(TypeError) as e:
523 inspect.getfile(sys)
524 self.assertTrue(str(e.exception).startswith('<module'))
525
526 def test_getfile_builtin_class(self):
527 with self.assertRaises(TypeError) as e:
528 inspect.getfile(int)
529 self.assertTrue(str(e.exception).startswith('<class'))
530
531 def test_getfile_builtin_function_or_method(self):
532 with self.assertRaises(TypeError) as e_abs:
533 inspect.getfile(abs)
534 self.assertIn('expected, got', str(e_abs.exception))
535 with self.assertRaises(TypeError) as e_append:
536 inspect.getfile(list.append)
537 self.assertIn('expected, got', str(e_append.exception))
538
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500539 def test_getfile_class_without_module(self):
540 class CM(type):
541 @property
542 def __module__(cls):
543 raise AttributeError
544 class C(metaclass=CM):
545 pass
546 with self.assertRaises(TypeError):
547 inspect.getfile(C)
548
Thomas Kluyvere968bc732017-10-24 13:42:36 +0100549 def test_getfile_broken_repr(self):
550 class ErrorRepr:
551 def __repr__(self):
552 raise Exception('xyz')
553 er = ErrorRepr()
554 with self.assertRaises(TypeError):
555 inspect.getfile(er)
556
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000557 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000558 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000559 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000560 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000561 m.__file__ = "<string>" # hopefully not a real filename...
562 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000563 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000564 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000565 del sys.modules[name]
566 inspect.getmodule(compile('a=10','','single'))
567
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500568 def test_proceed_with_fake_filename(self):
569 '''doctest monkeypatches linecache to enable inspection'''
570 fn, source = '<test>', 'def x(): pass\n'
571 getlines = linecache.getlines
572 def monkey(filename, module_globals=None):
573 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300574 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500575 else:
576 return getlines(filename, module_globals)
577 linecache.getlines = monkey
578 try:
579 ns = {}
580 exec(compile(source, fn, 'single'), ns)
581 inspect.getsource(ns["x"])
582 finally:
583 linecache.getlines = getlines
584
Antoine Pitroua8723a02015-04-15 00:41:29 +0200585 def test_getsource_on_code_object(self):
586 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
587
Miss Islington (bot)f468ede2021-07-30 10:46:42 -0700588class TestGetsourceInteractive(unittest.TestCase):
589 def tearDown(self):
590 mod.ParrotDroppings.__module__ = mod
591 sys.modules['__main__'] = self.main
592
593 def test_getclasses_interactive(self):
594 self.main = sys.modules['__main__']
595 class MockModule:
596 __file__ = None
597 sys.modules['__main__'] = MockModule
598 mod.ParrotDroppings.__module__ = '__main__'
599 with self.assertRaisesRegex(OSError, 'source code not available') as e:
600 inspect.getsource(mod.ParrotDroppings)
601
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700602class TestGettingSourceOfToplevelFrames(GetSourceBase):
603 fodderModule = mod
604
605 def test_range_toplevel_frame(self):
606 self.maxDiff = None
607 self.assertSourceEqual(mod.currentframe, 1, None)
608
609 def test_range_traceback_toplevel_frame(self):
610 self.assertSourceEqual(mod.tb, 1, None)
611
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000612class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000613 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000614
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000615 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000616 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000617
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000618 def test_replacing_decorator(self):
619 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000620
Yury Selivanov081bbf62014-09-26 17:34:54 -0400621 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200622 self.assertSourceEqual(mod2.real, 130, 132)
623
624 def test_decorator_with_lambda(self):
625 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400626
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000627class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000628 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000629 def test_oneline_lambda(self):
630 # Test inspect.getsource with a one-line lambda function.
631 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000632
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000633 def test_threeline_lambda(self):
634 # Test inspect.getsource with a three-line lambda function,
635 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000636 self.assertSourceEqual(mod2.tll, 28, 30)
637
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000638 def test_twoline_indented_lambda(self):
639 # Test inspect.getsource with a two-line lambda function,
640 # where the second line _is_ indented.
641 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000642
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000643 def test_onelinefunc(self):
644 # Test inspect.getsource with a regular one-line function.
645 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000646
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000647 def test_manyargs(self):
648 # Test inspect.getsource with a regular function where
649 # the arguments are on two lines and _not_ indented and
650 # the body on the second line with the last arguments.
651 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000652
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000653 def test_twolinefunc(self):
654 # Test inspect.getsource with a regular function where
655 # the body is on two lines, following the argument list and
656 # continued on the next line by a \\.
657 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000658
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000659 def test_lambda_in_list(self):
660 # Test inspect.getsource with a one-line lambda function
661 # defined in a list, indented.
662 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000663
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000664 def test_anonymous(self):
665 # Test inspect.getsource with a lambda function defined
666 # as argument to another function.
667 self.assertSourceEqual(mod2.anonymous, 55, 55)
668
Irit Katriel6e1eec72020-12-04 16:45:38 +0000669class TestBlockComments(GetSourceBase):
670 fodderModule = mod
671
672 def test_toplevel_class(self):
673 self.assertSourceEqual(mod.WhichComments, 96, 114)
674
675 def test_class_method(self):
676 self.assertSourceEqual(mod.WhichComments.f, 99, 104)
677
678 def test_class_async_method(self):
679 self.assertSourceEqual(mod.WhichComments.asyncf, 109, 112)
680
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000681class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000682 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000683
684 def test_with_comment(self):
685 self.assertSourceEqual(mod2.with_comment, 58, 59)
686
687 def test_multiline_sig(self):
688 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
689
Armin Rigodd5c0232005-09-25 11:45:45 +0000690 def test_nested_class(self):
691 self.assertSourceEqual(mod2.func69().func71, 71, 72)
692
693 def test_one_liner_followed_by_non_name(self):
694 self.assertSourceEqual(mod2.func77, 77, 77)
695
696 def test_one_liner_dedent_non_name(self):
697 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
698
699 def test_with_comment_instead_of_docstring(self):
700 self.assertSourceEqual(mod2.func88, 88, 90)
701
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000702 def test_method_in_dynamic_class(self):
703 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
704
R David Murray32562d72014-10-03 11:15:38 -0400705 # This should not skip for CPython, but might on a repackaged python where
706 # unicodedata is not an external module, or on pypy.
707 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
708 unicodedata.__file__.endswith('.py'),
709 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000710 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200711 self.assertRaises(OSError, inspect.getsource, unicodedata)
712 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000713
R. David Murraya1b37402010-06-17 02:04:29 +0000714 def test_findsource_code_in_linecache(self):
715 lines = ["x=1"]
716 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200717 self.assertRaises(OSError, inspect.findsource, co)
718 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000719 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200720 try:
721 self.assertEqual(inspect.findsource(co), (lines,0))
722 self.assertEqual(inspect.getsource(co), lines[0])
723 finally:
724 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000725
Ezio Melotti1b145922013-03-30 05:17:24 +0200726 def test_findsource_without_filename(self):
727 for fname in ['', '<string>']:
728 co = compile('x=1', fname, "exec")
729 self.assertRaises(IOError, inspect.findsource, co)
730 self.assertRaises(IOError, inspect.getsource, co)
731
Irit Katriel2e0760b2020-12-04 21:22:03 +0000732 def test_findsource_with_out_of_bounds_lineno(self):
733 mod_len = len(inspect.getsource(mod))
734 src = '\n' * 2* mod_len + "def f(): pass"
735 co = compile(src, mod.__file__, "exec")
736 g, l = {}, {}
737 eval(co, g, l)
738 func = l['f']
739 self.assertEqual(func.__code__.co_firstlineno, 1+2*mod_len)
740 with self.assertRaisesRegex(IOError, "lineno is out of bounds"):
741 inspect.findsource(func)
742
Antoine Pitroua8723a02015-04-15 00:41:29 +0200743 def test_getsource_on_method(self):
744 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
745
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300746 def test_nested_func(self):
747 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
748
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530749 def test_class_definition_in_multiline_string_definition(self):
750 self.assertSourceEqual(mod2.cls149, 149, 152)
751
752 def test_class_definition_in_multiline_comment(self):
753 self.assertSourceEqual(mod2.cls160, 160, 163)
754
755 def test_nested_class_definition_indented_string(self):
756 self.assertSourceEqual(mod2.cls173.cls175, 175, 176)
757
758 def test_nested_class_definition(self):
759 self.assertSourceEqual(mod2.cls183, 183, 188)
760 self.assertSourceEqual(mod2.cls183.cls185, 185, 188)
761
762 def test_class_decorator(self):
763 self.assertSourceEqual(mod2.cls196, 194, 201)
764 self.assertSourceEqual(mod2.cls196.cls200, 198, 201)
765
766 def test_class_inside_conditional(self):
767 self.assertSourceEqual(mod2.cls238, 238, 240)
768 self.assertSourceEqual(mod2.cls238.cls239, 239, 240)
769
770 def test_multiple_children_classes(self):
771 self.assertSourceEqual(mod2.cls203, 203, 209)
772 self.assertSourceEqual(mod2.cls203.cls204, 204, 206)
773 self.assertSourceEqual(mod2.cls203.cls204.cls205, 205, 206)
774 self.assertSourceEqual(mod2.cls203.cls207, 207, 209)
775 self.assertSourceEqual(mod2.cls203.cls207.cls205, 208, 209)
776
777 def test_nested_class_definition_inside_function(self):
778 self.assertSourceEqual(mod2.func212(), 213, 214)
779 self.assertSourceEqual(mod2.cls213, 218, 222)
780 self.assertSourceEqual(mod2.cls213().func219(), 220, 221)
781
782 def test_nested_class_definition_inside_async_function(self):
783 import asyncio
784 self.addCleanup(asyncio.set_event_loop_policy, None)
785 self.assertSourceEqual(asyncio.run(mod2.func225()), 226, 227)
786 self.assertSourceEqual(mod2.cls226, 231, 235)
787 self.assertSourceEqual(asyncio.run(mod2.cls226().func232()), 233, 234)
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300788
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000789class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400790 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000791 self.tempdir = TESTFN + '_dir'
792 os.mkdir(self.tempdir)
Inada Naokifb786922021-04-06 11:18:41 +0900793 with open(os.path.join(self.tempdir, 'inspect_fodder3%spy' % os.extsep),
794 'w', encoding='utf-8') as f:
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000795 f.write("class X:\n pass # No EOL")
796 with DirsOnSysPath(self.tempdir):
797 import inspect_fodder3 as mod3
798 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400799 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000800
801 def tearDown(self):
802 shutil.rmtree(self.tempdir)
803
804 def test_class(self):
805 self.assertSourceEqual(self.fodderModule.X, 1, 2)
806
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100807
808class _BrokenDataDescriptor(object):
809 """
810 A broken data descriptor. See bug #1785.
811 """
812 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700813 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100814
815 def __set__(*args):
816 raise RuntimeError
817
818 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700819 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100820
821
822class _BrokenMethodDescriptor(object):
823 """
824 A broken method descriptor. See bug #1785.
825 """
826 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700827 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100828
829 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700830 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100831
832
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000833# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000834def attrs_wo_objs(cls):
835 return [t[:3] for t in inspect.classify_class_attrs(cls)]
836
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100837
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000838class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000839 def test_newstyle_mro(self):
840 # The same w/ new-class MRO.
841 class A(object): pass
842 class B(A): pass
843 class C(A): pass
844 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000845
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000846 expected = (D, B, C, A, object)
847 got = inspect.getmro(D)
848 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000849
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500850 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
851 varkw_e=None, defaults_e=None, formatted=None):
Xtreak6d0b7472019-05-30 17:31:39 +0530852 with self.assertWarns(DeprecationWarning):
853 args, varargs, varkw, defaults = inspect.getargspec(routine)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500854 self.assertEqual(args, args_e)
855 self.assertEqual(varargs, varargs_e)
856 self.assertEqual(varkw, varkw_e)
857 self.assertEqual(defaults, defaults_e)
858 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530859 with self.assertWarns(DeprecationWarning):
860 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
861 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500862
Christian Heimes3795b532007-11-08 13:48:53 +0000863 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
864 varkw_e=None, defaults_e=None,
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100865 posonlyargs_e=[], kwonlyargs_e=[],
866 kwonlydefaults_e=None,
Christian Heimes3795b532007-11-08 13:48:53 +0000867 ann_e={}, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100868 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
869 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000870 self.assertEqual(args, args_e)
871 self.assertEqual(varargs, varargs_e)
872 self.assertEqual(varkw, varkw_e)
873 self.assertEqual(defaults, defaults_e)
874 self.assertEqual(kwonlyargs, kwonlyargs_e)
875 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
876 self.assertEqual(ann, ann_e)
877 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530878 with self.assertWarns(DeprecationWarning):
879 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
880 kwonlyargs, kwonlydefaults, ann),
881 formatted)
Christian Heimes3795b532007-11-08 13:48:53 +0000882
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500883 def test_getargspec(self):
884 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
885
Pablo Galindod5d2b452019-04-30 02:01:14 +0100886 self.assertArgSpecEquals(mod.spam,
887 ['a', 'b', 'c', 'd', 'e', 'f'],
888 'g', 'h', (3, 4, 5),
889 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500890
891 self.assertRaises(ValueError, self.assertArgSpecEquals,
892 mod2.keyworded, [])
893
894 self.assertRaises(ValueError, self.assertArgSpecEquals,
895 mod2.annotated, [])
896 self.assertRaises(ValueError, self.assertArgSpecEquals,
897 mod2.keyword_only_arg, [])
898
899
Christian Heimes3795b532007-11-08 13:48:53 +0000900 def test_getfullargspec(self):
901 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
902 kwonlyargs_e=['arg2'],
903 kwonlydefaults_e={'arg2':1},
904 formatted='(*arg1, arg2=1)')
905
906 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000907 ann_e={'arg1' : list},
Pablo Galindob0544ba2021-04-21 12:41:19 +0100908 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000909 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
910 kwonlyargs_e=['arg'],
911 formatted='(*, arg)')
912
Pablo Galindod5d2b452019-04-30 02:01:14 +0100913 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100914 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100915 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100916
917 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100918 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100919 varargs_e='args',
920 varkw_e='kwargs',
921 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100922 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100923
Pablo Galindod5d2b452019-04-30 02:01:14 +0100924 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100925 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100926 kwonlyargs_e=['e', 'f'],
927 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100928 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100929
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500930 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500931 # Issue 20684: low level introspection API must ignore __wrapped__
932 @functools.wraps(mod.spam)
933 def ham(x, y):
934 pass
935 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500936 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500937 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
938 self.assertFullArgSpecEquals(functools.partial(ham),
939 ['x', 'y'], formatted='(x, y)')
940 # Other variants
941 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500942 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
943 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500944 class C:
945 @functools.wraps(mod.spam)
946 def ham(self, x, y):
947 pass
948 pham = functools.partialmethod(ham)
949 @functools.wraps(mod.spam)
950 def __call__(self, x, y):
951 pass
952 check_method(C())
953 check_method(C.ham)
954 check_method(C().ham)
955 check_method(C.pham)
956 check_method(C().pham)
957
958 class C_new:
959 @functools.wraps(mod.spam)
960 def __new__(self, x, y):
961 pass
962 check_method(C_new)
963
964 class C_init:
965 @functools.wraps(mod.spam)
966 def __init__(self, x, y):
967 pass
968 check_method(C_init)
969
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500970 def test_getfullargspec_signature_attr(self):
971 def test():
972 pass
973 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
974 test.__signature__ = inspect.Signature(parameters=(spam_param,))
975
Pablo Galindod5d2b452019-04-30 02:01:14 +0100976 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500977
Yury Selivanov4cb93912014-01-29 11:54:12 -0500978 def test_getfullargspec_signature_annos(self):
979 def test(a:'spam') -> 'ham': pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100980 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500981 self.assertEqual(test.__annotations__, spec.annotations)
982
983 def test(): pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100984 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500985 self.assertEqual(test.__annotations__, spec.annotations)
986
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500987 @unittest.skipIf(MISSING_C_DOCSTRINGS,
988 "Signature information for builtins requires docstrings")
989 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100990 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
991 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500992
Pablo Galindod5d2b452019-04-30 02:01:14 +0100993 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
994 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500995
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500996 self.assertFullArgSpecEquals(
997 os.stat,
998 args_e=['path'],
999 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
1000 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
1001 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
1002
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001003 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001004 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1005 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +08001006 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001007 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001008 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindoaee19f52019-05-16 21:08:15 +01001009 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001010 self.assertEqual(spec.defaults[0], 'avocado')
1011
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001012 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001013 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1014 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +08001015 def test_getfullargspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001016 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001017 builtin = _testcapi.docstring_no_signature
Pablo Galindoaee19f52019-05-16 21:08:15 +01001018 with self.assertRaises(TypeError):
1019 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +00001020
larryhastingsf36ba122018-01-28 11:13:09 -08001021 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
1022 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindoaee19f52019-05-16 21:08:15 +01001023 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -08001024 l = list(signature.kwonlyargs)
1025 sorted_l = sorted(l)
1026 self.assertTrue(l)
1027 self.assertEqual(l, sorted_l)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001028 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -08001029 l = list(signature.kwonlyargs)
1030 self.assertEqual(l, unsorted_keyword_only_parameters)
1031
Yury Selivanov37dc2b22016-01-11 15:15:01 -05001032 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001033 class A(object):
1034 def m(self):
1035 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -05001036 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +00001037
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001038 def test_classify_newstyle(self):
1039 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +00001040
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001041 def s(): pass
1042 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +00001043
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001044 def c(cls): pass
1045 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +00001046
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001047 def getp(self): pass
1048 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +00001049
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001050 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001051
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001052 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001053
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001054 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +00001055
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001056 dd = _BrokenDataDescriptor()
1057 md = _BrokenMethodDescriptor()
1058
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001059 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001060
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001061 self.assertIn(('__new__', 'static method', object), attrs,
1062 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001063 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
1064
Benjamin Peterson577473f2010-01-19 00:09:57 +00001065 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1066 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1067 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001068 self.assertIn(('m', 'method', A), attrs,
1069 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001070 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1071 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001072 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1073 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001074
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001075 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001076
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001077 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001078
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001079 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001080 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1081 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1082 self.assertIn(('p', 'property', A), attrs, 'missing property')
1083 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1084 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1085 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001086 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1087 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001088
1089
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001090 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001091
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001092 def m(self): pass
1093 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001094
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001095 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001096 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1097 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1098 self.assertIn(('p', 'property', A), attrs, 'missing property')
1099 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
1100 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1101 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001102 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1103 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001104
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001105 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001106
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001107 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001108
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001109 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001110 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1111 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1112 self.assertIn(('p', 'property', A), attrs, 'missing property')
1113 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1114 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1115 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001116 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1117 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1118
1119 def test_classify_builtin_types(self):
1120 # Simple sanity check that all built-in types can have their
1121 # attributes classified.
1122 for name in dir(__builtins__):
1123 builtin = getattr(__builtins__, name)
1124 if isinstance(builtin, type):
1125 inspect.classify_class_attrs(builtin)
1126
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001127 attrs = attrs_wo_objs(bool)
1128 self.assertIn(('__new__', 'static method', bool), attrs,
1129 'missing __new__')
1130 self.assertIn(('from_bytes', 'class method', int), attrs,
1131 'missing class method')
1132 self.assertIn(('to_bytes', 'method', int), attrs,
1133 'missing plain method')
1134 self.assertIn(('__add__', 'method', int), attrs,
1135 'missing plain method')
1136 self.assertIn(('__and__', 'method', bool), attrs,
1137 'missing plain method')
1138
Ethan Furman63c141c2013-10-18 00:27:39 -07001139 def test_classify_DynamicClassAttribute(self):
1140 class Meta(type):
1141 def __getattr__(self, name):
1142 if name == 'ham':
1143 return 'spam'
1144 return super().__getattr__(name)
1145 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001146 @types.DynamicClassAttribute
1147 def ham(self):
1148 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001149 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1150 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001151 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001152 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1153
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001154 def test_classify_overrides_bool(self):
1155 class NoBool(object):
1156 def __eq__(self, other):
1157 return NoBool()
1158
1159 def __bool__(self):
1160 raise NotImplementedError(
1161 "This object does not specify a boolean value")
1162
1163 class HasNB(object):
1164 dd = NoBool()
1165
1166 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1167 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1168
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001169 def test_classify_metaclass_class_attribute(self):
1170 class Meta(type):
1171 fish = 'slap'
1172 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001173 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001174 class Class(metaclass=Meta):
1175 pass
1176 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1177 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1178
Ethan Furman63c141c2013-10-18 00:27:39 -07001179 def test_classify_VirtualAttribute(self):
1180 class Meta(type):
1181 def __dir__(cls):
1182 return ['__class__', '__module__', '__name__', 'BOOM']
1183 def __getattr__(self, name):
1184 if name =='BOOM':
1185 return 42
1186 return super().__getattr(name)
1187 class Class(metaclass=Meta):
1188 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001189 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001190 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1191
1192 def test_classify_VirtualAttribute_multi_classes(self):
1193 class Meta1(type):
1194 def __dir__(cls):
1195 return ['__class__', '__module__', '__name__', 'one']
1196 def __getattr__(self, name):
1197 if name =='one':
1198 return 1
1199 return super().__getattr__(name)
1200 class Meta2(type):
1201 def __dir__(cls):
1202 return ['__class__', '__module__', '__name__', 'two']
1203 def __getattr__(self, name):
1204 if name =='two':
1205 return 2
1206 return super().__getattr__(name)
1207 class Meta3(Meta1, Meta2):
1208 def __dir__(cls):
1209 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1210 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1211 def __getattr__(self, name):
1212 if name =='three':
1213 return 3
1214 return super().__getattr__(name)
1215 class Class1(metaclass=Meta1):
1216 pass
1217 class Class2(Class1, metaclass=Meta3):
1218 pass
1219
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001220 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1221 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1222 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001223 cca = inspect.classify_class_attrs(Class2)
1224 for sf in (should_find1, should_find2, should_find3):
1225 self.assertIn(sf, cca)
1226
1227 def test_classify_class_attrs_with_buggy_dir(self):
1228 class M(type):
1229 def __dir__(cls):
1230 return ['__class__', '__name__', 'missing']
1231 class C(metaclass=M):
1232 pass
1233 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1234 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001235
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001236 def test_getmembers_descriptors(self):
1237 class A(object):
1238 dd = _BrokenDataDescriptor()
1239 md = _BrokenMethodDescriptor()
1240
1241 def pred_wrapper(pred):
1242 # A quick'n'dirty way to discard standard attributes of new-style
1243 # classes.
1244 class Empty(object):
1245 pass
1246 def wrapped(x):
1247 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1248 return False
1249 return pred(x)
1250 return wrapped
1251
1252 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1253 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1254
1255 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1256 [('md', A.__dict__['md'])])
1257 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1258 [('dd', A.__dict__['dd'])])
1259
1260 class B(A):
1261 pass
1262
1263 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1264 [('md', A.__dict__['md'])])
1265 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1266 [('dd', A.__dict__['dd'])])
1267
Antoine Pitrou0c603812012-01-18 17:40:18 +01001268 def test_getmembers_method(self):
1269 class B:
1270 def f(self):
1271 pass
1272
1273 self.assertIn(('f', B.f), inspect.getmembers(B))
1274 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1275 b = B()
1276 self.assertIn(('f', b.f), inspect.getmembers(b))
1277 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1278
Ethan Furmane03ea372013-09-25 07:14:41 -07001279 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001280 class M(type):
1281 def __getattr__(cls, name):
1282 if name == 'eggs':
1283 return 'scrambled'
1284 return super().__getattr__(name)
1285 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001286 @types.DynamicClassAttribute
1287 def eggs(self):
1288 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001289 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1290 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1291
1292 def test_getmembers_with_buggy_dir(self):
1293 class M(type):
1294 def __dir__(cls):
1295 return ['__class__', '__name__', 'missing']
1296 class C(metaclass=M):
1297 pass
1298 attrs = [a[0] for a in inspect.getmembers(C)]
1299 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001300
larryhastings74613a42021-04-29 21:16:28 -07001301 def test_get_annotations_with_stock_annotations(self):
1302 def foo(a:int, b:str): pass
1303 self.assertEqual(inspect.get_annotations(foo), {'a': int, 'b': str})
1304
1305 foo.__annotations__ = {'a': 'foo', 'b':'str'}
1306 self.assertEqual(inspect.get_annotations(foo), {'a': 'foo', 'b': 'str'})
1307
1308 self.assertEqual(inspect.get_annotations(foo, eval_str=True, locals=locals()), {'a': foo, 'b': str})
1309 self.assertEqual(inspect.get_annotations(foo, eval_str=True, globals=locals()), {'a': foo, 'b': str})
1310
1311 isa = inspect_stock_annotations
1312 self.assertEqual(inspect.get_annotations(isa), {'a': int, 'b': str})
1313 self.assertEqual(inspect.get_annotations(isa.MyClass), {'a': int, 'b': str})
1314 self.assertEqual(inspect.get_annotations(isa.function), {'a': int, 'b': str, 'return': isa.MyClass})
1315 self.assertEqual(inspect.get_annotations(isa.function2), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1316 self.assertEqual(inspect.get_annotations(isa.function3), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1317 self.assertEqual(inspect.get_annotations(inspect), {}) # inspect module has no annotations
1318 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass), {})
1319 self.assertEqual(inspect.get_annotations(isa.unannotated_function), {})
1320
1321 self.assertEqual(inspect.get_annotations(isa, eval_str=True), {'a': int, 'b': str})
1322 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=True), {'a': int, 'b': str})
1323 self.assertEqual(inspect.get_annotations(isa.function, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1324 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=True), {'a': int, 'b': str, 'c': isa.MyClass, 'return': isa.MyClass})
1325 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=True), {'a': int, 'b': str, 'c': isa.MyClass})
1326 self.assertEqual(inspect.get_annotations(inspect, eval_str=True), {})
1327 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=True), {})
1328 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=True), {})
1329
1330 self.assertEqual(inspect.get_annotations(isa, eval_str=False), {'a': int, 'b': str})
1331 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=False), {'a': int, 'b': str})
1332 self.assertEqual(inspect.get_annotations(isa.function, eval_str=False), {'a': int, 'b': str, 'return': isa.MyClass})
1333 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=False), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1334 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=False), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1335 self.assertEqual(inspect.get_annotations(inspect, eval_str=False), {})
1336 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=False), {})
1337 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=False), {})
1338
1339 def times_three(fn):
1340 @functools.wraps(fn)
1341 def wrapper(a, b):
1342 return fn(a*3, b*3)
1343 return wrapper
1344
1345 wrapped = times_three(isa.function)
1346 self.assertEqual(wrapped(1, 'x'), isa.MyClass(3, 'xxx'))
1347 self.assertIsNot(wrapped.__globals__, isa.function.__globals__)
1348 self.assertEqual(inspect.get_annotations(wrapped), {'a': int, 'b': str, 'return': isa.MyClass})
1349 self.assertEqual(inspect.get_annotations(wrapped, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1350 self.assertEqual(inspect.get_annotations(wrapped, eval_str=False), {'a': int, 'b': str, 'return': isa.MyClass})
1351
1352 def test_get_annotations_with_stringized_annotations(self):
1353 isa = inspect_stringized_annotations
1354 self.assertEqual(inspect.get_annotations(isa), {'a': 'int', 'b': 'str'})
1355 self.assertEqual(inspect.get_annotations(isa.MyClass), {'a': 'int', 'b': 'str'})
1356 self.assertEqual(inspect.get_annotations(isa.function), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1357 self.assertEqual(inspect.get_annotations(isa.function2), {'a': 'int', 'b': "'str'", 'c': 'MyClass', 'return': 'MyClass'})
1358 self.assertEqual(inspect.get_annotations(isa.function3), {'a': "'int'", 'b': "'str'", 'c': "'MyClass'"})
1359 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass), {})
1360 self.assertEqual(inspect.get_annotations(isa.unannotated_function), {})
1361
1362 self.assertEqual(inspect.get_annotations(isa, eval_str=True), {'a': int, 'b': str})
1363 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=True), {'a': int, 'b': str})
1364 self.assertEqual(inspect.get_annotations(isa.function, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1365 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=True), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1366 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=True), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1367 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=True), {})
1368 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=True), {})
1369
1370 self.assertEqual(inspect.get_annotations(isa, eval_str=False), {'a': 'int', 'b': 'str'})
1371 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=False), {'a': 'int', 'b': 'str'})
1372 self.assertEqual(inspect.get_annotations(isa.function, eval_str=False), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1373 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=False), {'a': 'int', 'b': "'str'", 'c': 'MyClass', 'return': 'MyClass'})
1374 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=False), {'a': "'int'", 'b': "'str'", 'c': "'MyClass'"})
1375 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=False), {})
1376 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=False), {})
1377
1378 isa2 = inspect_stringized_annotations_2
1379 self.assertEqual(inspect.get_annotations(isa2), {})
1380 self.assertEqual(inspect.get_annotations(isa2, eval_str=True), {})
1381 self.assertEqual(inspect.get_annotations(isa2, eval_str=False), {})
1382
1383 def times_three(fn):
1384 @functools.wraps(fn)
1385 def wrapper(a, b):
1386 return fn(a*3, b*3)
1387 return wrapper
1388
1389 wrapped = times_three(isa.function)
1390 self.assertEqual(wrapped(1, 'x'), isa.MyClass(3, 'xxx'))
1391 self.assertIsNot(wrapped.__globals__, isa.function.__globals__)
1392 self.assertEqual(inspect.get_annotations(wrapped), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1393 self.assertEqual(inspect.get_annotations(wrapped, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1394 self.assertEqual(inspect.get_annotations(wrapped, eval_str=False), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1395
1396 # test that local namespace lookups work
1397 self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations), {'x': 'mytype'})
1398 self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations, eval_str=True), {'x': int})
1399
1400
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001401class TestIsDataDescriptor(unittest.TestCase):
1402
1403 def test_custom_descriptors(self):
1404 class NonDataDescriptor:
1405 def __get__(self, value, type=None): pass
1406 class DataDescriptor0:
1407 def __set__(self, name, value): pass
1408 class DataDescriptor1:
1409 def __delete__(self, name): pass
1410 class DataDescriptor2:
1411 __set__ = None
1412 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1413 'class with only __get__ not a data descriptor')
1414 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1415 'class with __set__ is a data descriptor')
1416 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1417 'class with __delete__ is a data descriptor')
1418 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1419 'class with __set__ = None is a data descriptor')
1420
1421 def test_slot(self):
1422 class Slotted:
1423 __slots__ = 'foo',
1424 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1425 'a slot is a data descriptor')
1426
1427 def test_property(self):
1428 class Propertied:
1429 @property
1430 def a_property(self):
1431 pass
1432 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1433 'a property is a data descriptor')
1434
1435 def test_functions(self):
1436 class Test(object):
1437 def instance_method(self): pass
1438 @classmethod
1439 def class_method(cls): pass
1440 @staticmethod
1441 def static_method(): pass
1442 def function():
1443 pass
1444 a_lambda = lambda: None
1445 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1446 'a instance method is not a data descriptor')
1447 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1448 'a class method is not a data descriptor')
1449 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1450 'a static method is not a data descriptor')
1451 self.assertFalse(inspect.isdatadescriptor(function),
1452 'a function is not a data descriptor')
1453 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1454 'a lambda is not a data descriptor')
1455
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001456
Nick Coghlan2f92e542012-06-23 19:39:55 +10001457_global_ref = object()
1458class TestGetClosureVars(unittest.TestCase):
1459
1460 def test_name_resolution(self):
1461 # Basic test of the 4 different resolution mechanisms
1462 def f(nonlocal_ref):
1463 def g(local_ref):
1464 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1465 return g
1466 _arg = object()
1467 nonlocal_vars = {"nonlocal_ref": _arg}
1468 global_vars = {"_global_ref": _global_ref}
1469 builtin_vars = {"print": print}
1470 unbound_names = {"unbound_ref"}
1471 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1472 builtin_vars, unbound_names)
1473 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1474
1475 def test_generator_closure(self):
1476 def f(nonlocal_ref):
1477 def g(local_ref):
1478 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1479 yield
1480 return g
1481 _arg = object()
1482 nonlocal_vars = {"nonlocal_ref": _arg}
1483 global_vars = {"_global_ref": _global_ref}
1484 builtin_vars = {"print": print}
1485 unbound_names = {"unbound_ref"}
1486 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1487 builtin_vars, unbound_names)
1488 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1489
1490 def test_method_closure(self):
1491 class C:
1492 def f(self, nonlocal_ref):
1493 def g(local_ref):
1494 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1495 return g
1496 _arg = object()
1497 nonlocal_vars = {"nonlocal_ref": _arg}
1498 global_vars = {"_global_ref": _global_ref}
1499 builtin_vars = {"print": print}
1500 unbound_names = {"unbound_ref"}
1501 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1502 builtin_vars, unbound_names)
1503 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1504
1505 def test_nonlocal_vars(self):
1506 # More complex tests of nonlocal resolution
1507 def _nonlocal_vars(f):
1508 return inspect.getclosurevars(f).nonlocals
1509
1510 def make_adder(x):
1511 def add(y):
1512 return x + y
1513 return add
1514
1515 def curry(func, arg1):
1516 return lambda arg2: func(arg1, arg2)
1517
1518 def less_than(a, b):
1519 return a < b
1520
1521 # The infamous Y combinator.
1522 def Y(le):
1523 def g(f):
1524 return le(lambda x: f(f)(x))
1525 Y.g_ref = g
1526 return g(g)
1527
1528 def check_y_combinator(func):
1529 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1530
1531 inc = make_adder(1)
1532 add_two = make_adder(2)
1533 greater_than_five = curry(less_than, 5)
1534
1535 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1536 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1537 self.assertEqual(_nonlocal_vars(greater_than_five),
1538 {'arg1': 5, 'func': less_than})
1539 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1540 {'x': 3})
1541 Y(check_y_combinator)
1542
1543 def test_getclosurevars_empty(self):
1544 def foo(): pass
1545 _empty = inspect.ClosureVars({}, {}, {}, set())
1546 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1547 self.assertEqual(inspect.getclosurevars(foo), _empty)
1548
1549 def test_getclosurevars_error(self):
1550 class T: pass
1551 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1552 self.assertRaises(TypeError, inspect.getclosurevars, list)
1553 self.assertRaises(TypeError, inspect.getclosurevars, {})
1554
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001555 def _private_globals(self):
1556 code = """def f(): print(path)"""
1557 ns = {}
1558 exec(code, ns)
1559 return ns["f"], ns
1560
1561 def test_builtins_fallback(self):
1562 f, ns = self._private_globals()
1563 ns.pop("__builtins__", None)
1564 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1565 self.assertEqual(inspect.getclosurevars(f), expected)
1566
1567 def test_builtins_as_dict(self):
1568 f, ns = self._private_globals()
1569 ns["__builtins__"] = {"path":1}
1570 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1571 self.assertEqual(inspect.getclosurevars(f), expected)
1572
1573 def test_builtins_as_module(self):
1574 f, ns = self._private_globals()
1575 ns["__builtins__"] = os
1576 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1577 self.assertEqual(inspect.getclosurevars(f), expected)
1578
Nick Coghlan2f92e542012-06-23 19:39:55 +10001579
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001580class TestGetcallargsFunctions(unittest.TestCase):
1581
1582 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1583 locs = dict(locs or {}, func=func)
1584 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001585 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1586 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001587 self.assertEqual(r1, r2)
1588
1589 def assertEqualException(self, func, call_param_string, locs=None):
1590 locs = dict(locs or {}, func=func)
1591 try:
1592 eval('func(%s)' % call_param_string, None, locs)
1593 except Exception as e:
1594 ex1 = e
1595 else:
1596 self.fail('Exception not raised')
1597 try:
Pablo Galindoaee19f52019-05-16 21:08:15 +01001598 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1599 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001600 except Exception as e:
1601 ex2 = e
1602 else:
1603 self.fail('Exception not raised')
1604 self.assertIs(type(ex1), type(ex2))
1605 self.assertEqual(str(ex1), str(ex2))
1606 del ex1, ex2
1607
1608 def makeCallable(self, signature):
1609 """Create a function that returns its locals()"""
1610 code = "lambda %s: locals()"
1611 return eval(code % signature)
1612
1613 def test_plain(self):
1614 f = self.makeCallable('a, b=1')
1615 self.assertEqualCallArgs(f, '2')
1616 self.assertEqualCallArgs(f, '2, 3')
1617 self.assertEqualCallArgs(f, 'a=2')
1618 self.assertEqualCallArgs(f, 'b=3, a=2')
1619 self.assertEqualCallArgs(f, '2, b=3')
1620 # expand *iterable / **mapping
1621 self.assertEqualCallArgs(f, '*(2,)')
1622 self.assertEqualCallArgs(f, '*[2]')
1623 self.assertEqualCallArgs(f, '*(2, 3)')
1624 self.assertEqualCallArgs(f, '*[2, 3]')
1625 self.assertEqualCallArgs(f, '**{"a":2}')
1626 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1627 self.assertEqualCallArgs(f, '2, **{"b":3}')
1628 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1629 # expand UserList / UserDict
1630 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1631 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1632 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1633 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1634 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1635
1636 def test_varargs(self):
1637 f = self.makeCallable('a, b=1, *c')
1638 self.assertEqualCallArgs(f, '2')
1639 self.assertEqualCallArgs(f, '2, 3')
1640 self.assertEqualCallArgs(f, '2, 3, 4')
1641 self.assertEqualCallArgs(f, '*(2,3,4)')
1642 self.assertEqualCallArgs(f, '2, *[3,4]')
1643 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1644
1645 def test_varkw(self):
1646 f = self.makeCallable('a, b=1, **c')
1647 self.assertEqualCallArgs(f, 'a=2')
1648 self.assertEqualCallArgs(f, '2, b=3, c=4')
1649 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1650 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1651 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1652 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1653 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1654 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1655 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1656
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001657 def test_varkw_only(self):
1658 # issue11256:
1659 f = self.makeCallable('**c')
1660 self.assertEqualCallArgs(f, '')
1661 self.assertEqualCallArgs(f, 'a=1')
1662 self.assertEqualCallArgs(f, 'a=1, b=2')
1663 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1664 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1665 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1666
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001667 def test_keyword_only(self):
1668 f = self.makeCallable('a=3, *, c, d=2')
1669 self.assertEqualCallArgs(f, 'c=3')
1670 self.assertEqualCallArgs(f, 'c=3, a=3')
1671 self.assertEqualCallArgs(f, 'a=2, c=4')
1672 self.assertEqualCallArgs(f, '4, c=4')
1673 self.assertEqualException(f, '')
1674 self.assertEqualException(f, '3')
1675 self.assertEqualException(f, 'a=3')
1676 self.assertEqualException(f, 'd=4')
1677
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001678 f = self.makeCallable('*, c, d=2')
1679 self.assertEqualCallArgs(f, 'c=3')
1680 self.assertEqualCallArgs(f, 'c=3, d=4')
1681 self.assertEqualCallArgs(f, 'd=4, c=3')
1682
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001683 def test_multiple_features(self):
1684 f = self.makeCallable('a, b=2, *f, **g')
1685 self.assertEqualCallArgs(f, '2, 3, 7')
1686 self.assertEqualCallArgs(f, '2, 3, x=8')
1687 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1688 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1689 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1690 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1691 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1692 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1693 '(4,[5,6])]), **collections.UserDict('
1694 'y=9, z=10)')
1695
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001696 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1697 self.assertEqualCallArgs(f, '2, 3, x=8')
1698 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1699 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1700 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1701 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1702 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1703 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1704 '(4,[5,6])]), q=0, **collections.UserDict('
1705 'y=9, z=10)')
1706
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001707 def test_errors(self):
1708 f0 = self.makeCallable('')
1709 f1 = self.makeCallable('a, b')
1710 f2 = self.makeCallable('a, b=1')
1711 # f0 takes no arguments
1712 self.assertEqualException(f0, '1')
1713 self.assertEqualException(f0, 'x=1')
1714 self.assertEqualException(f0, '1,x=1')
1715 # f1 takes exactly 2 arguments
1716 self.assertEqualException(f1, '')
1717 self.assertEqualException(f1, '1')
1718 self.assertEqualException(f1, 'a=2')
1719 self.assertEqualException(f1, 'b=3')
1720 # f2 takes at least 1 argument
1721 self.assertEqualException(f2, '')
1722 self.assertEqualException(f2, 'b=3')
1723 for f in f1, f2:
1724 # f1/f2 takes exactly/at most 2 arguments
1725 self.assertEqualException(f, '2, 3, 4')
1726 self.assertEqualException(f, '1, 2, 3, a=1')
1727 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001728 # XXX: success of this one depends on dict order
1729 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001730 # f got an unexpected keyword argument
1731 self.assertEqualException(f, 'c=2')
1732 self.assertEqualException(f, '2, c=3')
1733 self.assertEqualException(f, '2, 3, c=4')
1734 self.assertEqualException(f, '2, c=4, b=3')
1735 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1736 # f got multiple values for keyword argument
1737 self.assertEqualException(f, '1, a=2')
1738 self.assertEqualException(f, '1, **{"a":2}')
1739 self.assertEqualException(f, '1, 2, b=3')
1740 # XXX: Python inconsistency
1741 # - for functions and bound methods: unexpected keyword 'c'
1742 # - for unbound methods: multiple values for keyword 'a'
1743 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001744 # issue11256:
1745 f3 = self.makeCallable('**c')
1746 self.assertEqualException(f3, '1, 2')
1747 self.assertEqualException(f3, '1, 2, a=1, b=2')
1748 f4 = self.makeCallable('*, a, b=0')
1749 self.assertEqualException(f3, '1, 2')
1750 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001751
Yury Selivanov875df202014-03-27 18:23:03 -04001752 # issue #20816: getcallargs() fails to iterate over non-existent
1753 # kwonlydefaults and raises a wrong TypeError
1754 def f5(*, a): pass
1755 with self.assertRaisesRegex(TypeError,
1756 'missing 1 required keyword-only'):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001757 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001758
1759
Yury Selivanovdccfa132014-03-27 18:42:52 -04001760 # issue20817:
1761 def f6(a, b, c):
1762 pass
1763 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001764 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001765
Dong-hee Naa9cab432018-05-30 00:04:08 +09001766 # bpo-33197
1767 with self.assertRaisesRegex(ValueError,
1768 'variadic keyword parameters cannot'
1769 ' have default values'):
1770 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1771 default=42)
1772 with self.assertRaisesRegex(ValueError,
1773 "value 5 is not a valid Parameter.kind"):
1774 inspect.Parameter("bar", kind=5, default=42)
1775
1776 with self.assertRaisesRegex(TypeError,
1777 'name must be a str, not a int'):
1778 inspect.Parameter(123, kind=4)
1779
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001780class TestGetcallargsMethods(TestGetcallargsFunctions):
1781
1782 def setUp(self):
1783 class Foo(object):
1784 pass
1785 self.cls = Foo
1786 self.inst = Foo()
1787
1788 def makeCallable(self, signature):
1789 assert 'self' not in signature
1790 mk = super(TestGetcallargsMethods, self).makeCallable
1791 self.cls.method = mk('self, ' + signature)
1792 return self.inst.method
1793
1794class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1795
1796 def makeCallable(self, signature):
1797 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1798 return self.cls.method
1799
1800 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1801 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1802 *self._getAssertEqualParams(func, call_params_string, locs))
1803
1804 def assertEqualException(self, func, call_params_string, locs=None):
1805 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1806 *self._getAssertEqualParams(func, call_params_string, locs))
1807
1808 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1809 assert 'inst' not in call_params_string
1810 locs = dict(locs or {}, inst=self.inst)
1811 return (func, 'inst,' + call_params_string, locs)
1812
Michael Foord95fc51d2010-11-20 15:07:30 +00001813
1814class TestGetattrStatic(unittest.TestCase):
1815
1816 def test_basic(self):
1817 class Thing(object):
1818 x = object()
1819
1820 thing = Thing()
1821 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1822 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1823 with self.assertRaises(AttributeError):
1824 inspect.getattr_static(thing, 'y')
1825
1826 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1827
1828 def test_inherited(self):
1829 class Thing(object):
1830 x = object()
1831 class OtherThing(Thing):
1832 pass
1833
1834 something = OtherThing()
1835 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1836
1837 def test_instance_attr(self):
1838 class Thing(object):
1839 x = 2
1840 def __init__(self, x):
1841 self.x = x
1842 thing = Thing(3)
1843 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1844 del thing.x
1845 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1846
1847 def test_property(self):
1848 class Thing(object):
1849 @property
1850 def x(self):
1851 raise AttributeError("I'm pretending not to exist")
1852 thing = Thing()
1853 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1854
Ezio Melotti75cbd732011-04-28 00:59:29 +03001855 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001856 class descriptor(object):
1857 def __get__(*_):
1858 raise AttributeError("I'm pretending not to exist")
1859 desc = descriptor()
1860 class Thing(object):
1861 x = desc
1862 thing = Thing()
1863 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1864
1865 def test_classAttribute(self):
1866 class Thing(object):
1867 x = object()
1868
1869 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1870
Ethan Furmane03ea372013-09-25 07:14:41 -07001871 def test_classVirtualAttribute(self):
1872 class Thing(object):
1873 @types.DynamicClassAttribute
1874 def x(self):
1875 return self._x
1876 _x = object()
1877
1878 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1879
Michael Foord95fc51d2010-11-20 15:07:30 +00001880 def test_inherited_classattribute(self):
1881 class Thing(object):
1882 x = object()
1883 class OtherThing(Thing):
1884 pass
1885
1886 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1887
1888 def test_slots(self):
1889 class Thing(object):
1890 y = 'bar'
1891 __slots__ = ['x']
1892 def __init__(self):
1893 self.x = 'foo'
1894 thing = Thing()
1895 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1896 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1897
1898 del thing.x
1899 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1900
1901 def test_metaclass(self):
1902 class meta(type):
1903 attr = 'foo'
1904 class Thing(object, metaclass=meta):
1905 pass
1906 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1907
1908 class sub(meta):
1909 pass
1910 class OtherThing(object, metaclass=sub):
1911 x = 3
1912 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1913
1914 class OtherOtherThing(OtherThing):
1915 pass
1916 # this test is odd, but it was added as it exposed a bug
1917 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1918
1919 def test_no_dict_no_slots(self):
1920 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1921 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1922
1923 def test_no_dict_no_slots_instance_member(self):
1924 # returns descriptor
Inada Naokifb786922021-04-06 11:18:41 +09001925 with open(__file__, encoding='utf-8') as handle:
Michael Foord95fc51d2010-11-20 15:07:30 +00001926 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1927
1928 def test_inherited_slots(self):
1929 # returns descriptor
1930 class Thing(object):
1931 __slots__ = ['x']
1932 def __init__(self):
1933 self.x = 'foo'
1934
1935 class OtherThing(Thing):
1936 pass
1937 # it would be nice if this worked...
1938 # we get the descriptor instead of the instance attribute
1939 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1940
1941 def test_descriptor(self):
1942 class descriptor(object):
1943 def __get__(self, instance, owner):
1944 return 3
1945 class Foo(object):
1946 d = descriptor()
1947
1948 foo = Foo()
1949
1950 # for a non data descriptor we return the instance attribute
1951 foo.__dict__['d'] = 1
1952 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1953
Mike53f7a7c2017-12-14 14:04:53 +03001954 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001955 # descriptor
1956 descriptor.__set__ = lambda s, i, v: None
1957 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1958
1959
1960 def test_metaclass_with_descriptor(self):
1961 class descriptor(object):
1962 def __get__(self, instance, owner):
1963 return 3
1964 class meta(type):
1965 d = descriptor()
1966 class Thing(object, metaclass=meta):
1967 pass
1968 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1969
1970
Michael Foordcc7ebb82010-11-20 16:20:16 +00001971 def test_class_as_property(self):
1972 class Base(object):
1973 foo = 3
1974
1975 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001976 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001977 @property
1978 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001979 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001980 return object
1981
Michael Foord35184ed2010-11-20 16:58:30 +00001982 instance = Something()
1983 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1984 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001985 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1986
Michael Foorde5162652010-11-20 16:40:44 +00001987 def test_mro_as_property(self):
1988 class Meta(type):
1989 @property
1990 def __mro__(self):
1991 return (object,)
1992
1993 class Base(object):
1994 foo = 3
1995
1996 class Something(Base, metaclass=Meta):
1997 pass
1998
1999 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
2000 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
2001
Michael Foorddcebe0f2011-03-15 19:20:44 -04002002 def test_dict_as_property(self):
2003 test = self
2004 test.called = False
2005
2006 class Foo(dict):
2007 a = 3
2008 @property
2009 def __dict__(self):
2010 test.called = True
2011 return {}
2012
2013 foo = Foo()
2014 foo.a = 4
2015 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
2016 self.assertFalse(test.called)
2017
2018 def test_custom_object_dict(self):
2019 test = self
2020 test.called = False
2021
2022 class Custom(dict):
2023 def get(self, key, default=None):
2024 test.called = True
2025 super().get(key, default)
2026
2027 class Foo(object):
2028 a = 3
2029 foo = Foo()
2030 foo.__dict__ = Custom()
2031 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
2032 self.assertFalse(test.called)
2033
2034 def test_metaclass_dict_as_property(self):
2035 class Meta(type):
2036 @property
2037 def __dict__(self):
2038 self.executed = True
2039
2040 class Thing(metaclass=Meta):
2041 executed = False
2042
2043 def __init__(self):
2044 self.spam = 42
2045
2046 instance = Thing()
2047 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
2048 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00002049
Michael Foorda51623b2011-12-18 22:01:40 +00002050 def test_module(self):
2051 sentinel = object()
2052 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
2053 sentinel)
2054
Michael Foord3ba95f82011-12-22 01:13:37 +00002055 def test_metaclass_with_metaclass_with_dict_as_property(self):
2056 class MetaMeta(type):
2057 @property
2058 def __dict__(self):
2059 self.executed = True
2060 return dict(spam=42)
2061
2062 class Meta(type, metaclass=MetaMeta):
2063 executed = False
2064
2065 class Thing(metaclass=Meta):
2066 pass
2067
2068 with self.assertRaises(AttributeError):
2069 inspect.getattr_static(Thing, "spam")
2070 self.assertFalse(Thing.executed)
2071
Nick Coghlane0f04652010-11-21 03:44:04 +00002072class TestGetGeneratorState(unittest.TestCase):
2073
2074 def setUp(self):
2075 def number_generator():
2076 for number in range(5):
2077 yield number
2078 self.generator = number_generator()
2079
2080 def _generatorstate(self):
2081 return inspect.getgeneratorstate(self.generator)
2082
2083 def test_created(self):
2084 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
2085
2086 def test_suspended(self):
2087 next(self.generator)
2088 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
2089
2090 def test_closed_after_exhaustion(self):
2091 for i in self.generator:
2092 pass
2093 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
2094
2095 def test_closed_after_immediate_exception(self):
2096 with self.assertRaises(RuntimeError):
2097 self.generator.throw(RuntimeError)
2098 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
2099
2100 def test_running(self):
2101 # As mentioned on issue #10220, checking for the RUNNING state only
2102 # makes sense inside the generator itself.
2103 # The following generator checks for this by using the closure's
2104 # reference to self and the generator state checking helper method
2105 def running_check_generator():
2106 for number in range(5):
2107 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
2108 yield number
2109 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
2110 self.generator = running_check_generator()
2111 # Running up to the first yield
2112 next(self.generator)
2113 # Running after the first yield
2114 next(self.generator)
2115
Nick Coghlan7921b9f2010-11-30 06:36:04 +00002116 def test_easy_debugging(self):
2117 # repr() and str() of a generator state should contain the state name
2118 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
2119 for name in names:
2120 state = getattr(inspect, name)
2121 self.assertIn(name, repr(state))
2122 self.assertIn(name, str(state))
2123
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10002124 def test_getgeneratorlocals(self):
2125 def each(lst, a=None):
2126 b=(1, 2, 3)
2127 for v in lst:
2128 if v == 3:
2129 c = 12
2130 yield v
2131
2132 numbers = each([1, 2, 3])
2133 self.assertEqual(inspect.getgeneratorlocals(numbers),
2134 {'a': None, 'lst': [1, 2, 3]})
2135 next(numbers)
2136 self.assertEqual(inspect.getgeneratorlocals(numbers),
2137 {'a': None, 'lst': [1, 2, 3], 'v': 1,
2138 'b': (1, 2, 3)})
2139 next(numbers)
2140 self.assertEqual(inspect.getgeneratorlocals(numbers),
2141 {'a': None, 'lst': [1, 2, 3], 'v': 2,
2142 'b': (1, 2, 3)})
2143 next(numbers)
2144 self.assertEqual(inspect.getgeneratorlocals(numbers),
2145 {'a': None, 'lst': [1, 2, 3], 'v': 3,
2146 'b': (1, 2, 3), 'c': 12})
2147 try:
2148 next(numbers)
2149 except StopIteration:
2150 pass
2151 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
2152
2153 def test_getgeneratorlocals_empty(self):
2154 def yield_one():
2155 yield 1
2156 one = yield_one()
2157 self.assertEqual(inspect.getgeneratorlocals(one), {})
2158 try:
2159 next(one)
2160 except StopIteration:
2161 pass
2162 self.assertEqual(inspect.getgeneratorlocals(one), {})
2163
2164 def test_getgeneratorlocals_error(self):
2165 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
2166 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
2167 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
2168 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
2169
Nick Coghlane0f04652010-11-21 03:44:04 +00002170
Yury Selivanov5376ba92015-06-22 12:19:30 -04002171class TestGetCoroutineState(unittest.TestCase):
2172
2173 def setUp(self):
2174 @types.coroutine
2175 def number_coroutine():
2176 for number in range(5):
2177 yield number
2178 async def coroutine():
2179 await number_coroutine()
2180 self.coroutine = coroutine()
2181
2182 def tearDown(self):
2183 self.coroutine.close()
2184
2185 def _coroutinestate(self):
2186 return inspect.getcoroutinestate(self.coroutine)
2187
2188 def test_created(self):
2189 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
2190
2191 def test_suspended(self):
2192 self.coroutine.send(None)
2193 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
2194
2195 def test_closed_after_exhaustion(self):
2196 while True:
2197 try:
2198 self.coroutine.send(None)
2199 except StopIteration:
2200 break
2201
2202 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2203
2204 def test_closed_after_immediate_exception(self):
2205 with self.assertRaises(RuntimeError):
2206 self.coroutine.throw(RuntimeError)
2207 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2208
2209 def test_easy_debugging(self):
2210 # repr() and str() of a coroutine state should contain the state name
2211 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2212 for name in names:
2213 state = getattr(inspect, name)
2214 self.assertIn(name, repr(state))
2215 self.assertIn(name, str(state))
2216
2217 def test_getcoroutinelocals(self):
2218 @types.coroutine
2219 def gencoro():
2220 yield
2221
2222 gencoro = gencoro()
2223 async def func(a=None):
2224 b = 'spam'
2225 await gencoro
2226
2227 coro = func()
2228 self.assertEqual(inspect.getcoroutinelocals(coro),
2229 {'a': None, 'gencoro': gencoro})
2230 coro.send(None)
2231 self.assertEqual(inspect.getcoroutinelocals(coro),
2232 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2233
2234
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002235class MySignature(inspect.Signature):
2236 # Top-level to make it picklable;
2237 # used in test_signature_object_pickle
2238 pass
2239
2240class MyParameter(inspect.Parameter):
2241 # Top-level to make it picklable;
2242 # used in test_signature_object_pickle
2243 pass
2244
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002245
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002246
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002247class TestSignatureObject(unittest.TestCase):
2248 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002249 def signature(func, **kw):
2250 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002251 return (tuple((param.name,
2252 (... if param.default is param.empty else param.default),
2253 (... if param.annotation is param.empty
2254 else param.annotation),
2255 str(param.kind).lower())
2256 for param in sig.parameters.values()),
2257 (... if sig.return_annotation is sig.empty
2258 else sig.return_annotation))
2259
2260 def test_signature_object(self):
2261 S = inspect.Signature
2262 P = inspect.Parameter
2263
2264 self.assertEqual(str(S()), '()')
Jens Reidel611836a2020-03-18 03:22:46 +01002265 self.assertEqual(repr(S().parameters), 'mappingproxy(OrderedDict())')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002266
Yury Selivanov07a9e452014-01-29 10:58:16 -05002267 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002268 pass
2269 sig = inspect.signature(test)
2270 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002271 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002272 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002273 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002274 args = sig.parameters['args']
2275 ko = sig.parameters['ko']
2276 kwargs = sig.parameters['kwargs']
2277
2278 S((po, pk, 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((pk, po, args, 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((po, args, 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((args, po, pk, ko, kwargs))
2288
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002289 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002290 S((po, pk, args, kwargs, ko))
2291
2292 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002293 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002294 S((po, pk, args, kwargs2, ko))
2295
Yury Selivanov07a9e452014-01-29 10:58:16 -05002296 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2297 S((pod, po))
2298
2299 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2300 S((po, pkd, pk))
2301
2302 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2303 S((pkd, pk))
2304
Yury Selivanov374375d2014-03-27 12:41:53 -04002305 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002306 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002307
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002308 def test_signature_object_pickle(self):
2309 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2310 foo_partial = functools.partial(foo, a=1)
2311
2312 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002313
2314 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2315 with self.subTest(pickle_ver=ver, subclass=False):
2316 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2317 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002318
2319 # Test that basic sub-classing works
2320 sig = inspect.signature(foo)
2321 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2322 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2323 mysig = MySignature().replace(parameters=myparams.values(),
2324 return_annotation=sig.return_annotation)
2325 self.assertTrue(isinstance(mysig, MySignature))
2326 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2327
2328 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2329 with self.subTest(pickle_ver=ver, subclass=True):
2330 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2331 self.assertEqual(mysig, sig_pickled)
2332 self.assertTrue(isinstance(sig_pickled, MySignature))
2333 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2334 MyParameter))
2335
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002336 def test_signature_immutability(self):
2337 def test(a):
2338 pass
2339 sig = inspect.signature(test)
2340
2341 with self.assertRaises(AttributeError):
2342 sig.foo = 'bar'
2343
2344 with self.assertRaises(TypeError):
2345 sig.parameters['a'] = None
2346
2347 def test_signature_on_noarg(self):
2348 def test():
2349 pass
2350 self.assertEqual(self.signature(test), ((), ...))
2351
2352 def test_signature_on_wargs(self):
2353 def test(a, b:'foo') -> 123:
2354 pass
2355 self.assertEqual(self.signature(test),
2356 ((('a', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002357 ('b', ..., 'foo', "positional_or_keyword")),
2358 123))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002359
2360 def test_signature_on_wkwonly(self):
2361 def test(*, a:float, b:str) -> int:
2362 pass
2363 self.assertEqual(self.signature(test),
2364 ((('a', ..., float, "keyword_only"),
2365 ('b', ..., str, "keyword_only")),
2366 int))
2367
2368 def test_signature_on_complex_args(self):
2369 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2370 pass
2371 self.assertEqual(self.signature(test),
2372 ((('a', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002373 ('b', 10, 'foo', "positional_or_keyword"),
2374 ('args', ..., 'bar', "var_positional"),
2375 ('spam', ..., 'baz', "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002376 ('ham', 123, ..., "keyword_only"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002377 ('kwargs', ..., int, "var_keyword")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002378 ...))
2379
Dong-hee Na378d7062017-05-18 04:00:51 +09002380 def test_signature_without_self(self):
2381 def test_args_only(*args): # NOQA
2382 pass
2383
2384 def test_args_kwargs_only(*args, **kwargs): # NOQA
2385 pass
2386
2387 class A:
2388 @classmethod
2389 def test_classmethod(*args): # NOQA
2390 pass
2391
2392 @staticmethod
2393 def test_staticmethod(*args): # NOQA
2394 pass
2395
2396 f1 = functools.partialmethod((test_classmethod), 1)
2397 f2 = functools.partialmethod((test_args_only), 1)
2398 f3 = functools.partialmethod((test_staticmethod), 1)
2399 f4 = functools.partialmethod((test_args_kwargs_only),1)
2400
2401 self.assertEqual(self.signature(test_args_only),
2402 ((('args', ..., ..., 'var_positional'),), ...))
2403 self.assertEqual(self.signature(test_args_kwargs_only),
2404 ((('args', ..., ..., 'var_positional'),
2405 ('kwargs', ..., ..., 'var_keyword')), ...))
2406 self.assertEqual(self.signature(A.f1),
2407 ((('args', ..., ..., 'var_positional'),), ...))
2408 self.assertEqual(self.signature(A.f2),
2409 ((('args', ..., ..., 'var_positional'),), ...))
2410 self.assertEqual(self.signature(A.f3),
2411 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002412 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002413 ((('args', ..., ..., 'var_positional'),
2414 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002415 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002416 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2417 "Signature information for builtins requires docstrings")
2418 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002419 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002420
Larry Hastings5c661892014-01-24 06:17:25 -08002421 def test_unbound_method(o):
2422 """Use this to test unbound methods (things that should have a self)"""
2423 signature = inspect.signature(o)
2424 self.assertTrue(isinstance(signature, inspect.Signature))
2425 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2426 return signature
2427
2428 def test_callable(o):
2429 """Use this to test bound methods or normal callables (things that don't expect self)"""
2430 signature = inspect.signature(o)
2431 self.assertTrue(isinstance(signature, inspect.Signature))
2432 if signature.parameters:
2433 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2434 return signature
2435
2436 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002437 def p(name): return signature.parameters[name].default
2438 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002439 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002440 self.assertEqual(p('d'), 3.14)
2441 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002442 self.assertEqual(p('n'), None)
2443 self.assertEqual(p('t'), True)
2444 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002445 self.assertEqual(p('local'), 3)
2446 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002447 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002448
Larry Hastings5c661892014-01-24 06:17:25 -08002449 test_callable(object)
2450
2451 # normal method
2452 # (PyMethodDescr_Type, "method_descriptor")
2453 test_unbound_method(_pickle.Pickler.dump)
2454 d = _pickle.Pickler(io.StringIO())
2455 test_callable(d.dump)
2456
2457 # static method
Serhiy Storchaka279f4462019-09-14 12:24:05 +03002458 test_callable(bytes.maketrans)
2459 test_callable(b'abc'.maketrans)
Larry Hastings5c661892014-01-24 06:17:25 -08002460
2461 # class method
2462 test_callable(dict.fromkeys)
2463 test_callable({}.fromkeys)
2464
2465 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2466 test_unbound_method(type.__call__)
2467 test_unbound_method(int.__add__)
2468 test_callable((3).__add__)
2469
2470 # _PyMethodWrapper_Type
2471 # support for 'method-wrapper'
2472 test_callable(min.__call__)
2473
Larry Hastings2623c8c2014-02-08 22:15:29 -08002474 # This doesn't work now.
2475 # (We don't have a valid signature for "type" in 3.4)
2476 with self.assertRaisesRegex(ValueError, "no signature found"):
2477 class ThisWorksNow:
2478 __call__ = type
2479 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002480
Yury Selivanov056e2652014-03-02 12:25:27 -05002481 # Regression test for issue #20786
2482 test_unbound_method(dict.__delitem__)
2483 test_unbound_method(property.__delete__)
2484
Zachary Ware8ef887c2015-04-13 18:22:35 -05002485 # Regression test for issue #20586
2486 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2487
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002488 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002489 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2490 "Signature information for builtins requires docstrings")
2491 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002492 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002493 func = _testcapi.docstring_with_signature_with_defaults
2494
2495 def decorator(func):
2496 @functools.wraps(func)
2497 def wrapper(*args, **kwargs) -> int:
2498 return func(*args, **kwargs)
2499 return wrapper
2500
2501 decorated_func = decorator(func)
2502
2503 self.assertEqual(inspect.signature(func),
2504 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002505
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002506 def wrapper_like(*args, **kwargs) -> int: pass
2507 self.assertEqual(inspect.signature(decorated_func,
2508 follow_wrapped=False),
2509 inspect.signature(wrapper_like))
2510
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002511 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002512 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002513 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002514 with self.assertRaisesRegex(ValueError,
2515 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002516 inspect.signature(_testcapi.docstring_no_signature)
2517
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002518 with self.assertRaisesRegex(ValueError,
2519 'no signature found for builtin'):
2520 inspect.signature(str)
2521
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002522 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002523 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002524 inspect.signature(42)
2525
Yury Selivanov63da7c72014-01-31 14:48:37 -05002526 def test_signature_from_functionlike_object(self):
2527 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2528 pass
2529
2530 class funclike:
2531 # Has to be callable, and have correct
2532 # __code__, __annotations__, __defaults__, __name__,
2533 # and __kwdefaults__ attributes
2534
2535 def __init__(self, func):
2536 self.__name__ = func.__name__
2537 self.__code__ = func.__code__
2538 self.__annotations__ = func.__annotations__
2539 self.__defaults__ = func.__defaults__
2540 self.__kwdefaults__ = func.__kwdefaults__
2541 self.func = func
2542
2543 def __call__(self, *args, **kwargs):
2544 return self.func(*args, **kwargs)
2545
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002546 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002547
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002548 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002549 self.assertEqual(sig_funclike, sig_func)
2550
2551 sig_funclike = inspect.signature(funclike(func))
2552 self.assertEqual(sig_funclike, sig_func)
2553
2554 # If object is not a duck type of function, then
2555 # signature will try to get a signature for its '__call__'
2556 # method
2557 fl = funclike(func)
2558 del fl.__defaults__
2559 self.assertEqual(self.signature(fl),
2560 ((('args', ..., ..., "var_positional"),
2561 ('kwargs', ..., ..., "var_keyword")),
2562 ...))
2563
Yury Selivanova773de02014-02-21 18:30:53 -05002564 # Test with cython-like builtins:
2565 _orig_isdesc = inspect.ismethoddescriptor
2566 def _isdesc(obj):
2567 if hasattr(obj, '_builtinmock'):
2568 return True
2569 return _orig_isdesc(obj)
2570
2571 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2572 builtin_func = funclike(func)
2573 # Make sure that our mock setup is working
2574 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2575 builtin_func._builtinmock = True
2576 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2577 self.assertEqual(inspect.signature(builtin_func), sig_func)
2578
Yury Selivanov63da7c72014-01-31 14:48:37 -05002579 def test_signature_functionlike_class(self):
2580 # We only want to duck type function-like objects,
2581 # not classes.
2582
2583 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2584 pass
2585
2586 class funclike:
2587 def __init__(self, marker):
2588 pass
2589
2590 __name__ = func.__name__
2591 __code__ = func.__code__
2592 __annotations__ = func.__annotations__
2593 __defaults__ = func.__defaults__
2594 __kwdefaults__ = func.__kwdefaults__
2595
Yury Selivanov63da7c72014-01-31 14:48:37 -05002596 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2597
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002598 def test_signature_on_method(self):
2599 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002600 def __init__(*args):
2601 pass
2602 def m1(self, arg1, arg2=1) -> int:
2603 pass
2604 def m2(*args):
2605 pass
2606 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002607 pass
2608
Yury Selivanov62560fb2014-01-28 12:26:24 -05002609 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002610 ((('arg1', ..., ..., "positional_or_keyword"),
2611 ('arg2', 1, ..., "positional_or_keyword")),
2612 int))
2613
Yury Selivanov62560fb2014-01-28 12:26:24 -05002614 self.assertEqual(self.signature(Test().m2),
2615 ((('args', ..., ..., "var_positional"),),
2616 ...))
2617
2618 self.assertEqual(self.signature(Test),
2619 ((('args', ..., ..., "var_positional"),),
2620 ...))
2621
2622 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2623 self.signature(Test())
2624
Yury Selivanov46c759d2015-05-27 21:56:53 -04002625 def test_signature_wrapped_bound_method(self):
2626 # Issue 24298
2627 class Test:
2628 def m1(self, arg1, arg2=1) -> int:
2629 pass
2630 @functools.wraps(Test().m1)
2631 def m1d(*args, **kwargs):
2632 pass
2633 self.assertEqual(self.signature(m1d),
2634 ((('arg1', ..., ..., "positional_or_keyword"),
2635 ('arg2', 1, ..., "positional_or_keyword")),
2636 int))
2637
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002638 def test_signature_on_classmethod(self):
2639 class Test:
2640 @classmethod
2641 def foo(cls, arg1, *, arg2=1):
2642 pass
2643
2644 meth = Test().foo
2645 self.assertEqual(self.signature(meth),
2646 ((('arg1', ..., ..., "positional_or_keyword"),
2647 ('arg2', 1, ..., "keyword_only")),
2648 ...))
2649
2650 meth = Test.foo
2651 self.assertEqual(self.signature(meth),
2652 ((('arg1', ..., ..., "positional_or_keyword"),
2653 ('arg2', 1, ..., "keyword_only")),
2654 ...))
2655
2656 def test_signature_on_staticmethod(self):
2657 class Test:
2658 @staticmethod
2659 def foo(cls, *, arg):
2660 pass
2661
2662 meth = Test().foo
2663 self.assertEqual(self.signature(meth),
2664 ((('cls', ..., ..., "positional_or_keyword"),
2665 ('arg', ..., ..., "keyword_only")),
2666 ...))
2667
2668 meth = Test.foo
2669 self.assertEqual(self.signature(meth),
2670 ((('cls', ..., ..., "positional_or_keyword"),
2671 ('arg', ..., ..., "keyword_only")),
2672 ...))
2673
2674 def test_signature_on_partial(self):
2675 from functools import partial
2676
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002677 Parameter = inspect.Parameter
2678
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002679 def test():
2680 pass
2681
2682 self.assertEqual(self.signature(partial(test)), ((), ...))
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, 1))
2686
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002687 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002688 inspect.signature(partial(test, a=1))
2689
2690 def test(a, b, *, c, d):
2691 pass
2692
2693 self.assertEqual(self.signature(partial(test)),
2694 ((('a', ..., ..., "positional_or_keyword"),
2695 ('b', ..., ..., "positional_or_keyword"),
2696 ('c', ..., ..., "keyword_only"),
2697 ('d', ..., ..., "keyword_only")),
2698 ...))
2699
2700 self.assertEqual(self.signature(partial(test, 1)),
2701 ((('b', ..., ..., "positional_or_keyword"),
2702 ('c', ..., ..., "keyword_only"),
2703 ('d', ..., ..., "keyword_only")),
2704 ...))
2705
2706 self.assertEqual(self.signature(partial(test, 1, c=2)),
2707 ((('b', ..., ..., "positional_or_keyword"),
2708 ('c', 2, ..., "keyword_only"),
2709 ('d', ..., ..., "keyword_only")),
2710 ...))
2711
2712 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2713 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002714 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002715 ('c', 2, ..., "keyword_only"),
2716 ('d', ..., ..., "keyword_only")),
2717 ...))
2718
2719 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002720 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002721 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002722 ('d', ..., ..., "keyword_only")),
2723 ...))
2724
2725 self.assertEqual(self.signature(partial(test, a=1)),
2726 ((('a', 1, ..., "keyword_only"),
2727 ('b', ..., ..., "keyword_only"),
2728 ('c', ..., ..., "keyword_only"),
2729 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002730 ...))
2731
2732 def test(a, *args, b, **kwargs):
2733 pass
2734
2735 self.assertEqual(self.signature(partial(test, 1)),
2736 ((('args', ..., ..., "var_positional"),
2737 ('b', ..., ..., "keyword_only"),
2738 ('kwargs', ..., ..., "var_keyword")),
2739 ...))
2740
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002741 self.assertEqual(self.signature(partial(test, a=1)),
2742 ((('a', 1, ..., "keyword_only"),
2743 ('b', ..., ..., "keyword_only"),
2744 ('kwargs', ..., ..., "var_keyword")),
2745 ...))
2746
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002747 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2748 ((('args', ..., ..., "var_positional"),
2749 ('b', ..., ..., "keyword_only"),
2750 ('kwargs', ..., ..., "var_keyword")),
2751 ...))
2752
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002753 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2754 ((('args', ..., ..., "var_positional"),
2755 ('b', ..., ..., "keyword_only"),
2756 ('kwargs', ..., ..., "var_keyword")),
2757 ...))
2758
2759 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2760 ((('args', ..., ..., "var_positional"),
2761 ('b', 0, ..., "keyword_only"),
2762 ('kwargs', ..., ..., "var_keyword")),
2763 ...))
2764
2765 self.assertEqual(self.signature(partial(test, b=0)),
2766 ((('a', ..., ..., "positional_or_keyword"),
2767 ('args', ..., ..., "var_positional"),
2768 ('b', 0, ..., "keyword_only"),
2769 ('kwargs', ..., ..., "var_keyword")),
2770 ...))
2771
2772 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2773 ((('a', ..., ..., "positional_or_keyword"),
2774 ('args', ..., ..., "var_positional"),
2775 ('b', 0, ..., "keyword_only"),
2776 ('kwargs', ..., ..., "var_keyword")),
2777 ...))
2778
2779 def test(a, b, c:int) -> 42:
2780 pass
2781
2782 sig = test.__signature__ = inspect.signature(test)
2783
2784 self.assertEqual(self.signature(partial(partial(test, 1))),
2785 ((('b', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002786 ('c', ..., int, "positional_or_keyword")),
2787 42))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002788
2789 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002790 ((('c', ..., int, "positional_or_keyword"),),
2791 42))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002792
2793 psig = inspect.signature(partial(partial(test, 1), 2))
2794
2795 def foo(a):
2796 return a
2797 _foo = partial(partial(foo, a=10), a=20)
2798 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002799 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002800 ...))
2801 # check that we don't have any side-effects in signature(),
2802 # and the partial object is still functioning
2803 self.assertEqual(_foo(), 20)
2804
2805 def foo(a, b, c):
2806 return a, b, c
2807 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002808
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002809 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002810 ((('b', 30, ..., "keyword_only"),
2811 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002812 ...))
2813 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002814
2815 def foo(a, b, c, *, d):
2816 return a, b, c, d
2817 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2818 self.assertEqual(self.signature(_foo),
2819 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002820 ('b', 10, ..., "keyword_only"),
2821 ('c', 20, ..., "keyword_only"),
2822 ('d', 30, ..., "keyword_only"),
2823 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002824 ...))
2825 ba = inspect.signature(_foo).bind(a=200, b=11)
2826 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2827
2828 def foo(a=1, b=2, c=3):
2829 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002830 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2831
2832 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002833 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002834
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002835 ba = inspect.signature(_foo).bind(11, 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(11, b=12)
2839 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002840
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002841 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002842 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2843
2844 _foo = partial(_foo, b=10, c=20)
2845 ba = inspect.signature(_foo).bind(12)
2846 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2847
2848
2849 def foo(a, b, c, d, **kwargs):
2850 pass
2851 sig = inspect.signature(foo)
2852 params = sig.parameters.copy()
2853 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2854 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2855 foo.__signature__ = inspect.Signature(params.values())
2856 sig = inspect.signature(foo)
2857 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2858
2859 self.assertEqual(self.signature(partial(foo, 1)),
2860 ((('b', ..., ..., 'positional_only'),
2861 ('c', ..., ..., 'positional_or_keyword'),
2862 ('d', ..., ..., 'positional_or_keyword'),
2863 ('kwargs', ..., ..., 'var_keyword')),
2864 ...))
2865
2866 self.assertEqual(self.signature(partial(foo, 1, 2)),
2867 ((('c', ..., ..., 'positional_or_keyword'),
2868 ('d', ..., ..., 'positional_or_keyword'),
2869 ('kwargs', ..., ..., 'var_keyword')),
2870 ...))
2871
2872 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2873 ((('d', ..., ..., 'positional_or_keyword'),
2874 ('kwargs', ..., ..., 'var_keyword')),
2875 ...))
2876
2877 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2878 ((('c', 3, ..., 'keyword_only'),
2879 ('d', ..., ..., 'keyword_only'),
2880 ('kwargs', ..., ..., 'var_keyword')),
2881 ...))
2882
2883 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2884 ((('b', ..., ..., 'positional_only'),
2885 ('c', 3, ..., 'keyword_only'),
2886 ('d', ..., ..., 'keyword_only'),
2887 ('kwargs', ..., ..., 'var_keyword')),
2888 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002889
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002890 def test_signature_on_partialmethod(self):
2891 from functools import partialmethod
2892
2893 class Spam:
2894 def test():
2895 pass
2896 ham = partialmethod(test)
2897
2898 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2899 inspect.signature(Spam.ham)
2900
2901 class Spam:
2902 def test(it, a, *, c) -> 'spam':
2903 pass
2904 ham = partialmethod(test, c=1)
2905
larryhastings74613a42021-04-29 21:16:28 -07002906 self.assertEqual(self.signature(Spam.ham, eval_str=False),
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002907 ((('it', ..., ..., 'positional_or_keyword'),
2908 ('a', ..., ..., 'positional_or_keyword'),
2909 ('c', 1, ..., 'keyword_only')),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002910 'spam'))
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002911
larryhastings74613a42021-04-29 21:16:28 -07002912 self.assertEqual(self.signature(Spam().ham, eval_str=False),
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002913 ((('a', ..., ..., 'positional_or_keyword'),
2914 ('c', 1, ..., 'keyword_only')),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002915 'spam'))
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002916
Yury Selivanov8a387212018-03-06 12:59:45 -05002917 class Spam:
2918 def test(self: 'anno', x):
2919 pass
2920
2921 g = partialmethod(test, 1)
2922
larryhastings74613a42021-04-29 21:16:28 -07002923 self.assertEqual(self.signature(Spam.g, eval_str=False),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002924 ((('self', ..., 'anno', 'positional_or_keyword'),),
Yury Selivanov8a387212018-03-06 12:59:45 -05002925 ...))
2926
Yury Selivanov0486f812014-01-29 12:18:59 -05002927 def test_signature_on_fake_partialmethod(self):
2928 def foo(a): pass
2929 foo._partialmethod = 'spam'
2930 self.assertEqual(str(inspect.signature(foo)), '(a)')
2931
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002932 def test_signature_on_decorated(self):
2933 import functools
2934
2935 def decorator(func):
2936 @functools.wraps(func)
2937 def wrapper(*args, **kwargs) -> int:
2938 return func(*args, **kwargs)
2939 return wrapper
2940
2941 class Foo:
2942 @decorator
2943 def bar(self, a, b):
2944 pass
2945
2946 self.assertEqual(self.signature(Foo.bar),
2947 ((('self', ..., ..., "positional_or_keyword"),
2948 ('a', ..., ..., "positional_or_keyword"),
2949 ('b', ..., ..., "positional_or_keyword")),
2950 ...))
2951
2952 self.assertEqual(self.signature(Foo().bar),
2953 ((('a', ..., ..., "positional_or_keyword"),
2954 ('b', ..., ..., "positional_or_keyword")),
2955 ...))
2956
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002957 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2958 ((('args', ..., ..., "var_positional"),
2959 ('kwargs', ..., ..., "var_keyword")),
2960 ...)) # functools.wraps will copy __annotations__
2961 # from "func" to "wrapper", hence no
2962 # return_annotation
2963
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002964 # Test that we handle method wrappers correctly
2965 def decorator(func):
2966 @functools.wraps(func)
2967 def wrapper(*args, **kwargs) -> int:
2968 return func(42, *args, **kwargs)
2969 sig = inspect.signature(func)
2970 new_params = tuple(sig.parameters.values())[1:]
2971 wrapper.__signature__ = sig.replace(parameters=new_params)
2972 return wrapper
2973
2974 class Foo:
2975 @decorator
2976 def __call__(self, a, b):
2977 pass
2978
2979 self.assertEqual(self.signature(Foo.__call__),
2980 ((('a', ..., ..., "positional_or_keyword"),
2981 ('b', ..., ..., "positional_or_keyword")),
2982 ...))
2983
2984 self.assertEqual(self.signature(Foo().__call__),
2985 ((('b', ..., ..., "positional_or_keyword"),),
2986 ...))
2987
Nick Coghlane8c45d62013-07-28 20:00:01 +10002988 # Test we handle __signature__ partway down the wrapper stack
2989 def wrapped_foo_call():
2990 pass
2991 wrapped_foo_call.__wrapped__ = Foo.__call__
2992
2993 self.assertEqual(self.signature(wrapped_foo_call),
2994 ((('a', ..., ..., "positional_or_keyword"),
2995 ('b', ..., ..., "positional_or_keyword")),
2996 ...))
2997
2998
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002999 def test_signature_on_class(self):
3000 class C:
3001 def __init__(self, a):
3002 pass
3003
3004 self.assertEqual(self.signature(C),
3005 ((('a', ..., ..., "positional_or_keyword"),),
3006 ...))
3007
3008 class CM(type):
3009 def __call__(cls, a):
3010 pass
3011 class C(metaclass=CM):
3012 def __init__(self, b):
3013 pass
3014
3015 self.assertEqual(self.signature(C),
3016 ((('a', ..., ..., "positional_or_keyword"),),
3017 ...))
3018
3019 class CM(type):
3020 def __new__(mcls, name, bases, dct, *, foo=1):
3021 return super().__new__(mcls, name, bases, dct)
3022 class C(metaclass=CM):
3023 def __init__(self, b):
3024 pass
3025
3026 self.assertEqual(self.signature(C),
3027 ((('b', ..., ..., "positional_or_keyword"),),
3028 ...))
3029
3030 self.assertEqual(self.signature(CM),
3031 ((('name', ..., ..., "positional_or_keyword"),
3032 ('bases', ..., ..., "positional_or_keyword"),
3033 ('dct', ..., ..., "positional_or_keyword"),
3034 ('foo', 1, ..., "keyword_only")),
3035 ...))
3036
3037 class CMM(type):
3038 def __new__(mcls, name, bases, dct, *, foo=1):
3039 return super().__new__(mcls, name, bases, dct)
3040 def __call__(cls, nm, bs, dt):
3041 return type(nm, bs, dt)
3042 class CM(type, metaclass=CMM):
3043 def __new__(mcls, name, bases, dct, *, bar=2):
3044 return super().__new__(mcls, name, bases, dct)
3045 class C(metaclass=CM):
3046 def __init__(self, b):
3047 pass
3048
3049 self.assertEqual(self.signature(CMM),
3050 ((('name', ..., ..., "positional_or_keyword"),
3051 ('bases', ..., ..., "positional_or_keyword"),
3052 ('dct', ..., ..., "positional_or_keyword"),
3053 ('foo', 1, ..., "keyword_only")),
3054 ...))
3055
3056 self.assertEqual(self.signature(CM),
3057 ((('nm', ..., ..., "positional_or_keyword"),
3058 ('bs', ..., ..., "positional_or_keyword"),
3059 ('dt', ..., ..., "positional_or_keyword")),
3060 ...))
3061
3062 self.assertEqual(self.signature(C),
3063 ((('b', ..., ..., "positional_or_keyword"),),
3064 ...))
3065
3066 class CM(type):
3067 def __init__(cls, name, bases, dct, *, bar=2):
3068 return super().__init__(name, bases, dct)
3069 class C(metaclass=CM):
3070 def __init__(self, b):
3071 pass
3072
3073 self.assertEqual(self.signature(CM),
3074 ((('name', ..., ..., "positional_or_keyword"),
3075 ('bases', ..., ..., "positional_or_keyword"),
3076 ('dct', ..., ..., "positional_or_keyword"),
3077 ('bar', 2, ..., "keyword_only")),
3078 ...))
3079
Miss Islington (bot)948e39a2021-07-16 06:25:57 -07003080 def test_signature_on_subclass(self):
3081 class A:
3082 def __new__(cls, a=1, *args, **kwargs):
3083 return object.__new__(cls)
3084 class B(A):
3085 def __init__(self, b):
3086 pass
3087 class C(A):
3088 def __new__(cls, a=1, b=2, *args, **kwargs):
3089 return object.__new__(cls)
3090 class D(A):
3091 pass
3092
3093 self.assertEqual(self.signature(B),
3094 ((('b', ..., ..., "positional_or_keyword"),),
3095 ...))
3096 self.assertEqual(self.signature(C),
3097 ((('a', 1, ..., 'positional_or_keyword'),
3098 ('b', 2, ..., 'positional_or_keyword'),
3099 ('args', ..., ..., 'var_positional'),
3100 ('kwargs', ..., ..., 'var_keyword')),
3101 ...))
3102 self.assertEqual(self.signature(D),
3103 ((('a', 1, ..., 'positional_or_keyword'),
3104 ('args', ..., ..., 'var_positional'),
3105 ('kwargs', ..., ..., 'var_keyword')),
3106 ...))
3107
3108 def test_signature_on_generic_subclass(self):
3109 from typing import Generic, TypeVar
3110
3111 T = TypeVar('T')
3112
3113 class A(Generic[T]):
3114 def __init__(self, *, a: int) -> None:
3115 pass
3116
3117 self.assertEqual(self.signature(A),
3118 ((('a', ..., int, 'keyword_only'),),
3119 None))
3120
Yury Selivanov145dff82014-02-01 13:49:29 -05003121 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3122 "Signature information for builtins requires docstrings")
3123 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003124 # Test classes without user-defined __init__ or __new__
3125 class C: pass
3126 self.assertEqual(str(inspect.signature(C)), '()')
3127 class D(C): pass
3128 self.assertEqual(str(inspect.signature(D)), '()')
3129
3130 # Test meta-classes without user-defined __init__ or __new__
3131 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003132 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08003133 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
3134 self.assertEqual(inspect.signature(C), None)
3135 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
3136 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003137
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003138 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3139 "Signature information for builtins requires docstrings")
3140 def test_signature_on_builtin_class(self):
Antoine Pitrou91f43802019-05-26 17:10:09 +02003141 expected = ('(file, protocol=None, fix_imports=True, '
3142 'buffer_callback=None)')
3143 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003144
3145 class P(_pickle.Pickler): pass
3146 class EmptyTrait: pass
3147 class P2(EmptyTrait, P): pass
Antoine Pitrou91f43802019-05-26 17:10:09 +02003148 self.assertEqual(str(inspect.signature(P)), expected)
3149 self.assertEqual(str(inspect.signature(P2)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003150
3151 class P3(P2):
3152 def __init__(self, spam):
3153 pass
3154 self.assertEqual(str(inspect.signature(P3)), '(spam)')
3155
3156 class MetaP(type):
3157 def __call__(cls, foo, bar):
3158 pass
3159 class P4(P2, metaclass=MetaP):
3160 pass
3161 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
3162
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003163 def test_signature_on_callable_objects(self):
3164 class Foo:
3165 def __call__(self, a):
3166 pass
3167
3168 self.assertEqual(self.signature(Foo()),
3169 ((('a', ..., ..., "positional_or_keyword"),),
3170 ...))
3171
3172 class Spam:
3173 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003174 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003175 inspect.signature(Spam())
3176
3177 class Bar(Spam, Foo):
3178 pass
3179
3180 self.assertEqual(self.signature(Bar()),
3181 ((('a', ..., ..., "positional_or_keyword"),),
3182 ...))
3183
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003184 class Wrapped:
3185 pass
3186 Wrapped.__wrapped__ = lambda a: None
3187 self.assertEqual(self.signature(Wrapped),
3188 ((('a', ..., ..., "positional_or_keyword"),),
3189 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10003190 # wrapper loop:
3191 Wrapped.__wrapped__ = Wrapped
3192 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3193 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003194
3195 def test_signature_on_lambdas(self):
3196 self.assertEqual(self.signature((lambda a=10: a)),
3197 ((('a', 10, ..., "positional_or_keyword"),),
3198 ...))
3199
3200 def test_signature_equality(self):
3201 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003202 self.assertFalse(inspect.signature(foo) == 42)
3203 self.assertTrue(inspect.signature(foo) != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003204 self.assertTrue(inspect.signature(foo) == ALWAYS_EQ)
3205 self.assertFalse(inspect.signature(foo) != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003206
3207 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003208 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3209 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003210 self.assertEqual(
3211 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003212
3213 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003214 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3215 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003216 self.assertNotEqual(
3217 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003218
3219 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003220 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3221 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003222 self.assertNotEqual(
3223 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003224
3225 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003226 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3227 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003228 self.assertNotEqual(
3229 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003230
3231 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003232 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3233 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003234 self.assertNotEqual(
3235 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003236
3237 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003238 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3239 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003240 self.assertNotEqual(
3241 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003242 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003243 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3244 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003245 self.assertNotEqual(
3246 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003247
3248 def foo(*, a, b, c): pass
3249 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003250 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3251 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003252 self.assertEqual(
3253 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003254
3255 def foo(*, a=1, b, c): pass
3256 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003257 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3258 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003259 self.assertEqual(
3260 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003261
3262 def foo(pos, *, a=1, b, c): pass
3263 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003264 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3265 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003266 self.assertEqual(
3267 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003268
3269 def foo(pos, *, a, b, c): pass
3270 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003271 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3272 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003273 self.assertNotEqual(
3274 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003275
3276 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3277 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003278 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3279 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003280 self.assertEqual(
3281 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003282
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003283 def test_signature_hashable(self):
3284 S = inspect.Signature
3285 P = inspect.Parameter
3286
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003287 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003288 foo_sig = inspect.signature(foo)
3289
3290 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3291
3292 self.assertEqual(hash(foo_sig), hash(manual_sig))
3293 self.assertNotEqual(hash(foo_sig),
3294 hash(manual_sig.replace(return_annotation='spam')))
3295
3296 def bar(a) -> 1: pass
3297 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3298
3299 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003300 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003301 hash(inspect.signature(foo))
3302
Pablo Galindob0544ba2021-04-21 12:41:19 +01003303 def foo(a) -> {}: pass
3304 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3305 hash(inspect.signature(foo))
3306
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003307 def test_signature_str(self):
3308 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3309 pass
3310 self.assertEqual(str(inspect.signature(foo)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003311 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003312
3313 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3314 pass
3315 self.assertEqual(str(inspect.signature(foo)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003316 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003317
3318 def foo():
3319 pass
3320 self.assertEqual(str(inspect.signature(foo)), '()')
3321
3322 def test_signature_str_positional_only(self):
3323 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003324 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003325
3326 def test(a_po, *, b, **kwargs):
3327 return a_po, kwargs
3328
3329 sig = inspect.signature(test)
3330 new_params = list(sig.parameters.values())
3331 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3332 test.__signature__ = sig.replace(parameters=new_params)
3333
3334 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003335 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003336
Yury Selivanov2393dca2014-01-27 15:07:58 -05003337 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3338 '(foo, /)')
3339
3340 self.assertEqual(str(S(parameters=[
3341 P('foo', P.POSITIONAL_ONLY),
3342 P('bar', P.VAR_KEYWORD)])),
3343 '(foo, /, **bar)')
3344
3345 self.assertEqual(str(S(parameters=[
3346 P('foo', P.POSITIONAL_ONLY),
3347 P('bar', P.VAR_POSITIONAL)])),
3348 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003349
3350 def test_signature_replace_anno(self):
3351 def test() -> 42:
3352 pass
3353
3354 sig = inspect.signature(test)
3355 sig = sig.replace(return_annotation=None)
3356 self.assertIs(sig.return_annotation, None)
3357 sig = sig.replace(return_annotation=sig.empty)
3358 self.assertIs(sig.return_annotation, sig.empty)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003359 sig = sig.replace(return_annotation=42)
3360 self.assertEqual(sig.return_annotation, 42)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003361 self.assertEqual(sig, inspect.signature(test))
3362
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003363 def test_signature_on_mangled_parameters(self):
3364 class Spam:
3365 def foo(self, __p1:1=2, *, __p2:2=3):
3366 pass
3367 class Ham(Spam):
3368 pass
3369
3370 self.assertEqual(self.signature(Spam.foo),
3371 ((('self', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003372 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3373 ('_Spam__p2', 3, 2, "keyword_only")),
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003374 ...))
3375
3376 self.assertEqual(self.signature(Spam.foo),
3377 self.signature(Ham.foo))
3378
Yury Selivanovda396452014-03-27 12:09:24 -04003379 def test_signature_from_callable_python_obj(self):
3380 class MySignature(inspect.Signature): pass
3381 def foo(a, *, b:1): pass
3382 foo_sig = MySignature.from_callable(foo)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003383 self.assertIsInstance(foo_sig, MySignature)
3384
3385 def test_signature_from_callable_class(self):
3386 # A regression test for a class inheriting its signature from `object`.
3387 class MySignature(inspect.Signature): pass
3388 class foo: pass
3389 foo_sig = MySignature.from_callable(foo)
3390 self.assertIsInstance(foo_sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003391
3392 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3393 "Signature information for builtins requires docstrings")
3394 def test_signature_from_callable_builtin_obj(self):
3395 class MySignature(inspect.Signature): pass
3396 sig = MySignature.from_callable(_pickle.Pickler)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003397 self.assertIsInstance(sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003398
larryhastingsf36ba122018-01-28 11:13:09 -08003399 def test_signature_definition_order_preserved_on_kwonly(self):
3400 for fn in signatures_with_lexicographic_keyword_only_parameters():
3401 signature = inspect.signature(fn)
3402 l = list(signature.parameters)
3403 sorted_l = sorted(l)
3404 self.assertTrue(l)
3405 self.assertEqual(l, sorted_l)
3406 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3407 l = list(signature.parameters)
3408 self.assertEqual(l, unsorted_keyword_only_parameters)
3409
Jens Reidel611836a2020-03-18 03:22:46 +01003410 def test_signater_parameters_is_ordered(self):
3411 p1 = inspect.signature(lambda x, y: None).parameters
3412 p2 = inspect.signature(lambda y, x: None).parameters
3413 self.assertNotEqual(p1, p2)
3414
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003415 def test_signature_annotations_with_local_namespaces(self):
3416 class Foo: ...
3417 def func(foo: Foo) -> int: pass
Pablo Galindob0544ba2021-04-21 12:41:19 +01003418 def func2(foo: Foo, bar: 'Bar') -> int: pass
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003419
3420 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3421 with self.subTest(signature_func = signature_func):
3422 sig1 = signature_func(func)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003423 self.assertEqual(sig1.return_annotation, int)
3424 self.assertEqual(sig1.parameters['foo'].annotation, Foo)
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003425
larryhastings74613a42021-04-29 21:16:28 -07003426 sig2 = signature_func(func, locals=locals())
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003427 self.assertEqual(sig2.return_annotation, int)
3428 self.assertEqual(sig2.parameters['foo'].annotation, Foo)
3429
larryhastings74613a42021-04-29 21:16:28 -07003430 sig3 = signature_func(func2, globals={'Bar': int}, locals=locals())
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003431 self.assertEqual(sig3.return_annotation, int)
3432 self.assertEqual(sig3.parameters['foo'].annotation, Foo)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003433 self.assertEqual(sig3.parameters['bar'].annotation, 'Bar')
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003434
larryhastings74613a42021-04-29 21:16:28 -07003435 def test_signature_eval_str(self):
3436 isa = inspect_stringized_annotations
3437 sig = inspect.Signature
3438 par = inspect.Parameter
3439 PORK = inspect.Parameter.POSITIONAL_OR_KEYWORD
3440 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3441 with self.subTest(signature_func = signature_func):
3442 self.assertEqual(
3443 signature_func(isa.MyClass),
3444 sig(
3445 parameters=(
3446 par('a', PORK),
3447 par('b', PORK),
3448 )))
3449 self.assertEqual(
3450 signature_func(isa.function),
3451 sig(
3452 return_annotation='MyClass',
3453 parameters=(
3454 par('a', PORK, annotation='int'),
3455 par('b', PORK, annotation='str'),
3456 )))
3457 self.assertEqual(
3458 signature_func(isa.function2),
3459 sig(
3460 return_annotation='MyClass',
3461 parameters=(
3462 par('a', PORK, annotation='int'),
3463 par('b', PORK, annotation="'str'"),
3464 par('c', PORK, annotation="MyClass"),
3465 )))
3466 self.assertEqual(
3467 signature_func(isa.function3),
3468 sig(
3469 parameters=(
3470 par('a', PORK, annotation="'int'"),
3471 par('b', PORK, annotation="'str'"),
3472 par('c', PORK, annotation="'MyClass'"),
3473 )))
3474
3475 self.assertEqual(signature_func(isa.UnannotatedClass), sig())
3476 self.assertEqual(signature_func(isa.unannotated_function),
3477 sig(
3478 parameters=(
3479 par('a', PORK),
3480 par('b', PORK),
3481 par('c', PORK),
3482 )))
3483
3484 self.assertEqual(
3485 signature_func(isa.MyClass, eval_str=True),
3486 sig(
3487 parameters=(
3488 par('a', PORK),
3489 par('b', PORK),
3490 )))
3491 self.assertEqual(
3492 signature_func(isa.function, eval_str=True),
3493 sig(
3494 return_annotation=isa.MyClass,
3495 parameters=(
3496 par('a', PORK, annotation=int),
3497 par('b', PORK, annotation=str),
3498 )))
3499 self.assertEqual(
3500 signature_func(isa.function2, 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 par('c', PORK, annotation=isa.MyClass),
3507 )))
3508 self.assertEqual(
3509 signature_func(isa.function3, eval_str=True),
3510 sig(
3511 parameters=(
3512 par('a', PORK, annotation='int'),
3513 par('b', PORK, annotation='str'),
3514 par('c', PORK, annotation='MyClass'),
3515 )))
3516
3517 globalns = {'int': float, 'str': complex}
3518 localns = {'str': tuple, 'MyClass': dict}
3519 with self.assertRaises(NameError):
3520 signature_func(isa.function, eval_str=True, globals=globalns)
3521
3522 self.assertEqual(
3523 signature_func(isa.function, eval_str=True, locals=localns),
3524 sig(
3525 return_annotation=dict,
3526 parameters=(
3527 par('a', PORK, annotation=int),
3528 par('b', PORK, annotation=tuple),
3529 )))
3530
3531 self.assertEqual(
3532 signature_func(isa.function, eval_str=True, globals=globalns, locals=localns),
3533 sig(
3534 return_annotation=dict,
3535 parameters=(
3536 par('a', PORK, annotation=float),
3537 par('b', PORK, annotation=tuple),
3538 )))
3539
3540 def test_signature_none_annotation(self):
3541 class funclike:
3542 # Has to be callable, and have correct
3543 # __code__, __annotations__, __defaults__, __name__,
3544 # and __kwdefaults__ attributes
3545
3546 def __init__(self, func):
3547 self.__name__ = func.__name__
3548 self.__code__ = func.__code__
3549 self.__annotations__ = func.__annotations__
3550 self.__defaults__ = func.__defaults__
3551 self.__kwdefaults__ = func.__kwdefaults__
3552 self.func = func
3553
3554 def __call__(self, *args, **kwargs):
3555 return self.func(*args, **kwargs)
3556
3557 def foo(): pass
3558 foo = funclike(foo)
3559 foo.__annotations__ = None
3560 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3561 with self.subTest(signature_func = signature_func):
3562 self.assertEqual(signature_func(foo), inspect.Signature())
3563 self.assertEqual(inspect.get_annotations(foo), {})
3564
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003565
3566class TestParameterObject(unittest.TestCase):
3567 def test_signature_parameter_kinds(self):
3568 P = inspect.Parameter
3569 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3570 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3571
3572 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3573 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3574
3575 def test_signature_parameter_object(self):
3576 p = inspect.Parameter('foo', default=10,
3577 kind=inspect.Parameter.POSITIONAL_ONLY)
3578 self.assertEqual(p.name, 'foo')
3579 self.assertEqual(p.default, 10)
3580 self.assertIs(p.annotation, p.empty)
3581 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3582
Dong-hee Naa9cab432018-05-30 00:04:08 +09003583 with self.assertRaisesRegex(ValueError, "value '123' is "
3584 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003585 inspect.Parameter('foo', default=10, kind='123')
3586
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003587 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003588 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3589
Yury Selivanov2393dca2014-01-27 15:07:58 -05003590 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003591 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3592
Yury Selivanov2393dca2014-01-27 15:07:58 -05003593 with self.assertRaisesRegex(ValueError,
3594 'is not a valid parameter name'):
3595 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3596
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003597 with self.assertRaisesRegex(ValueError,
3598 'is not a valid parameter name'):
3599 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3600
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003601 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003602 inspect.Parameter('a', default=42,
3603 kind=inspect.Parameter.VAR_KEYWORD)
3604
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003605 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003606 inspect.Parameter('a', default=42,
3607 kind=inspect.Parameter.VAR_POSITIONAL)
3608
3609 p = inspect.Parameter('a', default=42,
3610 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003611 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003612 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3613
3614 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003615 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003616
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003617 def test_signature_parameter_hashable(self):
3618 P = inspect.Parameter
3619 foo = P('foo', kind=P.POSITIONAL_ONLY)
3620 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3621 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3622 default=42)))
3623 self.assertNotEqual(hash(foo),
3624 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3625
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003626 def test_signature_parameter_equality(self):
3627 P = inspect.Parameter
3628 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3629
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003630 self.assertTrue(p == p)
3631 self.assertFalse(p != p)
3632 self.assertFalse(p == 42)
3633 self.assertTrue(p != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003634 self.assertTrue(p == ALWAYS_EQ)
3635 self.assertFalse(p != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003636
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003637 self.assertTrue(p == P('foo', default=42,
3638 kind=inspect.Parameter.KEYWORD_ONLY))
3639 self.assertFalse(p != P('foo', default=42,
3640 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003641
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003642 def test_signature_parameter_replace(self):
3643 p = inspect.Parameter('foo', default=42,
3644 kind=inspect.Parameter.KEYWORD_ONLY)
3645
3646 self.assertIsNot(p, p.replace())
3647 self.assertEqual(p, p.replace())
3648
3649 p2 = p.replace(annotation=1)
3650 self.assertEqual(p2.annotation, 1)
3651 p2 = p2.replace(annotation=p2.empty)
3652 self.assertEqual(p, p2)
3653
3654 p2 = p2.replace(name='bar')
3655 self.assertEqual(p2.name, 'bar')
3656 self.assertNotEqual(p2, p)
3657
Yury Selivanov2393dca2014-01-27 15:07:58 -05003658 with self.assertRaisesRegex(ValueError,
3659 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003660 p2 = p2.replace(name=p2.empty)
3661
3662 p2 = p2.replace(name='foo', default=None)
3663 self.assertIs(p2.default, None)
3664 self.assertNotEqual(p2, p)
3665
3666 p2 = p2.replace(name='foo', default=p2.empty)
3667 self.assertIs(p2.default, p2.empty)
3668
3669
3670 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3671 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3672 self.assertNotEqual(p2, p)
3673
Dong-hee Naa9cab432018-05-30 00:04:08 +09003674 with self.assertRaisesRegex(ValueError,
3675 "value <class 'inspect._empty'> "
3676 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003677 p2 = p2.replace(kind=p2.empty)
3678
3679 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3680 self.assertEqual(p2, p)
3681
3682 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003683 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3684 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003685
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003686 @cpython_only
3687 def test_signature_parameter_implicit(self):
3688 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003689 'implicit arguments must be passed as '
3690 'positional or keyword arguments, '
3691 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003692 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3693
3694 param = inspect.Parameter(
3695 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3696 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3697 self.assertEqual(param.name, 'implicit0')
3698
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003699 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003700 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003701
3702 with self.assertRaises(AttributeError):
3703 p.foo = 'bar'
3704
3705 with self.assertRaises(AttributeError):
3706 p.kind = 123
3707
3708
3709class TestSignatureBind(unittest.TestCase):
3710 @staticmethod
3711 def call(func, *args, **kwargs):
3712 sig = inspect.signature(func)
3713 ba = sig.bind(*args, **kwargs)
3714 return func(*ba.args, **ba.kwargs)
3715
3716 def test_signature_bind_empty(self):
3717 def test():
3718 return 42
3719
3720 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003721 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003722 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003723 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003724 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003725 with self.assertRaisesRegex(
3726 TypeError, "got an unexpected keyword argument 'spam'"):
3727
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003728 self.call(test, spam=1)
3729
3730 def test_signature_bind_var(self):
3731 def test(*args, **kwargs):
3732 return args, kwargs
3733
3734 self.assertEqual(self.call(test), ((), {}))
3735 self.assertEqual(self.call(test, 1), ((1,), {}))
3736 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3737 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3738 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3739 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3740 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3741 ((1, 2), {'foo': 'bar'}))
3742
3743 def test_signature_bind_just_args(self):
3744 def test(a, b, c):
3745 return a, b, c
3746
3747 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3748
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003749 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003750 self.call(test, 1, 2, 3, 4)
3751
Yury Selivanov86872752015-05-19 00:27:49 -04003752 with self.assertRaisesRegex(TypeError,
3753 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003754 self.call(test, 1)
3755
Yury Selivanov86872752015-05-19 00:27:49 -04003756 with self.assertRaisesRegex(TypeError,
3757 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003758 self.call(test)
3759
3760 def test(a, b, c=10):
3761 return a, b, c
3762 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3763 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3764
3765 def test(a=1, b=2, c=3):
3766 return a, b, c
3767 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3768 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3769 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3770
3771 def test_signature_bind_varargs_order(self):
3772 def test(*args):
3773 return args
3774
3775 self.assertEqual(self.call(test), ())
3776 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3777
3778 def test_signature_bind_args_and_varargs(self):
3779 def test(a, b, c=3, *args):
3780 return a, b, c, args
3781
3782 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3783 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3784 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3785 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3786
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003787 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003788 "multiple values for argument 'c'"):
3789 self.call(test, 1, 2, 3, c=4)
3790
3791 def test_signature_bind_just_kwargs(self):
3792 def test(**kwargs):
3793 return kwargs
3794
3795 self.assertEqual(self.call(test), {})
3796 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3797 {'foo': 'bar', 'spam': 'ham'})
3798
3799 def test_signature_bind_args_and_kwargs(self):
3800 def test(a, b, c=3, **kwargs):
3801 return a, b, c, kwargs
3802
3803 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3804 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3805 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3806 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3807 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3808 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3809 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3810 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3811 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3812 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3813 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3814 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3815 (1, 2, 4, {'foo': 'bar'}))
3816 self.assertEqual(self.call(test, c=5, a=4, b=3),
3817 (4, 3, 5, {}))
3818
3819 def test_signature_bind_kwonly(self):
3820 def test(*, foo):
3821 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003822 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003823 'too many positional arguments'):
3824 self.call(test, 1)
3825 self.assertEqual(self.call(test, foo=1), 1)
3826
3827 def test(a, *, foo=1, bar):
3828 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003829 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003830 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003831 self.call(test, 1)
3832
3833 def test(foo, *, bar):
3834 return foo, bar
3835 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3836 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3837
Yury Selivanov86872752015-05-19 00:27:49 -04003838 with self.assertRaisesRegex(
3839 TypeError, "got an unexpected keyword argument 'spam'"):
3840
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003841 self.call(test, bar=2, foo=1, spam=10)
3842
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003843 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003844 'too many positional arguments'):
3845 self.call(test, 1, 2)
3846
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003847 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003848 'too many positional arguments'):
3849 self.call(test, 1, 2, bar=2)
3850
Yury Selivanov86872752015-05-19 00:27:49 -04003851 with self.assertRaisesRegex(
3852 TypeError, "got an unexpected keyword argument 'spam'"):
3853
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003854 self.call(test, 1, bar=2, spam='ham')
3855
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003856 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003857 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003858 self.call(test, 1)
3859
3860 def test(foo, *, bar, **bin):
3861 return foo, bar, bin
3862 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3863 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3864 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3865 (1, 2, {'spam': 'ham'}))
3866 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3867 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003868 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003869 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003870 self.call(test, spam='ham', bar=2)
3871 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3872 (1, 2, {'bin': 1, 'spam': 10}))
3873
3874 def test_signature_bind_arguments(self):
3875 def test(a, *args, b, z=100, **kwargs):
3876 pass
3877 sig = inspect.signature(test)
3878 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3879 # we won't have 'z' argument in the bound arguments object, as we didn't
3880 # pass it to the 'bind'
3881 self.assertEqual(tuple(ba.arguments.items()),
3882 (('a', 10), ('args', (20,)), ('b', 30),
3883 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3884 self.assertEqual(ba.kwargs,
3885 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3886 self.assertEqual(ba.args, (10, 20))
3887
3888 def test_signature_bind_positional_only(self):
3889 P = inspect.Parameter
3890
3891 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3892 return a_po, b_po, c_po, foo, bar, kwargs
3893
3894 sig = inspect.signature(test)
3895 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3896 for name in ('a_po', 'b_po', 'c_po'):
3897 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3898 new_sig = sig.replace(parameters=new_params.values())
3899 test.__signature__ = new_sig
3900
3901 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3902 (1, 2, 4, 5, 6, {}))
3903
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003904 self.assertEqual(self.call(test, 1, 2),
3905 (1, 2, 3, 42, 50, {}))
3906
3907 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3908 (1, 2, 3, 4, 5, {}))
3909
3910 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3911 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3912
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003913 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003914 self.call(test, 1, 2, c_po=4)
3915
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003916 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003917 self.call(test, a_po=1, b_po=2)
3918
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003919 def test_signature_bind_with_self_arg(self):
3920 # Issue #17071: one of the parameters is named "self
3921 def test(a, self, b):
3922 pass
3923 sig = inspect.signature(test)
3924 ba = sig.bind(1, 2, 3)
3925 self.assertEqual(ba.args, (1, 2, 3))
3926 ba = sig.bind(1, self=2, b=3)
3927 self.assertEqual(ba.args, (1, 2, 3))
3928
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003929 def test_signature_bind_vararg_name(self):
3930 def test(a, *args):
3931 return a, args
3932 sig = inspect.signature(test)
3933
Yury Selivanov86872752015-05-19 00:27:49 -04003934 with self.assertRaisesRegex(
3935 TypeError, "got an unexpected keyword argument 'args'"):
3936
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003937 sig.bind(a=0, args=1)
3938
3939 def test(*args, **kwargs):
3940 return args, kwargs
3941 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3942
3943 sig = inspect.signature(test)
3944 ba = sig.bind(args=1)
3945 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3946
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003947 @cpython_only
3948 def test_signature_bind_implicit_arg(self):
3949 # Issue #19611: getcallargs should work with set comprehensions
3950 def make_set():
3951 return {z * z for z in range(5)}
3952 setcomp_code = make_set.__code__.co_consts[1]
3953 setcomp_func = types.FunctionType(setcomp_code, {})
3954
3955 iterator = iter(range(5))
3956 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3957
Pablo Galindof3ef06a2019-10-15 12:40:02 +01003958 def test_signature_bind_posonly_kwargs(self):
3959 def foo(bar, /, **kwargs):
3960 return bar, kwargs.get(bar)
3961
3962 sig = inspect.signature(foo)
3963 result = sig.bind("pos-only", bar="keyword")
3964
3965 self.assertEqual(result.kwargs, {"bar": "keyword"})
3966 self.assertIn(("bar", "pos-only"), result.arguments.items())
3967
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003968
3969class TestBoundArguments(unittest.TestCase):
3970 def test_signature_bound_arguments_unhashable(self):
3971 def foo(a): pass
3972 ba = inspect.signature(foo).bind(1)
3973
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003974 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003975 hash(ba)
3976
3977 def test_signature_bound_arguments_equality(self):
3978 def foo(a): pass
3979 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003980 self.assertTrue(ba == ba)
3981 self.assertFalse(ba != ba)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003982 self.assertTrue(ba == ALWAYS_EQ)
3983 self.assertFalse(ba != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003984
3985 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003986 self.assertTrue(ba == ba2)
3987 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003988
3989 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003990 self.assertFalse(ba == ba3)
3991 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003992 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003993 self.assertTrue(ba == ba3)
3994 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003995
3996 def bar(b): pass
3997 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003998 self.assertFalse(ba == ba4)
3999 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004000
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04004001 def foo(*, a, b): pass
4002 sig = inspect.signature(foo)
4003 ba1 = sig.bind(a=1, b=2)
4004 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03004005 self.assertTrue(ba1 == ba2)
4006 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04004007
Yury Selivanova5d63dd2014-03-27 11:31:43 -04004008 def test_signature_bound_arguments_pickle(self):
4009 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
4010 sig = inspect.signature(foo)
4011 ba = sig.bind(20, 30, z={})
4012
4013 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
4014 with self.subTest(pickle_ver=ver):
4015 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
4016 self.assertEqual(ba, ba_pickled)
4017
Yury Selivanov3f6538f2015-05-14 18:47:17 -04004018 def test_signature_bound_arguments_repr(self):
4019 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
4020 sig = inspect.signature(foo)
4021 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04004022 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04004023
Yury Selivanovb907a512015-05-16 13:45:09 -04004024 def test_signature_bound_arguments_apply_defaults(self):
4025 def foo(a, b=1, *args, c:1={}, **kw): pass
4026 sig = inspect.signature(foo)
4027
4028 ba = sig.bind(20)
4029 ba.apply_defaults()
4030 self.assertEqual(
4031 list(ba.arguments.items()),
4032 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
4033
4034 # Make sure that we preserve the order:
4035 # i.e. 'c' should be *before* 'kw'.
4036 ba = sig.bind(10, 20, 30, d=1)
4037 ba.apply_defaults()
4038 self.assertEqual(
4039 list(ba.arguments.items()),
4040 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
4041
4042 # Make sure that BoundArguments produced by bind_partial()
4043 # are supported.
4044 def foo(a, b): pass
4045 sig = inspect.signature(foo)
4046 ba = sig.bind_partial(20)
4047 ba.apply_defaults()
4048 self.assertEqual(
4049 list(ba.arguments.items()),
4050 [('a', 20)])
4051
4052 # Test no args
4053 def foo(): pass
4054 sig = inspect.signature(foo)
4055 ba = sig.bind()
4056 ba.apply_defaults()
4057 self.assertEqual(list(ba.arguments.items()), [])
4058
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05004059 # Make sure a no-args binding still acquires proper defaults.
4060 def foo(a='spam'): pass
4061 sig = inspect.signature(foo)
4062 ba = sig.bind()
4063 ba.apply_defaults()
4064 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
4065
Rémi Lapeyre2cca8ef2020-01-28 13:47:03 +01004066 def test_signature_bound_arguments_arguments_type(self):
4067 def foo(a): pass
4068 ba = inspect.signature(foo).bind(1)
4069 self.assertIs(type(ba.arguments), dict)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004070
Yury Selivanovd82eddc2014-01-29 11:24:39 -05004071class TestSignaturePrivateHelpers(unittest.TestCase):
4072 def test_signature_get_bound_param(self):
4073 getter = inspect._signature_get_bound_param
4074
4075 self.assertEqual(getter('($self)'), 'self')
4076 self.assertEqual(getter('($self, obj)'), 'self')
4077 self.assertEqual(getter('($cls, /, obj)'), 'cls')
4078
Larry Hastings2623c8c2014-02-08 22:15:29 -08004079 def _strip_non_python_syntax(self, input,
4080 clean_signature, self_parameter, last_positional_only):
4081 computed_clean_signature, \
4082 computed_self_parameter, \
4083 computed_last_positional_only = \
4084 inspect._signature_strip_non_python_syntax(input)
4085 self.assertEqual(computed_clean_signature, clean_signature)
4086 self.assertEqual(computed_self_parameter, self_parameter)
4087 self.assertEqual(computed_last_positional_only, last_positional_only)
4088
4089 def test_signature_strip_non_python_syntax(self):
4090 self._strip_non_python_syntax(
4091 "($module, /, path, mode, *, dir_fd=None, " +
4092 "effective_ids=False,\n follow_symlinks=True)",
4093 "(module, path, mode, *, dir_fd=None, " +
4094 "effective_ids=False, follow_symlinks=True)",
4095 0,
4096 0)
4097
4098 self._strip_non_python_syntax(
4099 "($module, word, salt, /)",
4100 "(module, word, salt)",
4101 0,
4102 2)
4103
4104 self._strip_non_python_syntax(
4105 "(x, y=None, z=None, /)",
4106 "(x, y=None, z=None)",
4107 None,
4108 2)
4109
4110 self._strip_non_python_syntax(
4111 "(x, y=None, z=None)",
4112 "(x, y=None, z=None)",
4113 None,
4114 None)
4115
4116 self._strip_non_python_syntax(
4117 "(x,\n y=None,\n z = None )",
4118 "(x, y=None, z=None)",
4119 None,
4120 None)
4121
4122 self._strip_non_python_syntax(
4123 "",
4124 "",
4125 None,
4126 None)
4127
4128 self._strip_non_python_syntax(
4129 None,
4130 None,
4131 None,
4132 None)
4133
Nick Coghlan9c680b02015-04-13 12:54:54 -04004134class TestSignatureDefinitions(unittest.TestCase):
4135 # This test case provides a home for checking that particular APIs
4136 # have signatures available for introspection
4137
4138 @cpython_only
4139 @unittest.skipIf(MISSING_C_DOCSTRINGS,
4140 "Signature information for builtins requires docstrings")
4141 def test_builtins_have_signatures(self):
4142 # This checks all builtin callables in CPython have signatures
4143 # A few have signatures Signature can't yet handle, so we skip those
4144 # since they will have to wait until PEP 457 adds the required
4145 # introspection support to the inspect module
4146 # Some others also haven't been converted yet for various other
4147 # reasons, so we also skip those for the time being, but design
4148 # the test to fail in order to indicate when it needs to be
4149 # updated.
4150 no_signature = set()
4151 # These need PEP 457 groups
4152 needs_groups = {"range", "slice", "dir", "getattr",
4153 "next", "iter", "vars"}
4154 no_signature |= needs_groups
Joshua Bronsonf0a6fde2021-03-23 18:47:21 -04004155 # These have unrepresentable parameter default values of NULL
4156 needs_null = {"anext"}
4157 no_signature |= needs_null
Nick Coghlan9c680b02015-04-13 12:54:54 -04004158 # These need PEP 457 groups or a signature change to accept None
4159 needs_semantic_update = {"round"}
4160 no_signature |= needs_semantic_update
4161 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04004162 needs_varargs = {"breakpoint", "min", "max", "print",
4163 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04004164 no_signature |= needs_varargs
4165 # These simply weren't covered in the initial AC conversion
4166 # for builtin callables
4167 not_converted_yet = {"open", "__import__"}
4168 no_signature |= not_converted_yet
4169 # These builtin types are expected to provide introspection info
4170 types_with_signatures = set()
4171 # Check the signatures we expect to be there
4172 ns = vars(builtins)
4173 for name, obj in sorted(ns.items()):
4174 if not callable(obj):
4175 continue
4176 # The builtin types haven't been converted to AC yet
4177 if isinstance(obj, type) and (name not in types_with_signatures):
4178 # Note that this also skips all the exception types
4179 no_signature.add(name)
4180 if (name in no_signature):
4181 # Not yet converted
4182 continue
4183 with self.subTest(builtin=name):
4184 self.assertIsNotNone(inspect.signature(obj))
4185 # Check callables that haven't been converted don't claim a signature
4186 # This ensures this test will start failing as more signatures are
4187 # added, so the affected items can be moved into the scope of the
4188 # regression test above
4189 for name in no_signature:
4190 with self.subTest(builtin=name):
4191 self.assertIsNone(obj.__text_signature__)
4192
Serhiy Storchakad53cf992019-05-06 22:40:27 +03004193 def test_python_function_override_signature(self):
4194 def func(*args, **kwargs):
4195 pass
4196 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
4197 sig = inspect.signature(func)
4198 self.assertIsNotNone(sig)
4199 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
4200 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
4201 sig = inspect.signature(func)
4202 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
4203
Yury Selivanovd82eddc2014-01-29 11:24:39 -05004204
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01004205class NTimesUnwrappable:
4206 def __init__(self, n):
4207 self.n = n
4208 self._next = None
4209
4210 @property
4211 def __wrapped__(self):
4212 if self.n <= 0:
4213 raise Exception("Unwrapped too many times")
4214 if self._next is None:
4215 self._next = NTimesUnwrappable(self.n - 1)
4216 return self._next
4217
Nick Coghlane8c45d62013-07-28 20:00:01 +10004218class TestUnwrap(unittest.TestCase):
4219
4220 def test_unwrap_one(self):
4221 def func(a, b):
4222 return a + b
4223 wrapper = functools.lru_cache(maxsize=20)(func)
4224 self.assertIs(inspect.unwrap(wrapper), func)
4225
4226 def test_unwrap_several(self):
4227 def func(a, b):
4228 return a + b
4229 wrapper = func
4230 for __ in range(10):
4231 @functools.wraps(wrapper)
4232 def wrapper():
4233 pass
4234 self.assertIsNot(wrapper.__wrapped__, func)
4235 self.assertIs(inspect.unwrap(wrapper), func)
4236
4237 def test_stop(self):
4238 def func1(a, b):
4239 return a + b
4240 @functools.wraps(func1)
4241 def func2():
4242 pass
4243 @functools.wraps(func2)
4244 def wrapper():
4245 pass
4246 func2.stop_here = 1
4247 unwrapped = inspect.unwrap(wrapper,
4248 stop=(lambda f: hasattr(f, "stop_here")))
4249 self.assertIs(unwrapped, func2)
4250
4251 def test_cycle(self):
4252 def func1(): pass
4253 func1.__wrapped__ = func1
4254 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4255 inspect.unwrap(func1)
4256
4257 def func2(): pass
4258 func2.__wrapped__ = func1
4259 func1.__wrapped__ = func2
4260 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4261 inspect.unwrap(func1)
4262 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4263 inspect.unwrap(func2)
4264
4265 def test_unhashable(self):
4266 def func(): pass
4267 func.__wrapped__ = None
4268 class C:
4269 __hash__ = None
4270 __wrapped__ = func
4271 self.assertIsNone(inspect.unwrap(C()))
4272
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01004273 def test_recursion_limit(self):
4274 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
4275 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4276 inspect.unwrap(obj)
4277
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004278class TestMain(unittest.TestCase):
4279 def test_only_source(self):
4280 module = importlib.import_module('unittest')
4281 rc, out, err = assert_python_ok('-m', 'inspect',
4282 'unittest')
4283 lines = out.decode().splitlines()
4284 # ignore the final newline
4285 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
4286 self.assertEqual(err, b'')
4287
Yury Selivanov42407ab2014-06-23 10:23:50 -07004288 def test_custom_getattr(self):
4289 def foo():
4290 pass
4291 foo.__signature__ = 42
4292 with self.assertRaises(TypeError):
4293 inspect.signature(foo)
4294
Brett Cannon634a8fc2013-10-02 10:25:42 -04004295 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04004296 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004297 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004298 rc, out, err = assert_python_ok('-m', 'inspect',
4299 'concurrent.futures:ThreadPoolExecutor')
4300 lines = out.decode().splitlines()
4301 # ignore the final newline
4302 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04004303 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004304 self.assertEqual(err, b'')
4305
4306 def test_builtins(self):
4307 module = importlib.import_module('unittest')
4308 _, out, err = assert_python_failure('-m', 'inspect',
4309 'sys')
4310 lines = err.decode().splitlines()
4311 self.assertEqual(lines, ["Can't get info for builtin modules."])
4312
4313 def test_details(self):
4314 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01004315 args = support.optim_args_from_interpreter_flags()
4316 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004317 'unittest', '--details')
4318 output = out.decode()
4319 # Just a quick sanity check on the output
4320 self.assertIn(module.__name__, output)
4321 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01004322 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004323 self.assertEqual(err, b'')
4324
4325
Yury Selivanovef1e7502014-12-08 16:05:34 -05004326class TestReload(unittest.TestCase):
4327
4328 src_before = textwrap.dedent("""\
4329def foo():
4330 print("Bla")
4331 """)
4332
4333 src_after = textwrap.dedent("""\
4334def foo():
4335 print("Oh no!")
4336 """)
4337
4338 def assertInspectEqual(self, path, source):
4339 inspected_src = inspect.getsource(source)
Inada Naokifb786922021-04-06 11:18:41 +09004340 with open(path, encoding='utf-8') as src:
Yury Selivanovef1e7502014-12-08 16:05:34 -05004341 self.assertEqual(
4342 src.read().splitlines(True),
4343 inspected_src.splitlines(True)
4344 )
4345
4346 def test_getsource_reload(self):
4347 # see issue 1218234
4348 with _ready_to_import('reload_bug', self.src_before) as (name, path):
4349 module = importlib.import_module(name)
4350 self.assertInspectEqual(path, module)
Inada Naokifb786922021-04-06 11:18:41 +09004351 with open(path, 'w', encoding='utf-8') as src:
Yury Selivanovef1e7502014-12-08 16:05:34 -05004352 src.write(self.src_after)
4353 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004354
Nick Coghlane8c45d62013-07-28 20:00:01 +10004355
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004356def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00004357 run_unittest(
Irit Katriel6e1eec72020-12-04 16:45:38 +00004358 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBlockComments,
4359 TestBuggyCases, TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00004360 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00004361 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004362 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04004363 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04004364 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04004365 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Miss Islington (bot)f468ede2021-07-30 10:46:42 -07004366 TestGetCoroutineState, TestGettingSourceOfToplevelFrames,
4367 TestGetsourceInteractive,
Michael Foord95fc51d2010-11-20 15:07:30 +00004368 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00004369
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004370if __name__ == "__main__":
4371 test_main()