blob: 93ff2f85df193d0435ae9e716bc33fc7b5e45a92 [file] [log] [blame]
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001import builtins
Guido van Rossum813b0e52007-05-21 18:11:34 +00002import collections
Larry Hastings5c661892014-01-24 06:17:25 -08003import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10004import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10005import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08006import inspect
7import io
8import linecache
9import os
Christian Heimesa3538eb2007-11-06 11:44:48 +000010from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080011import _pickle
Yury Selivanova5d63dd2014-03-27 11:31:43 -040012import pickle
Larry Hastings5c661892014-01-24 06:17:25 -080013import shutil
14import sys
15import types
Yury Selivanovef1e7502014-12-08 16:05:34 -050016import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080017import unicodedata
18import unittest
Yury Selivanova773de02014-02-21 18:30:53 -050019import unittest.mock
Yury Selivanov75445082015-05-11 22:57:16 -040020import warnings
Larry Hastings5c661892014-01-24 06:17:25 -080021
Brett Cannon634a8fc2013-10-02 10:25:42 -040022try:
23 from concurrent.futures import ThreadPoolExecutor
24except ImportError:
25 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000026
Serhiy Storchakabedce352021-09-19 22:36:03 +030027from test.support import cpython_only
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +030028from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ
Hai Shic7decc22020-08-04 23:53:12 +080029from test.support.import_helper import DirsOnSysPath
30from test.support.os_helper import TESTFN
Berker Peksagce643912015-05-06 06:33:17 +030031from test.support.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000032from test import inspect_fodder as mod
33from test import inspect_fodder2 as mod2
Victor Stinner9def2842016-01-18 12:15:08 +010034from test import support
larryhastings74613a42021-04-29 21:16:28 -070035from test import inspect_stock_annotations
36from test import inspect_stringized_annotations
37from test import inspect_stringized_annotations_2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000038
Yury Selivanovef1e7502014-12-08 16:05:34 -050039from test.test_import import _ready_to_import
40
R. David Murray74b89242009-05-13 17:33:03 +000041
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000042# Functions tested in this suite:
43# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000044# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
45# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
Berker Peksagfa3922c2015-07-31 04:11:29 +030046# getclasstree, getargvalues, formatargspec, formatargvalues,
Christian Heimes7131fd92008-02-19 14:21:46 +000047# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000048
Nick Coghlanf088e5e2008-12-14 11:50:48 +000049# NOTE: There are some additional tests relating to interaction with
50# zipimport in the test_zipimport_support test module.
51
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000052modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000053if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000054 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000055
Christian Heimesa3538eb2007-11-06 11:44:48 +000056# Normalize file names: on Windows, the case of file names of compiled
57# modules depends on the path used to start the python executable.
58modfile = normcase(modfile)
59
60def revise(filename, *args):
61 return (normcase(filename),) + args
62
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000063git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000064
larryhastingsf36ba122018-01-28 11:13:09 -080065
66def signatures_with_lexicographic_keyword_only_parameters():
67 """
68 Yields a whole bunch of functions with only keyword-only parameters,
69 where those parameters are always in lexicographically sorted order.
70 """
71 parameters = ['a', 'bar', 'c', 'delta', 'ephraim', 'magical', 'yoyo', 'z']
72 for i in range(1, 2**len(parameters)):
73 p = []
74 bit = 1
75 for j in range(len(parameters)):
76 if i & (bit << j):
77 p.append(parameters[j])
78 fn_text = "def foo(*, " + ", ".join(p) + "): pass"
79 symbols = {}
80 exec(fn_text, symbols, symbols)
81 yield symbols['foo']
82
83
84def unsorted_keyword_only_parameters_fn(*, throw, out, the, baby, with_,
85 the_, bathwater):
86 pass
87
88unsorted_keyword_only_parameters = 'throw out the baby with_ the_ bathwater'.split()
89
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000090class IsTestBase(unittest.TestCase):
91 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
92 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000093 inspect.ismodule, inspect.istraceback,
Yury Selivanov75445082015-05-11 22:57:16 -040094 inspect.isgenerator, inspect.isgeneratorfunction,
Yury Selivanoveb636452016-09-08 22:01:51 -070095 inspect.iscoroutine, inspect.iscoroutinefunction,
96 inspect.isasyncgen, inspect.isasyncgenfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000097
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000098 def istest(self, predicate, exp):
99 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000100 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000101
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000102 for other in self.predicates - set([predicate]):
Yury Selivanov75445082015-05-11 22:57:16 -0400103 if (predicate == inspect.isgeneratorfunction or \
Yury Selivanoveb636452016-09-08 22:01:51 -0700104 predicate == inspect.isasyncgenfunction or \
Yury Selivanov75445082015-05-11 22:57:16 -0400105 predicate == inspect.iscoroutinefunction) and \
Christian Heimes7131fd92008-02-19 14:21:46 +0000106 other == inspect.isfunction:
107 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000108 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000109
Christian Heimes7131fd92008-02-19 14:21:46 +0000110def generator_function_example(self):
111 for i in range(2):
112 yield i
113
Yury Selivanoveb636452016-09-08 22:01:51 -0700114async def async_generator_function_example(self):
115 async for i in range(2):
116 yield i
117
Yury Selivanov75445082015-05-11 22:57:16 -0400118async def coroutine_function_example(self):
119 return 'spam'
120
121@types.coroutine
122def gen_coroutine_function_example(self):
123 yield
124 return 'spam'
125
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000126class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +0000127
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000128 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200129 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000130 self.istest(inspect.isbuiltin, 'sys.exit')
131 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +0000132 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200133 try:
134 1/0
135 except:
136 tb = sys.exc_info()[2]
137 self.istest(inspect.isframe, 'tb.tb_frame')
138 self.istest(inspect.istraceback, 'tb')
139 if hasattr(types, 'GetSetDescriptorType'):
140 self.istest(inspect.isgetsetdescriptor,
141 'type(tb.tb_frame).f_locals')
142 else:
143 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
144 finally:
145 # Clear traceback and all the frames and local variables hanging to it.
146 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000147 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000148 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000149 self.istest(inspect.ismethod, 'git.argue')
Jeroen Demeyerfcef60f2019-04-02 16:03:42 +0200150 self.istest(inspect.ismethod, 'mod.custom_method')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000151 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000152 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000153 self.istest(inspect.isgenerator, '(x for x in range(2))')
154 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanoveb636452016-09-08 22:01:51 -0700155 self.istest(inspect.isasyncgen,
156 'async_generator_function_example(1)')
157 self.istest(inspect.isasyncgenfunction,
158 'async_generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400159
160 with warnings.catch_warnings():
161 warnings.simplefilter("ignore")
162 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
163 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
164
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000165 if hasattr(types, 'MemberDescriptorType'):
166 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
167 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000168 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000169
Yury Selivanov75445082015-05-11 22:57:16 -0400170 def test_iscoroutine(self):
Pablo Galindo7cd25432018-10-26 12:19:14 +0100171 async_gen_coro = async_generator_function_example(1)
Yury Selivanov75445082015-05-11 22:57:16 -0400172 gen_coro = gen_coroutine_function_example(1)
173 coro = coroutine_function_example(1)
174
Yury Selivanov5376ba92015-06-22 12:19:30 -0400175 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400176 inspect.iscoroutinefunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100177 self.assertFalse(
178 inspect.iscoroutinefunction(
179 functools.partial(functools.partial(
180 gen_coroutine_function_example))))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400181 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400182
183 self.assertTrue(
184 inspect.isgeneratorfunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100185 self.assertTrue(
186 inspect.isgeneratorfunction(
187 functools.partial(functools.partial(
188 gen_coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400189 self.assertTrue(inspect.isgenerator(gen_coro))
190
191 self.assertTrue(
192 inspect.iscoroutinefunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100193 self.assertTrue(
194 inspect.iscoroutinefunction(
195 functools.partial(functools.partial(
196 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400197 self.assertTrue(inspect.iscoroutine(coro))
198
199 self.assertFalse(
200 inspect.isgeneratorfunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100201 self.assertFalse(
202 inspect.isgeneratorfunction(
203 functools.partial(functools.partial(
204 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400205 self.assertFalse(inspect.isgenerator(coro))
206
Pablo Galindo7cd25432018-10-26 12:19:14 +0100207 self.assertTrue(
208 inspect.isasyncgenfunction(async_generator_function_example))
209 self.assertTrue(
210 inspect.isasyncgenfunction(
211 functools.partial(functools.partial(
212 async_generator_function_example))))
213 self.assertTrue(inspect.isasyncgen(async_gen_coro))
214
215 coro.close(); gen_coro.close(); # silence warnings
Yury Selivanov75445082015-05-11 22:57:16 -0400216
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400217 def test_isawaitable(self):
218 def gen(): yield
219 self.assertFalse(inspect.isawaitable(gen()))
220
221 coro = coroutine_function_example(1)
222 gen_coro = gen_coroutine_function_example(1)
223
224 self.assertTrue(inspect.isawaitable(coro))
225 self.assertTrue(inspect.isawaitable(gen_coro))
226
227 class Future:
228 def __await__():
229 pass
230 self.assertTrue(inspect.isawaitable(Future()))
231 self.assertFalse(inspect.isawaitable(Future))
232
233 class NotFuture: pass
234 not_fut = NotFuture()
235 not_fut.__await__ = lambda: None
236 self.assertFalse(inspect.isawaitable(not_fut))
237
238 coro.close(); gen_coro.close() # silence warnings
239
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000240 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000241 self.assertTrue(inspect.isroutine(mod.spam))
242 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000243
Benjamin Petersonc4656002009-01-17 22:41:18 +0000244 def test_isclass(self):
245 self.istest(inspect.isclass, 'mod.StupidGit')
246 self.assertTrue(inspect.isclass(list))
247
248 class CustomGetattr(object):
249 def __getattr__(self, attr):
250 return None
251 self.assertFalse(inspect.isclass(CustomGetattr()))
252
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000253 def test_get_slot_members(self):
254 class C(object):
255 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000256 x = C()
257 x.a = 42
258 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000259 self.assertIn('a', members)
260 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000261
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000262 def test_isabstract(self):
263 from abc import ABCMeta, abstractmethod
264
265 class AbstractClassExample(metaclass=ABCMeta):
266
267 @abstractmethod
268 def foo(self):
269 pass
270
271 class ClassExample(AbstractClassExample):
272 def foo(self):
273 pass
274
275 a = ClassExample()
276
277 # Test general behaviour.
278 self.assertTrue(inspect.isabstract(AbstractClassExample))
279 self.assertFalse(inspect.isabstract(ClassExample))
280 self.assertFalse(inspect.isabstract(a))
281 self.assertFalse(inspect.isabstract(int))
282 self.assertFalse(inspect.isabstract(5))
283
Natefcfe80e2017-04-24 10:06:15 -0700284 def test_isabstract_during_init_subclass(self):
285 from abc import ABCMeta, abstractmethod
286 isabstract_checks = []
287 class AbstractChecker(metaclass=ABCMeta):
288 def __init_subclass__(cls):
289 isabstract_checks.append(inspect.isabstract(cls))
290 class AbstractClassExample(AbstractChecker):
291 @abstractmethod
292 def foo(self):
293 pass
294 class ClassExample(AbstractClassExample):
295 def foo(self):
296 pass
297 self.assertEqual(isabstract_checks, [True, False])
298
299 isabstract_checks.clear()
300 class AbstractChild(AbstractClassExample):
301 pass
302 class AbstractGrandchild(AbstractChild):
303 pass
304 class ConcreteGrandchild(ClassExample):
305 pass
306 self.assertEqual(isabstract_checks, [True, True, False])
307
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000308
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000309class TestInterpreterStack(IsTestBase):
310 def __init__(self, *args, **kwargs):
311 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000312
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000313 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000314
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000315 def test_abuse_done(self):
316 self.istest(inspect.istraceback, 'git.ex[2]')
317 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000318
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000319 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000320 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000321 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000322 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000323 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000324 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000325 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000326 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000327 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000328 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400329 # Test named tuple fields
330 record = mod.st[0]
331 self.assertIs(record.frame, mod.fr)
332 self.assertEqual(record.lineno, 16)
333 self.assertEqual(record.filename, mod.__file__)
334 self.assertEqual(record.function, 'eggs')
335 self.assertIn('inspect.stack()', record.code_context[0])
336 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000337
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000338 def test_trace(self):
339 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000340 self.assertEqual(revise(*git.tr[0][1:]),
341 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
342 self.assertEqual(revise(*git.tr[1][1:]),
343 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
344 self.assertEqual(revise(*git.tr[2][1:]),
345 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000346
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000347 def test_frame(self):
348 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
349 self.assertEqual(args, ['x', 'y'])
350 self.assertEqual(varargs, None)
351 self.assertEqual(varkw, None)
352 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
353 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
354 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000355
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000356 def test_previous_frame(self):
357 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000358 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000359 self.assertEqual(varargs, 'g')
360 self.assertEqual(varkw, 'h')
361 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000362 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000363
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000364class GetSourceBase(unittest.TestCase):
365 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000366 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000367
Yury Selivanov6738b112015-05-16 10:10:21 -0400368 def setUp(self):
Inada Naokifb786922021-04-06 11:18:41 +0900369 with open(inspect.getsourcefile(self.fodderModule), encoding="utf-8") as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000370 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000371
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000372 def sourcerange(self, top, bottom):
373 lines = self.source.split("\n")
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700374 return "\n".join(lines[top-1:bottom]) + ("\n" if bottom else "")
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000375
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000376 def assertSourceEqual(self, obj, top, bottom):
377 self.assertEqual(inspect.getsource(obj),
378 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000379
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700380class SlotUser:
381 'Docstrings for __slots__'
382 __slots__ = {'power': 'measured in kilowatts',
383 'distance': 'measured in kilometers'}
384
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000385class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000386 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000387
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000388 def test_getclasses(self):
389 classes = inspect.getmembers(mod, inspect.isclass)
390 self.assertEqual(classes,
391 [('FesteringGob', mod.FesteringGob),
392 ('MalodorousPervert', mod.MalodorousPervert),
393 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300394 ('StupidGit', mod.StupidGit),
395 ('Tit', mod.MalodorousPervert),
Irit Katriel6e1eec72020-12-04 16:45:38 +0000396 ('WhichComments', mod.WhichComments),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300397 ])
398 tree = inspect.getclasstree([cls[1] for cls in classes])
399 self.assertEqual(tree,
400 [(object, ()),
401 [(mod.ParrotDroppings, (object,)),
402 [(mod.FesteringGob, (mod.MalodorousPervert,
403 mod.ParrotDroppings))
404 ],
405 (mod.StupidGit, (object,)),
406 [(mod.MalodorousPervert, (mod.StupidGit,)),
407 [(mod.FesteringGob, (mod.MalodorousPervert,
408 mod.ParrotDroppings))
409 ]
Irit Katriel6e1eec72020-12-04 16:45:38 +0000410 ],
411 (mod.WhichComments, (object,),)
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300412 ]
413 ])
414 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000415 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000416 [(object, ()),
417 [(mod.ParrotDroppings, (object,)),
418 (mod.StupidGit, (object,)),
419 [(mod.MalodorousPervert, (mod.StupidGit,)),
420 [(mod.FesteringGob, (mod.MalodorousPervert,
421 mod.ParrotDroppings))
422 ]
Irit Katriel6e1eec72020-12-04 16:45:38 +0000423 ],
424 (mod.WhichComments, (object,),)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000425 ]
426 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000427
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000428 def test_getfunctions(self):
429 functions = inspect.getmembers(mod, inspect.isfunction)
430 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300431 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000432 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000433
R. David Murray378c0cf2010-02-24 01:46:21 +0000434 @unittest.skipIf(sys.flags.optimize >= 2,
435 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000436 def test_getdoc(self):
437 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
438 self.assertEqual(inspect.getdoc(mod.StupidGit),
439 'A longer,\n\nindented\n\ndocstring.')
440 self.assertEqual(inspect.getdoc(git.abuse),
441 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700442 self.assertEqual(inspect.getdoc(SlotUser.power),
443 'measured in kilowatts')
444 self.assertEqual(inspect.getdoc(SlotUser.distance),
445 'measured in kilometers')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000446
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300447 @unittest.skipIf(sys.flags.optimize >= 2,
448 "Docstrings are omitted with -O2 and above")
449 def test_getdoc_inherited(self):
Serhiy Storchaka08b47c32020-05-18 20:25:07 +0300450 self.assertEqual(inspect.getdoc(mod.FesteringGob),
451 'A longer,\n\nindented\n\ndocstring.')
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300452 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
453 'Another\n\ndocstring\n\ncontaining\n\ntabs')
454 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
455 'Another\n\ndocstring\n\ncontaining\n\ntabs')
456 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
457 'The automatic gainsaying.')
458
459 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
460 def test_finddoc(self):
461 finddoc = inspect._finddoc
Serhiy Storchaka08b47c32020-05-18 20:25:07 +0300462 self.assertEqual(finddoc(int), int.__doc__)
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300463 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
464 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
465 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
466 self.assertEqual(finddoc(int.real), int.real.__doc__)
467
Georg Brandl0c77a822008-06-10 16:37:50 +0000468 def test_cleandoc(self):
469 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
470 'An\nindented\ndocstring.')
471
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000472 def test_getcomments(self):
473 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
474 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530475 self.assertEqual(inspect.getcomments(mod2.cls160), '# line 159\n')
Marco Buttu3f2155f2017-03-17 09:50:23 +0100476 # If the object source file is not available, return None.
477 co = compile('x=1', '_non_existing_filename.py', 'exec')
478 self.assertIsNone(inspect.getcomments(co))
479 # If the object has been defined in C, return None.
480 self.assertIsNone(inspect.getcomments(list))
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000481
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000482 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000483 # Check actual module
484 self.assertEqual(inspect.getmodule(mod), mod)
485 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000486 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000487 # Check a method (no __module__ attribute, falls back to filename)
488 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
489 # Do it again (check the caching isn't broken)
490 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
491 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000492 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000493 # Check filename override
494 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000495
Miss Islington (bot)cfdd7d22021-11-02 15:23:43 -0700496 def test_getmodule_file_not_found(self):
497 # See bpo-45406
498 def _getabsfile(obj, _filename):
499 raise FileNotFoundError('bad file')
500 with unittest.mock.patch('inspect.getabsfile', _getabsfile):
501 f = inspect.currentframe()
502 self.assertIsNone(inspect.getmodule(f))
503 inspect.getouterframes(f) # smoke test
504
Berker Peksagff0e3b72017-01-02 06:57:43 +0300505 def test_getframeinfo_get_first_line(self):
506 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
507 self.assertEqual(frame_info.code_context[0], "# line 1\n")
508 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
509
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000510 def test_getsource(self):
511 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200512 self.assertSourceEqual(mod.StupidGit, 21, 51)
513 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000514
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000515 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000516 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
517 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000518 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100519 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000520 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000521 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200522 try:
523 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
524 finally:
525 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000526
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000527 def test_getfile(self):
528 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000529
Philipp Ad407d2a2019-06-08 14:05:46 +0200530 def test_getfile_builtin_module(self):
531 with self.assertRaises(TypeError) as e:
532 inspect.getfile(sys)
533 self.assertTrue(str(e.exception).startswith('<module'))
534
535 def test_getfile_builtin_class(self):
536 with self.assertRaises(TypeError) as e:
537 inspect.getfile(int)
538 self.assertTrue(str(e.exception).startswith('<class'))
539
540 def test_getfile_builtin_function_or_method(self):
541 with self.assertRaises(TypeError) as e_abs:
542 inspect.getfile(abs)
543 self.assertIn('expected, got', str(e_abs.exception))
544 with self.assertRaises(TypeError) as e_append:
545 inspect.getfile(list.append)
546 self.assertIn('expected, got', str(e_append.exception))
547
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500548 def test_getfile_class_without_module(self):
549 class CM(type):
550 @property
551 def __module__(cls):
552 raise AttributeError
553 class C(metaclass=CM):
554 pass
555 with self.assertRaises(TypeError):
556 inspect.getfile(C)
557
Thomas Kluyvere968bc732017-10-24 13:42:36 +0100558 def test_getfile_broken_repr(self):
559 class ErrorRepr:
560 def __repr__(self):
561 raise Exception('xyz')
562 er = ErrorRepr()
563 with self.assertRaises(TypeError):
564 inspect.getfile(er)
565
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000566 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000567 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000568 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000569 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000570 m.__file__ = "<string>" # hopefully not a real filename...
571 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000572 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000573 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000574 del sys.modules[name]
575 inspect.getmodule(compile('a=10','','single'))
576
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500577 def test_proceed_with_fake_filename(self):
578 '''doctest monkeypatches linecache to enable inspection'''
579 fn, source = '<test>', 'def x(): pass\n'
580 getlines = linecache.getlines
581 def monkey(filename, module_globals=None):
582 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300583 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500584 else:
585 return getlines(filename, module_globals)
586 linecache.getlines = monkey
587 try:
588 ns = {}
589 exec(compile(source, fn, 'single'), ns)
590 inspect.getsource(ns["x"])
591 finally:
592 linecache.getlines = getlines
593
Antoine Pitroua8723a02015-04-15 00:41:29 +0200594 def test_getsource_on_code_object(self):
595 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
596
Miss Islington (bot)f468ede2021-07-30 10:46:42 -0700597class TestGetsourceInteractive(unittest.TestCase):
Miss Islington (bot)f468ede2021-07-30 10:46:42 -0700598 def test_getclasses_interactive(self):
Miss Islington (bot)bc2841c2021-08-03 06:07:59 -0700599 # bpo-44648: simulate a REPL session;
600 # there is no `__file__` in the __main__ module
601 code = "import sys, inspect; \
602 assert not hasattr(sys.modules['__main__'], '__file__'); \
603 A = type('A', (), {}); \
604 inspect.getsource(A)"
605 _, _, stderr = assert_python_failure("-c", code, __isolated=True)
606 self.assertIn(b'OSError: source code not available', stderr)
Miss Islington (bot)f468ede2021-07-30 10:46:42 -0700607
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700608class TestGettingSourceOfToplevelFrames(GetSourceBase):
609 fodderModule = mod
610
611 def test_range_toplevel_frame(self):
612 self.maxDiff = None
613 self.assertSourceEqual(mod.currentframe, 1, None)
614
615 def test_range_traceback_toplevel_frame(self):
616 self.assertSourceEqual(mod.tb, 1, None)
617
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000618class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000619 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000620
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000621 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000622 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000623
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000624 def test_replacing_decorator(self):
625 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000626
Yury Selivanov081bbf62014-09-26 17:34:54 -0400627 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200628 self.assertSourceEqual(mod2.real, 130, 132)
629
630 def test_decorator_with_lambda(self):
631 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400632
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000633class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000634 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000635 def test_oneline_lambda(self):
636 # Test inspect.getsource with a one-line lambda function.
637 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000638
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000639 def test_threeline_lambda(self):
640 # Test inspect.getsource with a three-line lambda function,
641 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000642 self.assertSourceEqual(mod2.tll, 28, 30)
643
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000644 def test_twoline_indented_lambda(self):
645 # Test inspect.getsource with a two-line lambda function,
646 # where the second line _is_ indented.
647 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000648
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000649 def test_onelinefunc(self):
650 # Test inspect.getsource with a regular one-line function.
651 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000652
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000653 def test_manyargs(self):
654 # Test inspect.getsource with a regular function where
655 # the arguments are on two lines and _not_ indented and
656 # the body on the second line with the last arguments.
657 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000658
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000659 def test_twolinefunc(self):
660 # Test inspect.getsource with a regular function where
661 # the body is on two lines, following the argument list and
662 # continued on the next line by a \\.
663 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000664
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000665 def test_lambda_in_list(self):
666 # Test inspect.getsource with a one-line lambda function
667 # defined in a list, indented.
668 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000669
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000670 def test_anonymous(self):
671 # Test inspect.getsource with a lambda function defined
672 # as argument to another function.
673 self.assertSourceEqual(mod2.anonymous, 55, 55)
674
Irit Katriel6e1eec72020-12-04 16:45:38 +0000675class TestBlockComments(GetSourceBase):
676 fodderModule = mod
677
678 def test_toplevel_class(self):
679 self.assertSourceEqual(mod.WhichComments, 96, 114)
680
681 def test_class_method(self):
682 self.assertSourceEqual(mod.WhichComments.f, 99, 104)
683
684 def test_class_async_method(self):
685 self.assertSourceEqual(mod.WhichComments.asyncf, 109, 112)
686
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000687class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000688 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000689
690 def test_with_comment(self):
691 self.assertSourceEqual(mod2.with_comment, 58, 59)
692
693 def test_multiline_sig(self):
694 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
695
Armin Rigodd5c0232005-09-25 11:45:45 +0000696 def test_nested_class(self):
697 self.assertSourceEqual(mod2.func69().func71, 71, 72)
698
699 def test_one_liner_followed_by_non_name(self):
700 self.assertSourceEqual(mod2.func77, 77, 77)
701
702 def test_one_liner_dedent_non_name(self):
703 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
704
705 def test_with_comment_instead_of_docstring(self):
706 self.assertSourceEqual(mod2.func88, 88, 90)
707
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000708 def test_method_in_dynamic_class(self):
709 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
710
R David Murray32562d72014-10-03 11:15:38 -0400711 # This should not skip for CPython, but might on a repackaged python where
712 # unicodedata is not an external module, or on pypy.
713 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
714 unicodedata.__file__.endswith('.py'),
715 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000716 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200717 self.assertRaises(OSError, inspect.getsource, unicodedata)
718 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000719
R. David Murraya1b37402010-06-17 02:04:29 +0000720 def test_findsource_code_in_linecache(self):
721 lines = ["x=1"]
722 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200723 self.assertRaises(OSError, inspect.findsource, co)
724 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000725 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200726 try:
727 self.assertEqual(inspect.findsource(co), (lines,0))
728 self.assertEqual(inspect.getsource(co), lines[0])
729 finally:
730 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000731
Ezio Melotti1b145922013-03-30 05:17:24 +0200732 def test_findsource_without_filename(self):
733 for fname in ['', '<string>']:
734 co = compile('x=1', fname, "exec")
735 self.assertRaises(IOError, inspect.findsource, co)
736 self.assertRaises(IOError, inspect.getsource, co)
737
Irit Katriel2e0760b2020-12-04 21:22:03 +0000738 def test_findsource_with_out_of_bounds_lineno(self):
739 mod_len = len(inspect.getsource(mod))
740 src = '\n' * 2* mod_len + "def f(): pass"
741 co = compile(src, mod.__file__, "exec")
742 g, l = {}, {}
743 eval(co, g, l)
744 func = l['f']
745 self.assertEqual(func.__code__.co_firstlineno, 1+2*mod_len)
746 with self.assertRaisesRegex(IOError, "lineno is out of bounds"):
747 inspect.findsource(func)
748
Antoine Pitroua8723a02015-04-15 00:41:29 +0200749 def test_getsource_on_method(self):
750 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
751
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300752 def test_nested_func(self):
753 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
754
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530755 def test_class_definition_in_multiline_string_definition(self):
756 self.assertSourceEqual(mod2.cls149, 149, 152)
757
758 def test_class_definition_in_multiline_comment(self):
759 self.assertSourceEqual(mod2.cls160, 160, 163)
760
761 def test_nested_class_definition_indented_string(self):
762 self.assertSourceEqual(mod2.cls173.cls175, 175, 176)
763
764 def test_nested_class_definition(self):
765 self.assertSourceEqual(mod2.cls183, 183, 188)
766 self.assertSourceEqual(mod2.cls183.cls185, 185, 188)
767
768 def test_class_decorator(self):
769 self.assertSourceEqual(mod2.cls196, 194, 201)
770 self.assertSourceEqual(mod2.cls196.cls200, 198, 201)
771
772 def test_class_inside_conditional(self):
773 self.assertSourceEqual(mod2.cls238, 238, 240)
774 self.assertSourceEqual(mod2.cls238.cls239, 239, 240)
775
776 def test_multiple_children_classes(self):
777 self.assertSourceEqual(mod2.cls203, 203, 209)
778 self.assertSourceEqual(mod2.cls203.cls204, 204, 206)
779 self.assertSourceEqual(mod2.cls203.cls204.cls205, 205, 206)
780 self.assertSourceEqual(mod2.cls203.cls207, 207, 209)
781 self.assertSourceEqual(mod2.cls203.cls207.cls205, 208, 209)
782
783 def test_nested_class_definition_inside_function(self):
784 self.assertSourceEqual(mod2.func212(), 213, 214)
785 self.assertSourceEqual(mod2.cls213, 218, 222)
786 self.assertSourceEqual(mod2.cls213().func219(), 220, 221)
787
788 def test_nested_class_definition_inside_async_function(self):
789 import asyncio
790 self.addCleanup(asyncio.set_event_loop_policy, None)
791 self.assertSourceEqual(asyncio.run(mod2.func225()), 226, 227)
792 self.assertSourceEqual(mod2.cls226, 231, 235)
793 self.assertSourceEqual(asyncio.run(mod2.cls226().func232()), 233, 234)
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300794
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000795class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400796 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000797 self.tempdir = TESTFN + '_dir'
798 os.mkdir(self.tempdir)
Inada Naokifb786922021-04-06 11:18:41 +0900799 with open(os.path.join(self.tempdir, 'inspect_fodder3%spy' % os.extsep),
800 'w', encoding='utf-8') as f:
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000801 f.write("class X:\n pass # No EOL")
802 with DirsOnSysPath(self.tempdir):
803 import inspect_fodder3 as mod3
804 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400805 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000806
807 def tearDown(self):
808 shutil.rmtree(self.tempdir)
809
810 def test_class(self):
811 self.assertSourceEqual(self.fodderModule.X, 1, 2)
812
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100813
814class _BrokenDataDescriptor(object):
815 """
816 A broken data descriptor. See bug #1785.
817 """
818 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700819 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100820
821 def __set__(*args):
822 raise RuntimeError
823
824 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700825 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100826
827
828class _BrokenMethodDescriptor(object):
829 """
830 A broken method descriptor. See bug #1785.
831 """
832 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700833 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100834
835 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700836 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100837
838
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000839# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000840def attrs_wo_objs(cls):
841 return [t[:3] for t in inspect.classify_class_attrs(cls)]
842
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100843
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000844class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000845 def test_newstyle_mro(self):
846 # The same w/ new-class MRO.
847 class A(object): pass
848 class B(A): pass
849 class C(A): pass
850 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000851
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000852 expected = (D, B, C, A, object)
853 got = inspect.getmro(D)
854 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000855
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500856 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
857 varkw_e=None, defaults_e=None, formatted=None):
Xtreak6d0b7472019-05-30 17:31:39 +0530858 with self.assertWarns(DeprecationWarning):
859 args, varargs, varkw, defaults = inspect.getargspec(routine)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500860 self.assertEqual(args, args_e)
861 self.assertEqual(varargs, varargs_e)
862 self.assertEqual(varkw, varkw_e)
863 self.assertEqual(defaults, defaults_e)
864 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530865 with self.assertWarns(DeprecationWarning):
866 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
867 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500868
Christian Heimes3795b532007-11-08 13:48:53 +0000869 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
870 varkw_e=None, defaults_e=None,
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100871 posonlyargs_e=[], kwonlyargs_e=[],
872 kwonlydefaults_e=None,
Christian Heimes3795b532007-11-08 13:48:53 +0000873 ann_e={}, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100874 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
875 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000876 self.assertEqual(args, args_e)
877 self.assertEqual(varargs, varargs_e)
878 self.assertEqual(varkw, varkw_e)
879 self.assertEqual(defaults, defaults_e)
880 self.assertEqual(kwonlyargs, kwonlyargs_e)
881 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
882 self.assertEqual(ann, ann_e)
883 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530884 with self.assertWarns(DeprecationWarning):
885 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
886 kwonlyargs, kwonlydefaults, ann),
887 formatted)
Christian Heimes3795b532007-11-08 13:48:53 +0000888
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500889 def test_getargspec(self):
890 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
891
Pablo Galindod5d2b452019-04-30 02:01:14 +0100892 self.assertArgSpecEquals(mod.spam,
893 ['a', 'b', 'c', 'd', 'e', 'f'],
894 'g', 'h', (3, 4, 5),
895 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500896
897 self.assertRaises(ValueError, self.assertArgSpecEquals,
898 mod2.keyworded, [])
899
900 self.assertRaises(ValueError, self.assertArgSpecEquals,
901 mod2.annotated, [])
902 self.assertRaises(ValueError, self.assertArgSpecEquals,
903 mod2.keyword_only_arg, [])
904
905
Christian Heimes3795b532007-11-08 13:48:53 +0000906 def test_getfullargspec(self):
907 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
908 kwonlyargs_e=['arg2'],
909 kwonlydefaults_e={'arg2':1},
910 formatted='(*arg1, arg2=1)')
911
912 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000913 ann_e={'arg1' : list},
Pablo Galindob0544ba2021-04-21 12:41:19 +0100914 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000915 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
916 kwonlyargs_e=['arg'],
917 formatted='(*, arg)')
918
Pablo Galindod5d2b452019-04-30 02:01:14 +0100919 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100920 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100921 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100922
923 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100924 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100925 varargs_e='args',
926 varkw_e='kwargs',
927 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100928 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100929
Pablo Galindod5d2b452019-04-30 02:01:14 +0100930 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100931 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100932 kwonlyargs_e=['e', 'f'],
933 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100934 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100935
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500936 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500937 # Issue 20684: low level introspection API must ignore __wrapped__
938 @functools.wraps(mod.spam)
939 def ham(x, y):
940 pass
941 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500942 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500943 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
944 self.assertFullArgSpecEquals(functools.partial(ham),
945 ['x', 'y'], formatted='(x, y)')
946 # Other variants
947 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500948 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
949 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500950 class C:
951 @functools.wraps(mod.spam)
952 def ham(self, x, y):
953 pass
954 pham = functools.partialmethod(ham)
955 @functools.wraps(mod.spam)
956 def __call__(self, x, y):
957 pass
958 check_method(C())
959 check_method(C.ham)
960 check_method(C().ham)
961 check_method(C.pham)
962 check_method(C().pham)
963
964 class C_new:
965 @functools.wraps(mod.spam)
966 def __new__(self, x, y):
967 pass
968 check_method(C_new)
969
970 class C_init:
971 @functools.wraps(mod.spam)
972 def __init__(self, x, y):
973 pass
974 check_method(C_init)
975
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500976 def test_getfullargspec_signature_attr(self):
977 def test():
978 pass
979 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
980 test.__signature__ = inspect.Signature(parameters=(spam_param,))
981
Pablo Galindod5d2b452019-04-30 02:01:14 +0100982 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500983
Yury Selivanov4cb93912014-01-29 11:54:12 -0500984 def test_getfullargspec_signature_annos(self):
985 def test(a:'spam') -> 'ham': pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100986 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500987 self.assertEqual(test.__annotations__, spec.annotations)
988
989 def test(): pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100990 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500991 self.assertEqual(test.__annotations__, spec.annotations)
992
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500993 @unittest.skipIf(MISSING_C_DOCSTRINGS,
994 "Signature information for builtins requires docstrings")
995 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100996 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
997 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500998
Pablo Galindod5d2b452019-04-30 02:01:14 +0100999 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
1000 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001001
Yury Selivanov8c185ee2014-02-21 01:32:42 -05001002 self.assertFullArgSpecEquals(
1003 os.stat,
1004 args_e=['path'],
1005 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
1006 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
1007 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
1008
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001009 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001010 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1011 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +08001012 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001013 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001014 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindoaee19f52019-05-16 21:08:15 +01001015 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001016 self.assertEqual(spec.defaults[0], 'avocado')
1017
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001018 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001019 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1020 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +08001021 def test_getfullargspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001022 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001023 builtin = _testcapi.docstring_no_signature
Pablo Galindoaee19f52019-05-16 21:08:15 +01001024 with self.assertRaises(TypeError):
1025 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +00001026
larryhastingsf36ba122018-01-28 11:13:09 -08001027 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
1028 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindoaee19f52019-05-16 21:08:15 +01001029 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -08001030 l = list(signature.kwonlyargs)
1031 sorted_l = sorted(l)
1032 self.assertTrue(l)
1033 self.assertEqual(l, sorted_l)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001034 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -08001035 l = list(signature.kwonlyargs)
1036 self.assertEqual(l, unsorted_keyword_only_parameters)
1037
Yury Selivanov37dc2b22016-01-11 15:15:01 -05001038 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001039 class A(object):
1040 def m(self):
1041 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -05001042 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +00001043
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001044 def test_classify_newstyle(self):
1045 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +00001046
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001047 def s(): pass
1048 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +00001049
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001050 def c(cls): pass
1051 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +00001052
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001053 def getp(self): pass
1054 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +00001055
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001056 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001057
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001058 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001059
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001060 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +00001061
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001062 dd = _BrokenDataDescriptor()
1063 md = _BrokenMethodDescriptor()
1064
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001065 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001066
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001067 self.assertIn(('__new__', 'static method', object), attrs,
1068 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001069 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
1070
Benjamin Peterson577473f2010-01-19 00:09:57 +00001071 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1072 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1073 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001074 self.assertIn(('m', 'method', A), attrs,
1075 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001076 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1077 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001078 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1079 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001080
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001081 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001082
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001083 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001084
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001085 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001086 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1087 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1088 self.assertIn(('p', 'property', A), attrs, 'missing property')
1089 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1090 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1091 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001092 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1093 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001094
1095
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001096 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001097
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001098 def m(self): pass
1099 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001100
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001101 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001102 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1103 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1104 self.assertIn(('p', 'property', A), attrs, 'missing property')
1105 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
1106 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1107 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001108 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1109 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001110
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001111 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001112
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001113 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001114
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001115 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001116 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1117 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1118 self.assertIn(('p', 'property', A), attrs, 'missing property')
1119 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1120 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1121 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001122 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1123 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1124
1125 def test_classify_builtin_types(self):
1126 # Simple sanity check that all built-in types can have their
1127 # attributes classified.
1128 for name in dir(__builtins__):
1129 builtin = getattr(__builtins__, name)
1130 if isinstance(builtin, type):
1131 inspect.classify_class_attrs(builtin)
1132
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001133 attrs = attrs_wo_objs(bool)
1134 self.assertIn(('__new__', 'static method', bool), attrs,
1135 'missing __new__')
1136 self.assertIn(('from_bytes', 'class method', int), attrs,
1137 'missing class method')
1138 self.assertIn(('to_bytes', 'method', int), attrs,
1139 'missing plain method')
1140 self.assertIn(('__add__', 'method', int), attrs,
1141 'missing plain method')
1142 self.assertIn(('__and__', 'method', bool), attrs,
1143 'missing plain method')
1144
Ethan Furman63c141c2013-10-18 00:27:39 -07001145 def test_classify_DynamicClassAttribute(self):
1146 class Meta(type):
1147 def __getattr__(self, name):
1148 if name == 'ham':
1149 return 'spam'
1150 return super().__getattr__(name)
1151 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001152 @types.DynamicClassAttribute
1153 def ham(self):
1154 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001155 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1156 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001157 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001158 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1159
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001160 def test_classify_overrides_bool(self):
1161 class NoBool(object):
1162 def __eq__(self, other):
1163 return NoBool()
1164
1165 def __bool__(self):
1166 raise NotImplementedError(
1167 "This object does not specify a boolean value")
1168
1169 class HasNB(object):
1170 dd = NoBool()
1171
1172 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1173 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1174
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001175 def test_classify_metaclass_class_attribute(self):
1176 class Meta(type):
1177 fish = 'slap'
1178 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001179 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001180 class Class(metaclass=Meta):
1181 pass
1182 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1183 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1184
Ethan Furman63c141c2013-10-18 00:27:39 -07001185 def test_classify_VirtualAttribute(self):
1186 class Meta(type):
1187 def __dir__(cls):
1188 return ['__class__', '__module__', '__name__', 'BOOM']
1189 def __getattr__(self, name):
1190 if name =='BOOM':
1191 return 42
1192 return super().__getattr(name)
1193 class Class(metaclass=Meta):
1194 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001195 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001196 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1197
1198 def test_classify_VirtualAttribute_multi_classes(self):
1199 class Meta1(type):
1200 def __dir__(cls):
1201 return ['__class__', '__module__', '__name__', 'one']
1202 def __getattr__(self, name):
1203 if name =='one':
1204 return 1
1205 return super().__getattr__(name)
1206 class Meta2(type):
1207 def __dir__(cls):
1208 return ['__class__', '__module__', '__name__', 'two']
1209 def __getattr__(self, name):
1210 if name =='two':
1211 return 2
1212 return super().__getattr__(name)
1213 class Meta3(Meta1, Meta2):
1214 def __dir__(cls):
1215 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1216 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1217 def __getattr__(self, name):
1218 if name =='three':
1219 return 3
1220 return super().__getattr__(name)
1221 class Class1(metaclass=Meta1):
1222 pass
1223 class Class2(Class1, metaclass=Meta3):
1224 pass
1225
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001226 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1227 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1228 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001229 cca = inspect.classify_class_attrs(Class2)
1230 for sf in (should_find1, should_find2, should_find3):
1231 self.assertIn(sf, cca)
1232
1233 def test_classify_class_attrs_with_buggy_dir(self):
1234 class M(type):
1235 def __dir__(cls):
1236 return ['__class__', '__name__', 'missing']
1237 class C(metaclass=M):
1238 pass
1239 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1240 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001241
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001242 def test_getmembers_descriptors(self):
1243 class A(object):
1244 dd = _BrokenDataDescriptor()
1245 md = _BrokenMethodDescriptor()
1246
1247 def pred_wrapper(pred):
1248 # A quick'n'dirty way to discard standard attributes of new-style
1249 # classes.
1250 class Empty(object):
1251 pass
1252 def wrapped(x):
1253 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1254 return False
1255 return pred(x)
1256 return wrapped
1257
1258 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1259 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1260
1261 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1262 [('md', A.__dict__['md'])])
1263 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1264 [('dd', A.__dict__['dd'])])
1265
1266 class B(A):
1267 pass
1268
1269 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1270 [('md', A.__dict__['md'])])
1271 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1272 [('dd', A.__dict__['dd'])])
1273
Antoine Pitrou0c603812012-01-18 17:40:18 +01001274 def test_getmembers_method(self):
1275 class B:
1276 def f(self):
1277 pass
1278
1279 self.assertIn(('f', B.f), inspect.getmembers(B))
1280 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1281 b = B()
1282 self.assertIn(('f', b.f), inspect.getmembers(b))
1283 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1284
Ethan Furmane03ea372013-09-25 07:14:41 -07001285 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001286 class M(type):
1287 def __getattr__(cls, name):
1288 if name == 'eggs':
1289 return 'scrambled'
1290 return super().__getattr__(name)
1291 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001292 @types.DynamicClassAttribute
1293 def eggs(self):
1294 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001295 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1296 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1297
1298 def test_getmembers_with_buggy_dir(self):
1299 class M(type):
1300 def __dir__(cls):
1301 return ['__class__', '__name__', 'missing']
1302 class C(metaclass=M):
1303 pass
1304 attrs = [a[0] for a in inspect.getmembers(C)]
1305 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001306
larryhastings74613a42021-04-29 21:16:28 -07001307 def test_get_annotations_with_stock_annotations(self):
1308 def foo(a:int, b:str): pass
1309 self.assertEqual(inspect.get_annotations(foo), {'a': int, 'b': str})
1310
1311 foo.__annotations__ = {'a': 'foo', 'b':'str'}
1312 self.assertEqual(inspect.get_annotations(foo), {'a': 'foo', 'b': 'str'})
1313
1314 self.assertEqual(inspect.get_annotations(foo, eval_str=True, locals=locals()), {'a': foo, 'b': str})
1315 self.assertEqual(inspect.get_annotations(foo, eval_str=True, globals=locals()), {'a': foo, 'b': str})
1316
1317 isa = inspect_stock_annotations
1318 self.assertEqual(inspect.get_annotations(isa), {'a': int, 'b': str})
1319 self.assertEqual(inspect.get_annotations(isa.MyClass), {'a': int, 'b': str})
1320 self.assertEqual(inspect.get_annotations(isa.function), {'a': int, 'b': str, 'return': isa.MyClass})
1321 self.assertEqual(inspect.get_annotations(isa.function2), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1322 self.assertEqual(inspect.get_annotations(isa.function3), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1323 self.assertEqual(inspect.get_annotations(inspect), {}) # inspect module has no annotations
1324 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass), {})
1325 self.assertEqual(inspect.get_annotations(isa.unannotated_function), {})
1326
1327 self.assertEqual(inspect.get_annotations(isa, eval_str=True), {'a': int, 'b': str})
1328 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=True), {'a': int, 'b': str})
1329 self.assertEqual(inspect.get_annotations(isa.function, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1330 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=True), {'a': int, 'b': str, 'c': isa.MyClass, 'return': isa.MyClass})
1331 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=True), {'a': int, 'b': str, 'c': isa.MyClass})
1332 self.assertEqual(inspect.get_annotations(inspect, eval_str=True), {})
1333 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=True), {})
1334 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=True), {})
1335
1336 self.assertEqual(inspect.get_annotations(isa, eval_str=False), {'a': int, 'b': str})
1337 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=False), {'a': int, 'b': str})
1338 self.assertEqual(inspect.get_annotations(isa.function, eval_str=False), {'a': int, 'b': str, 'return': isa.MyClass})
1339 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=False), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1340 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=False), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1341 self.assertEqual(inspect.get_annotations(inspect, eval_str=False), {})
1342 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=False), {})
1343 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=False), {})
1344
1345 def times_three(fn):
1346 @functools.wraps(fn)
1347 def wrapper(a, b):
1348 return fn(a*3, b*3)
1349 return wrapper
1350
1351 wrapped = times_three(isa.function)
1352 self.assertEqual(wrapped(1, 'x'), isa.MyClass(3, 'xxx'))
1353 self.assertIsNot(wrapped.__globals__, isa.function.__globals__)
1354 self.assertEqual(inspect.get_annotations(wrapped), {'a': int, 'b': str, 'return': isa.MyClass})
1355 self.assertEqual(inspect.get_annotations(wrapped, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1356 self.assertEqual(inspect.get_annotations(wrapped, eval_str=False), {'a': int, 'b': str, 'return': isa.MyClass})
1357
1358 def test_get_annotations_with_stringized_annotations(self):
1359 isa = inspect_stringized_annotations
1360 self.assertEqual(inspect.get_annotations(isa), {'a': 'int', 'b': 'str'})
1361 self.assertEqual(inspect.get_annotations(isa.MyClass), {'a': 'int', 'b': 'str'})
1362 self.assertEqual(inspect.get_annotations(isa.function), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1363 self.assertEqual(inspect.get_annotations(isa.function2), {'a': 'int', 'b': "'str'", 'c': 'MyClass', 'return': 'MyClass'})
1364 self.assertEqual(inspect.get_annotations(isa.function3), {'a': "'int'", 'b': "'str'", 'c': "'MyClass'"})
1365 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass), {})
1366 self.assertEqual(inspect.get_annotations(isa.unannotated_function), {})
1367
1368 self.assertEqual(inspect.get_annotations(isa, eval_str=True), {'a': int, 'b': str})
1369 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=True), {'a': int, 'b': str})
1370 self.assertEqual(inspect.get_annotations(isa.function, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1371 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=True), {'a': int, 'b': 'str', 'c': isa.MyClass, 'return': isa.MyClass})
1372 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=True), {'a': 'int', 'b': 'str', 'c': 'MyClass'})
1373 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=True), {})
1374 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=True), {})
1375
1376 self.assertEqual(inspect.get_annotations(isa, eval_str=False), {'a': 'int', 'b': 'str'})
1377 self.assertEqual(inspect.get_annotations(isa.MyClass, eval_str=False), {'a': 'int', 'b': 'str'})
1378 self.assertEqual(inspect.get_annotations(isa.function, eval_str=False), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1379 self.assertEqual(inspect.get_annotations(isa.function2, eval_str=False), {'a': 'int', 'b': "'str'", 'c': 'MyClass', 'return': 'MyClass'})
1380 self.assertEqual(inspect.get_annotations(isa.function3, eval_str=False), {'a': "'int'", 'b': "'str'", 'c': "'MyClass'"})
1381 self.assertEqual(inspect.get_annotations(isa.UnannotatedClass, eval_str=False), {})
1382 self.assertEqual(inspect.get_annotations(isa.unannotated_function, eval_str=False), {})
1383
1384 isa2 = inspect_stringized_annotations_2
1385 self.assertEqual(inspect.get_annotations(isa2), {})
1386 self.assertEqual(inspect.get_annotations(isa2, eval_str=True), {})
1387 self.assertEqual(inspect.get_annotations(isa2, eval_str=False), {})
1388
1389 def times_three(fn):
1390 @functools.wraps(fn)
1391 def wrapper(a, b):
1392 return fn(a*3, b*3)
1393 return wrapper
1394
1395 wrapped = times_three(isa.function)
1396 self.assertEqual(wrapped(1, 'x'), isa.MyClass(3, 'xxx'))
1397 self.assertIsNot(wrapped.__globals__, isa.function.__globals__)
1398 self.assertEqual(inspect.get_annotations(wrapped), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1399 self.assertEqual(inspect.get_annotations(wrapped, eval_str=True), {'a': int, 'b': str, 'return': isa.MyClass})
1400 self.assertEqual(inspect.get_annotations(wrapped, eval_str=False), {'a': 'int', 'b': 'str', 'return': 'MyClass'})
1401
1402 # test that local namespace lookups work
1403 self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations), {'x': 'mytype'})
1404 self.assertEqual(inspect.get_annotations(isa.MyClassWithLocalAnnotations, eval_str=True), {'x': int})
1405
1406
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001407class TestIsDataDescriptor(unittest.TestCase):
1408
1409 def test_custom_descriptors(self):
1410 class NonDataDescriptor:
1411 def __get__(self, value, type=None): pass
1412 class DataDescriptor0:
1413 def __set__(self, name, value): pass
1414 class DataDescriptor1:
1415 def __delete__(self, name): pass
1416 class DataDescriptor2:
1417 __set__ = None
1418 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1419 'class with only __get__ not a data descriptor')
1420 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1421 'class with __set__ is a data descriptor')
1422 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1423 'class with __delete__ is a data descriptor')
1424 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1425 'class with __set__ = None is a data descriptor')
1426
1427 def test_slot(self):
1428 class Slotted:
1429 __slots__ = 'foo',
1430 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1431 'a slot is a data descriptor')
1432
1433 def test_property(self):
1434 class Propertied:
1435 @property
1436 def a_property(self):
1437 pass
1438 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1439 'a property is a data descriptor')
1440
1441 def test_functions(self):
1442 class Test(object):
1443 def instance_method(self): pass
1444 @classmethod
1445 def class_method(cls): pass
1446 @staticmethod
1447 def static_method(): pass
1448 def function():
1449 pass
1450 a_lambda = lambda: None
1451 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1452 'a instance method is not a data descriptor')
1453 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1454 'a class method is not a data descriptor')
1455 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1456 'a static method is not a data descriptor')
1457 self.assertFalse(inspect.isdatadescriptor(function),
1458 'a function is not a data descriptor')
1459 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1460 'a lambda is not a data descriptor')
1461
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001462
Nick Coghlan2f92e542012-06-23 19:39:55 +10001463_global_ref = object()
1464class TestGetClosureVars(unittest.TestCase):
1465
1466 def test_name_resolution(self):
1467 # Basic test of the 4 different resolution mechanisms
1468 def f(nonlocal_ref):
1469 def g(local_ref):
1470 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1471 return g
1472 _arg = object()
1473 nonlocal_vars = {"nonlocal_ref": _arg}
1474 global_vars = {"_global_ref": _global_ref}
1475 builtin_vars = {"print": print}
1476 unbound_names = {"unbound_ref"}
1477 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1478 builtin_vars, unbound_names)
1479 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1480
1481 def test_generator_closure(self):
1482 def f(nonlocal_ref):
1483 def g(local_ref):
1484 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1485 yield
1486 return g
1487 _arg = object()
1488 nonlocal_vars = {"nonlocal_ref": _arg}
1489 global_vars = {"_global_ref": _global_ref}
1490 builtin_vars = {"print": print}
1491 unbound_names = {"unbound_ref"}
1492 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1493 builtin_vars, unbound_names)
1494 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1495
1496 def test_method_closure(self):
1497 class C:
1498 def f(self, nonlocal_ref):
1499 def g(local_ref):
1500 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1501 return g
1502 _arg = object()
1503 nonlocal_vars = {"nonlocal_ref": _arg}
1504 global_vars = {"_global_ref": _global_ref}
1505 builtin_vars = {"print": print}
1506 unbound_names = {"unbound_ref"}
1507 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1508 builtin_vars, unbound_names)
1509 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1510
1511 def test_nonlocal_vars(self):
1512 # More complex tests of nonlocal resolution
1513 def _nonlocal_vars(f):
1514 return inspect.getclosurevars(f).nonlocals
1515
1516 def make_adder(x):
1517 def add(y):
1518 return x + y
1519 return add
1520
1521 def curry(func, arg1):
1522 return lambda arg2: func(arg1, arg2)
1523
1524 def less_than(a, b):
1525 return a < b
1526
1527 # The infamous Y combinator.
1528 def Y(le):
1529 def g(f):
1530 return le(lambda x: f(f)(x))
1531 Y.g_ref = g
1532 return g(g)
1533
1534 def check_y_combinator(func):
1535 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1536
1537 inc = make_adder(1)
1538 add_two = make_adder(2)
1539 greater_than_five = curry(less_than, 5)
1540
1541 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1542 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1543 self.assertEqual(_nonlocal_vars(greater_than_five),
1544 {'arg1': 5, 'func': less_than})
1545 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1546 {'x': 3})
1547 Y(check_y_combinator)
1548
1549 def test_getclosurevars_empty(self):
1550 def foo(): pass
1551 _empty = inspect.ClosureVars({}, {}, {}, set())
1552 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1553 self.assertEqual(inspect.getclosurevars(foo), _empty)
1554
1555 def test_getclosurevars_error(self):
1556 class T: pass
1557 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1558 self.assertRaises(TypeError, inspect.getclosurevars, list)
1559 self.assertRaises(TypeError, inspect.getclosurevars, {})
1560
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001561 def _private_globals(self):
1562 code = """def f(): print(path)"""
1563 ns = {}
1564 exec(code, ns)
1565 return ns["f"], ns
1566
1567 def test_builtins_fallback(self):
1568 f, ns = self._private_globals()
1569 ns.pop("__builtins__", None)
1570 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1571 self.assertEqual(inspect.getclosurevars(f), expected)
1572
1573 def test_builtins_as_dict(self):
1574 f, ns = self._private_globals()
1575 ns["__builtins__"] = {"path":1}
1576 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1577 self.assertEqual(inspect.getclosurevars(f), expected)
1578
1579 def test_builtins_as_module(self):
1580 f, ns = self._private_globals()
1581 ns["__builtins__"] = os
1582 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1583 self.assertEqual(inspect.getclosurevars(f), expected)
1584
Nick Coghlan2f92e542012-06-23 19:39:55 +10001585
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001586class TestGetcallargsFunctions(unittest.TestCase):
1587
1588 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1589 locs = dict(locs or {}, func=func)
1590 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001591 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1592 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001593 self.assertEqual(r1, r2)
1594
1595 def assertEqualException(self, func, call_param_string, locs=None):
1596 locs = dict(locs or {}, func=func)
1597 try:
1598 eval('func(%s)' % call_param_string, None, locs)
1599 except Exception as e:
1600 ex1 = e
1601 else:
1602 self.fail('Exception not raised')
1603 try:
Pablo Galindoaee19f52019-05-16 21:08:15 +01001604 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1605 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001606 except Exception as e:
1607 ex2 = e
1608 else:
1609 self.fail('Exception not raised')
1610 self.assertIs(type(ex1), type(ex2))
1611 self.assertEqual(str(ex1), str(ex2))
1612 del ex1, ex2
1613
1614 def makeCallable(self, signature):
1615 """Create a function that returns its locals()"""
1616 code = "lambda %s: locals()"
1617 return eval(code % signature)
1618
1619 def test_plain(self):
1620 f = self.makeCallable('a, b=1')
1621 self.assertEqualCallArgs(f, '2')
1622 self.assertEqualCallArgs(f, '2, 3')
1623 self.assertEqualCallArgs(f, 'a=2')
1624 self.assertEqualCallArgs(f, 'b=3, a=2')
1625 self.assertEqualCallArgs(f, '2, b=3')
1626 # expand *iterable / **mapping
1627 self.assertEqualCallArgs(f, '*(2,)')
1628 self.assertEqualCallArgs(f, '*[2]')
1629 self.assertEqualCallArgs(f, '*(2, 3)')
1630 self.assertEqualCallArgs(f, '*[2, 3]')
1631 self.assertEqualCallArgs(f, '**{"a":2}')
1632 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1633 self.assertEqualCallArgs(f, '2, **{"b":3}')
1634 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1635 # expand UserList / UserDict
1636 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1637 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1638 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1639 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1640 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1641
1642 def test_varargs(self):
1643 f = self.makeCallable('a, b=1, *c')
1644 self.assertEqualCallArgs(f, '2')
1645 self.assertEqualCallArgs(f, '2, 3')
1646 self.assertEqualCallArgs(f, '2, 3, 4')
1647 self.assertEqualCallArgs(f, '*(2,3,4)')
1648 self.assertEqualCallArgs(f, '2, *[3,4]')
1649 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1650
1651 def test_varkw(self):
1652 f = self.makeCallable('a, b=1, **c')
1653 self.assertEqualCallArgs(f, 'a=2')
1654 self.assertEqualCallArgs(f, '2, b=3, c=4')
1655 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1656 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1657 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1658 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1659 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1660 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1661 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1662
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001663 def test_varkw_only(self):
1664 # issue11256:
1665 f = self.makeCallable('**c')
1666 self.assertEqualCallArgs(f, '')
1667 self.assertEqualCallArgs(f, 'a=1')
1668 self.assertEqualCallArgs(f, 'a=1, b=2')
1669 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1670 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1671 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1672
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001673 def test_keyword_only(self):
1674 f = self.makeCallable('a=3, *, c, d=2')
1675 self.assertEqualCallArgs(f, 'c=3')
1676 self.assertEqualCallArgs(f, 'c=3, a=3')
1677 self.assertEqualCallArgs(f, 'a=2, c=4')
1678 self.assertEqualCallArgs(f, '4, c=4')
1679 self.assertEqualException(f, '')
1680 self.assertEqualException(f, '3')
1681 self.assertEqualException(f, 'a=3')
1682 self.assertEqualException(f, 'd=4')
1683
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001684 f = self.makeCallable('*, c, d=2')
1685 self.assertEqualCallArgs(f, 'c=3')
1686 self.assertEqualCallArgs(f, 'c=3, d=4')
1687 self.assertEqualCallArgs(f, 'd=4, c=3')
1688
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001689 def test_multiple_features(self):
1690 f = self.makeCallable('a, b=2, *f, **g')
1691 self.assertEqualCallArgs(f, '2, 3, 7')
1692 self.assertEqualCallArgs(f, '2, 3, x=8')
1693 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1694 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1695 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1696 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1697 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1698 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1699 '(4,[5,6])]), **collections.UserDict('
1700 'y=9, z=10)')
1701
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001702 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1703 self.assertEqualCallArgs(f, '2, 3, x=8')
1704 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1705 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1706 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1707 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1708 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1709 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1710 '(4,[5,6])]), q=0, **collections.UserDict('
1711 'y=9, z=10)')
1712
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001713 def test_errors(self):
1714 f0 = self.makeCallable('')
1715 f1 = self.makeCallable('a, b')
1716 f2 = self.makeCallable('a, b=1')
1717 # f0 takes no arguments
1718 self.assertEqualException(f0, '1')
1719 self.assertEqualException(f0, 'x=1')
1720 self.assertEqualException(f0, '1,x=1')
1721 # f1 takes exactly 2 arguments
1722 self.assertEqualException(f1, '')
1723 self.assertEqualException(f1, '1')
1724 self.assertEqualException(f1, 'a=2')
1725 self.assertEqualException(f1, 'b=3')
1726 # f2 takes at least 1 argument
1727 self.assertEqualException(f2, '')
1728 self.assertEqualException(f2, 'b=3')
1729 for f in f1, f2:
1730 # f1/f2 takes exactly/at most 2 arguments
1731 self.assertEqualException(f, '2, 3, 4')
1732 self.assertEqualException(f, '1, 2, 3, a=1')
1733 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001734 # XXX: success of this one depends on dict order
1735 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001736 # f got an unexpected keyword argument
1737 self.assertEqualException(f, 'c=2')
1738 self.assertEqualException(f, '2, c=3')
1739 self.assertEqualException(f, '2, 3, c=4')
1740 self.assertEqualException(f, '2, c=4, b=3')
1741 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1742 # f got multiple values for keyword argument
1743 self.assertEqualException(f, '1, a=2')
1744 self.assertEqualException(f, '1, **{"a":2}')
1745 self.assertEqualException(f, '1, 2, b=3')
1746 # XXX: Python inconsistency
1747 # - for functions and bound methods: unexpected keyword 'c'
1748 # - for unbound methods: multiple values for keyword 'a'
1749 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001750 # issue11256:
1751 f3 = self.makeCallable('**c')
1752 self.assertEqualException(f3, '1, 2')
1753 self.assertEqualException(f3, '1, 2, a=1, b=2')
1754 f4 = self.makeCallable('*, a, b=0')
1755 self.assertEqualException(f3, '1, 2')
1756 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001757
Yury Selivanov875df202014-03-27 18:23:03 -04001758 # issue #20816: getcallargs() fails to iterate over non-existent
1759 # kwonlydefaults and raises a wrong TypeError
1760 def f5(*, a): pass
1761 with self.assertRaisesRegex(TypeError,
1762 'missing 1 required keyword-only'):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001763 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001764
1765
Yury Selivanovdccfa132014-03-27 18:42:52 -04001766 # issue20817:
1767 def f6(a, b, c):
1768 pass
1769 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001770 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001771
Dong-hee Naa9cab432018-05-30 00:04:08 +09001772 # bpo-33197
1773 with self.assertRaisesRegex(ValueError,
1774 'variadic keyword parameters cannot'
1775 ' have default values'):
1776 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1777 default=42)
1778 with self.assertRaisesRegex(ValueError,
1779 "value 5 is not a valid Parameter.kind"):
1780 inspect.Parameter("bar", kind=5, default=42)
1781
1782 with self.assertRaisesRegex(TypeError,
1783 'name must be a str, not a int'):
1784 inspect.Parameter(123, kind=4)
1785
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001786class TestGetcallargsMethods(TestGetcallargsFunctions):
1787
1788 def setUp(self):
1789 class Foo(object):
1790 pass
1791 self.cls = Foo
1792 self.inst = Foo()
1793
1794 def makeCallable(self, signature):
1795 assert 'self' not in signature
1796 mk = super(TestGetcallargsMethods, self).makeCallable
1797 self.cls.method = mk('self, ' + signature)
1798 return self.inst.method
1799
1800class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1801
1802 def makeCallable(self, signature):
1803 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1804 return self.cls.method
1805
1806 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1807 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1808 *self._getAssertEqualParams(func, call_params_string, locs))
1809
1810 def assertEqualException(self, func, call_params_string, locs=None):
1811 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1812 *self._getAssertEqualParams(func, call_params_string, locs))
1813
1814 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1815 assert 'inst' not in call_params_string
1816 locs = dict(locs or {}, inst=self.inst)
1817 return (func, 'inst,' + call_params_string, locs)
1818
Michael Foord95fc51d2010-11-20 15:07:30 +00001819
1820class TestGetattrStatic(unittest.TestCase):
1821
1822 def test_basic(self):
1823 class Thing(object):
1824 x = object()
1825
1826 thing = Thing()
1827 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1828 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1829 with self.assertRaises(AttributeError):
1830 inspect.getattr_static(thing, 'y')
1831
1832 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1833
1834 def test_inherited(self):
1835 class Thing(object):
1836 x = object()
1837 class OtherThing(Thing):
1838 pass
1839
1840 something = OtherThing()
1841 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1842
1843 def test_instance_attr(self):
1844 class Thing(object):
1845 x = 2
1846 def __init__(self, x):
1847 self.x = x
1848 thing = Thing(3)
1849 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1850 del thing.x
1851 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1852
1853 def test_property(self):
1854 class Thing(object):
1855 @property
1856 def x(self):
1857 raise AttributeError("I'm pretending not to exist")
1858 thing = Thing()
1859 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1860
Ezio Melotti75cbd732011-04-28 00:59:29 +03001861 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001862 class descriptor(object):
1863 def __get__(*_):
1864 raise AttributeError("I'm pretending not to exist")
1865 desc = descriptor()
1866 class Thing(object):
1867 x = desc
1868 thing = Thing()
1869 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1870
1871 def test_classAttribute(self):
1872 class Thing(object):
1873 x = object()
1874
1875 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1876
Ethan Furmane03ea372013-09-25 07:14:41 -07001877 def test_classVirtualAttribute(self):
1878 class Thing(object):
1879 @types.DynamicClassAttribute
1880 def x(self):
1881 return self._x
1882 _x = object()
1883
1884 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1885
Michael Foord95fc51d2010-11-20 15:07:30 +00001886 def test_inherited_classattribute(self):
1887 class Thing(object):
1888 x = object()
1889 class OtherThing(Thing):
1890 pass
1891
1892 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1893
1894 def test_slots(self):
1895 class Thing(object):
1896 y = 'bar'
1897 __slots__ = ['x']
1898 def __init__(self):
1899 self.x = 'foo'
1900 thing = Thing()
1901 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1902 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1903
1904 del thing.x
1905 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1906
1907 def test_metaclass(self):
1908 class meta(type):
1909 attr = 'foo'
1910 class Thing(object, metaclass=meta):
1911 pass
1912 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1913
1914 class sub(meta):
1915 pass
1916 class OtherThing(object, metaclass=sub):
1917 x = 3
1918 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1919
1920 class OtherOtherThing(OtherThing):
1921 pass
1922 # this test is odd, but it was added as it exposed a bug
1923 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1924
1925 def test_no_dict_no_slots(self):
1926 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1927 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1928
1929 def test_no_dict_no_slots_instance_member(self):
1930 # returns descriptor
Inada Naokifb786922021-04-06 11:18:41 +09001931 with open(__file__, encoding='utf-8') as handle:
Michael Foord95fc51d2010-11-20 15:07:30 +00001932 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1933
1934 def test_inherited_slots(self):
1935 # returns descriptor
1936 class Thing(object):
1937 __slots__ = ['x']
1938 def __init__(self):
1939 self.x = 'foo'
1940
1941 class OtherThing(Thing):
1942 pass
1943 # it would be nice if this worked...
1944 # we get the descriptor instead of the instance attribute
1945 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1946
1947 def test_descriptor(self):
1948 class descriptor(object):
1949 def __get__(self, instance, owner):
1950 return 3
1951 class Foo(object):
1952 d = descriptor()
1953
1954 foo = Foo()
1955
1956 # for a non data descriptor we return the instance attribute
1957 foo.__dict__['d'] = 1
1958 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1959
Mike53f7a7c2017-12-14 14:04:53 +03001960 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001961 # descriptor
1962 descriptor.__set__ = lambda s, i, v: None
1963 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1964
1965
1966 def test_metaclass_with_descriptor(self):
1967 class descriptor(object):
1968 def __get__(self, instance, owner):
1969 return 3
1970 class meta(type):
1971 d = descriptor()
1972 class Thing(object, metaclass=meta):
1973 pass
1974 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1975
1976
Michael Foordcc7ebb82010-11-20 16:20:16 +00001977 def test_class_as_property(self):
1978 class Base(object):
1979 foo = 3
1980
1981 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001982 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001983 @property
1984 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001985 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001986 return object
1987
Michael Foord35184ed2010-11-20 16:58:30 +00001988 instance = Something()
1989 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1990 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001991 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1992
Michael Foorde5162652010-11-20 16:40:44 +00001993 def test_mro_as_property(self):
1994 class Meta(type):
1995 @property
1996 def __mro__(self):
1997 return (object,)
1998
1999 class Base(object):
2000 foo = 3
2001
2002 class Something(Base, metaclass=Meta):
2003 pass
2004
2005 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
2006 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
2007
Michael Foorddcebe0f2011-03-15 19:20:44 -04002008 def test_dict_as_property(self):
2009 test = self
2010 test.called = False
2011
2012 class Foo(dict):
2013 a = 3
2014 @property
2015 def __dict__(self):
2016 test.called = True
2017 return {}
2018
2019 foo = Foo()
2020 foo.a = 4
2021 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
2022 self.assertFalse(test.called)
2023
2024 def test_custom_object_dict(self):
2025 test = self
2026 test.called = False
2027
2028 class Custom(dict):
2029 def get(self, key, default=None):
2030 test.called = True
2031 super().get(key, default)
2032
2033 class Foo(object):
2034 a = 3
2035 foo = Foo()
2036 foo.__dict__ = Custom()
2037 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
2038 self.assertFalse(test.called)
2039
2040 def test_metaclass_dict_as_property(self):
2041 class Meta(type):
2042 @property
2043 def __dict__(self):
2044 self.executed = True
2045
2046 class Thing(metaclass=Meta):
2047 executed = False
2048
2049 def __init__(self):
2050 self.spam = 42
2051
2052 instance = Thing()
2053 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
2054 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00002055
Michael Foorda51623b2011-12-18 22:01:40 +00002056 def test_module(self):
2057 sentinel = object()
2058 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
2059 sentinel)
2060
Michael Foord3ba95f82011-12-22 01:13:37 +00002061 def test_metaclass_with_metaclass_with_dict_as_property(self):
2062 class MetaMeta(type):
2063 @property
2064 def __dict__(self):
2065 self.executed = True
2066 return dict(spam=42)
2067
2068 class Meta(type, metaclass=MetaMeta):
2069 executed = False
2070
2071 class Thing(metaclass=Meta):
2072 pass
2073
2074 with self.assertRaises(AttributeError):
2075 inspect.getattr_static(Thing, "spam")
2076 self.assertFalse(Thing.executed)
2077
Nick Coghlane0f04652010-11-21 03:44:04 +00002078class TestGetGeneratorState(unittest.TestCase):
2079
2080 def setUp(self):
2081 def number_generator():
2082 for number in range(5):
2083 yield number
2084 self.generator = number_generator()
2085
2086 def _generatorstate(self):
2087 return inspect.getgeneratorstate(self.generator)
2088
2089 def test_created(self):
2090 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
2091
2092 def test_suspended(self):
2093 next(self.generator)
2094 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
2095
2096 def test_closed_after_exhaustion(self):
2097 for i in self.generator:
2098 pass
2099 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
2100
2101 def test_closed_after_immediate_exception(self):
2102 with self.assertRaises(RuntimeError):
2103 self.generator.throw(RuntimeError)
2104 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
2105
2106 def test_running(self):
2107 # As mentioned on issue #10220, checking for the RUNNING state only
2108 # makes sense inside the generator itself.
2109 # The following generator checks for this by using the closure's
2110 # reference to self and the generator state checking helper method
2111 def running_check_generator():
2112 for number in range(5):
2113 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
2114 yield number
2115 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
2116 self.generator = running_check_generator()
2117 # Running up to the first yield
2118 next(self.generator)
2119 # Running after the first yield
2120 next(self.generator)
2121
Nick Coghlan7921b9f2010-11-30 06:36:04 +00002122 def test_easy_debugging(self):
2123 # repr() and str() of a generator state should contain the state name
2124 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
2125 for name in names:
2126 state = getattr(inspect, name)
2127 self.assertIn(name, repr(state))
2128 self.assertIn(name, str(state))
2129
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10002130 def test_getgeneratorlocals(self):
2131 def each(lst, a=None):
2132 b=(1, 2, 3)
2133 for v in lst:
2134 if v == 3:
2135 c = 12
2136 yield v
2137
2138 numbers = each([1, 2, 3])
2139 self.assertEqual(inspect.getgeneratorlocals(numbers),
2140 {'a': None, 'lst': [1, 2, 3]})
2141 next(numbers)
2142 self.assertEqual(inspect.getgeneratorlocals(numbers),
2143 {'a': None, 'lst': [1, 2, 3], 'v': 1,
2144 'b': (1, 2, 3)})
2145 next(numbers)
2146 self.assertEqual(inspect.getgeneratorlocals(numbers),
2147 {'a': None, 'lst': [1, 2, 3], 'v': 2,
2148 'b': (1, 2, 3)})
2149 next(numbers)
2150 self.assertEqual(inspect.getgeneratorlocals(numbers),
2151 {'a': None, 'lst': [1, 2, 3], 'v': 3,
2152 'b': (1, 2, 3), 'c': 12})
2153 try:
2154 next(numbers)
2155 except StopIteration:
2156 pass
2157 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
2158
2159 def test_getgeneratorlocals_empty(self):
2160 def yield_one():
2161 yield 1
2162 one = yield_one()
2163 self.assertEqual(inspect.getgeneratorlocals(one), {})
2164 try:
2165 next(one)
2166 except StopIteration:
2167 pass
2168 self.assertEqual(inspect.getgeneratorlocals(one), {})
2169
2170 def test_getgeneratorlocals_error(self):
2171 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
2172 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
2173 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
2174 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
2175
Nick Coghlane0f04652010-11-21 03:44:04 +00002176
Yury Selivanov5376ba92015-06-22 12:19:30 -04002177class TestGetCoroutineState(unittest.TestCase):
2178
2179 def setUp(self):
2180 @types.coroutine
2181 def number_coroutine():
2182 for number in range(5):
2183 yield number
2184 async def coroutine():
2185 await number_coroutine()
2186 self.coroutine = coroutine()
2187
2188 def tearDown(self):
2189 self.coroutine.close()
2190
2191 def _coroutinestate(self):
2192 return inspect.getcoroutinestate(self.coroutine)
2193
2194 def test_created(self):
2195 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
2196
2197 def test_suspended(self):
2198 self.coroutine.send(None)
2199 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
2200
2201 def test_closed_after_exhaustion(self):
2202 while True:
2203 try:
2204 self.coroutine.send(None)
2205 except StopIteration:
2206 break
2207
2208 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2209
2210 def test_closed_after_immediate_exception(self):
2211 with self.assertRaises(RuntimeError):
2212 self.coroutine.throw(RuntimeError)
2213 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2214
2215 def test_easy_debugging(self):
2216 # repr() and str() of a coroutine state should contain the state name
2217 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2218 for name in names:
2219 state = getattr(inspect, name)
2220 self.assertIn(name, repr(state))
2221 self.assertIn(name, str(state))
2222
2223 def test_getcoroutinelocals(self):
2224 @types.coroutine
2225 def gencoro():
2226 yield
2227
2228 gencoro = gencoro()
2229 async def func(a=None):
2230 b = 'spam'
2231 await gencoro
2232
2233 coro = func()
2234 self.assertEqual(inspect.getcoroutinelocals(coro),
2235 {'a': None, 'gencoro': gencoro})
2236 coro.send(None)
2237 self.assertEqual(inspect.getcoroutinelocals(coro),
2238 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2239
2240
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002241class MySignature(inspect.Signature):
2242 # Top-level to make it picklable;
2243 # used in test_signature_object_pickle
2244 pass
2245
2246class MyParameter(inspect.Parameter):
2247 # Top-level to make it picklable;
2248 # used in test_signature_object_pickle
2249 pass
2250
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002251
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002252
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002253class TestSignatureObject(unittest.TestCase):
2254 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002255 def signature(func, **kw):
2256 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002257 return (tuple((param.name,
2258 (... if param.default is param.empty else param.default),
2259 (... if param.annotation is param.empty
2260 else param.annotation),
2261 str(param.kind).lower())
2262 for param in sig.parameters.values()),
2263 (... if sig.return_annotation is sig.empty
2264 else sig.return_annotation))
2265
2266 def test_signature_object(self):
2267 S = inspect.Signature
2268 P = inspect.Parameter
2269
2270 self.assertEqual(str(S()), '()')
Jens Reidel611836a2020-03-18 03:22:46 +01002271 self.assertEqual(repr(S().parameters), 'mappingproxy(OrderedDict())')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002272
Yury Selivanov07a9e452014-01-29 10:58:16 -05002273 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002274 pass
2275 sig = inspect.signature(test)
2276 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002277 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002278 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002279 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002280 args = sig.parameters['args']
2281 ko = sig.parameters['ko']
2282 kwargs = sig.parameters['kwargs']
2283
2284 S((po, pk, args, 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((pk, po, args, 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, args, pk, ko, kwargs))
2291
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002292 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002293 S((args, po, pk, ko, kwargs))
2294
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002295 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002296 S((po, pk, args, kwargs, ko))
2297
2298 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002299 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002300 S((po, pk, args, kwargs2, ko))
2301
Yury Selivanov07a9e452014-01-29 10:58:16 -05002302 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2303 S((pod, po))
2304
2305 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2306 S((po, pkd, pk))
2307
2308 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2309 S((pkd, pk))
2310
Yury Selivanov374375d2014-03-27 12:41:53 -04002311 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002312 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002313
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002314 def test_signature_object_pickle(self):
2315 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2316 foo_partial = functools.partial(foo, a=1)
2317
2318 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002319
2320 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2321 with self.subTest(pickle_ver=ver, subclass=False):
2322 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2323 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002324
2325 # Test that basic sub-classing works
2326 sig = inspect.signature(foo)
2327 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2328 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2329 mysig = MySignature().replace(parameters=myparams.values(),
2330 return_annotation=sig.return_annotation)
2331 self.assertTrue(isinstance(mysig, MySignature))
2332 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2333
2334 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2335 with self.subTest(pickle_ver=ver, subclass=True):
2336 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2337 self.assertEqual(mysig, sig_pickled)
2338 self.assertTrue(isinstance(sig_pickled, MySignature))
2339 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2340 MyParameter))
2341
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002342 def test_signature_immutability(self):
2343 def test(a):
2344 pass
2345 sig = inspect.signature(test)
2346
2347 with self.assertRaises(AttributeError):
2348 sig.foo = 'bar'
2349
2350 with self.assertRaises(TypeError):
2351 sig.parameters['a'] = None
2352
2353 def test_signature_on_noarg(self):
2354 def test():
2355 pass
2356 self.assertEqual(self.signature(test), ((), ...))
2357
2358 def test_signature_on_wargs(self):
2359 def test(a, b:'foo') -> 123:
2360 pass
2361 self.assertEqual(self.signature(test),
2362 ((('a', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002363 ('b', ..., 'foo', "positional_or_keyword")),
2364 123))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002365
2366 def test_signature_on_wkwonly(self):
2367 def test(*, a:float, b:str) -> int:
2368 pass
2369 self.assertEqual(self.signature(test),
2370 ((('a', ..., float, "keyword_only"),
2371 ('b', ..., str, "keyword_only")),
2372 int))
2373
2374 def test_signature_on_complex_args(self):
2375 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2376 pass
2377 self.assertEqual(self.signature(test),
2378 ((('a', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002379 ('b', 10, 'foo', "positional_or_keyword"),
2380 ('args', ..., 'bar', "var_positional"),
2381 ('spam', ..., 'baz', "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002382 ('ham', 123, ..., "keyword_only"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002383 ('kwargs', ..., int, "var_keyword")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002384 ...))
2385
Dong-hee Na378d7062017-05-18 04:00:51 +09002386 def test_signature_without_self(self):
2387 def test_args_only(*args): # NOQA
2388 pass
2389
2390 def test_args_kwargs_only(*args, **kwargs): # NOQA
2391 pass
2392
2393 class A:
2394 @classmethod
2395 def test_classmethod(*args): # NOQA
2396 pass
2397
2398 @staticmethod
2399 def test_staticmethod(*args): # NOQA
2400 pass
2401
2402 f1 = functools.partialmethod((test_classmethod), 1)
2403 f2 = functools.partialmethod((test_args_only), 1)
2404 f3 = functools.partialmethod((test_staticmethod), 1)
2405 f4 = functools.partialmethod((test_args_kwargs_only),1)
2406
2407 self.assertEqual(self.signature(test_args_only),
2408 ((('args', ..., ..., 'var_positional'),), ...))
2409 self.assertEqual(self.signature(test_args_kwargs_only),
2410 ((('args', ..., ..., 'var_positional'),
2411 ('kwargs', ..., ..., 'var_keyword')), ...))
2412 self.assertEqual(self.signature(A.f1),
2413 ((('args', ..., ..., 'var_positional'),), ...))
2414 self.assertEqual(self.signature(A.f2),
2415 ((('args', ..., ..., 'var_positional'),), ...))
2416 self.assertEqual(self.signature(A.f3),
2417 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002418 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002419 ((('args', ..., ..., 'var_positional'),
2420 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002421 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002422 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2423 "Signature information for builtins requires docstrings")
2424 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002425 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002426
Larry Hastings5c661892014-01-24 06:17:25 -08002427 def test_unbound_method(o):
2428 """Use this to test unbound methods (things that should have a self)"""
2429 signature = inspect.signature(o)
2430 self.assertTrue(isinstance(signature, inspect.Signature))
2431 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2432 return signature
2433
2434 def test_callable(o):
2435 """Use this to test bound methods or normal callables (things that don't expect self)"""
2436 signature = inspect.signature(o)
2437 self.assertTrue(isinstance(signature, inspect.Signature))
2438 if signature.parameters:
2439 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2440 return signature
2441
2442 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002443 def p(name): return signature.parameters[name].default
2444 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002445 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002446 self.assertEqual(p('d'), 3.14)
2447 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002448 self.assertEqual(p('n'), None)
2449 self.assertEqual(p('t'), True)
2450 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002451 self.assertEqual(p('local'), 3)
2452 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002453 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002454
Larry Hastings5c661892014-01-24 06:17:25 -08002455 test_callable(object)
2456
2457 # normal method
2458 # (PyMethodDescr_Type, "method_descriptor")
2459 test_unbound_method(_pickle.Pickler.dump)
2460 d = _pickle.Pickler(io.StringIO())
2461 test_callable(d.dump)
2462
2463 # static method
Serhiy Storchaka279f4462019-09-14 12:24:05 +03002464 test_callable(bytes.maketrans)
2465 test_callable(b'abc'.maketrans)
Larry Hastings5c661892014-01-24 06:17:25 -08002466
2467 # class method
2468 test_callable(dict.fromkeys)
2469 test_callable({}.fromkeys)
2470
2471 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2472 test_unbound_method(type.__call__)
2473 test_unbound_method(int.__add__)
2474 test_callable((3).__add__)
2475
2476 # _PyMethodWrapper_Type
2477 # support for 'method-wrapper'
2478 test_callable(min.__call__)
2479
Larry Hastings2623c8c2014-02-08 22:15:29 -08002480 # This doesn't work now.
2481 # (We don't have a valid signature for "type" in 3.4)
2482 with self.assertRaisesRegex(ValueError, "no signature found"):
2483 class ThisWorksNow:
2484 __call__ = type
2485 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002486
Yury Selivanov056e2652014-03-02 12:25:27 -05002487 # Regression test for issue #20786
2488 test_unbound_method(dict.__delitem__)
2489 test_unbound_method(property.__delete__)
2490
Zachary Ware8ef887c2015-04-13 18:22:35 -05002491 # Regression test for issue #20586
2492 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2493
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002494 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002495 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2496 "Signature information for builtins requires docstrings")
2497 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002498 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002499 func = _testcapi.docstring_with_signature_with_defaults
2500
2501 def decorator(func):
2502 @functools.wraps(func)
2503 def wrapper(*args, **kwargs) -> int:
2504 return func(*args, **kwargs)
2505 return wrapper
2506
2507 decorated_func = decorator(func)
2508
2509 self.assertEqual(inspect.signature(func),
2510 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002511
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002512 def wrapper_like(*args, **kwargs) -> int: pass
2513 self.assertEqual(inspect.signature(decorated_func,
2514 follow_wrapped=False),
2515 inspect.signature(wrapper_like))
2516
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002517 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002518 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002519 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002520 with self.assertRaisesRegex(ValueError,
2521 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002522 inspect.signature(_testcapi.docstring_no_signature)
2523
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002524 with self.assertRaisesRegex(ValueError,
2525 'no signature found for builtin'):
2526 inspect.signature(str)
2527
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002528 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002529 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002530 inspect.signature(42)
2531
Yury Selivanov63da7c72014-01-31 14:48:37 -05002532 def test_signature_from_functionlike_object(self):
2533 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2534 pass
2535
2536 class funclike:
2537 # Has to be callable, and have correct
2538 # __code__, __annotations__, __defaults__, __name__,
2539 # and __kwdefaults__ attributes
2540
2541 def __init__(self, func):
2542 self.__name__ = func.__name__
2543 self.__code__ = func.__code__
2544 self.__annotations__ = func.__annotations__
2545 self.__defaults__ = func.__defaults__
2546 self.__kwdefaults__ = func.__kwdefaults__
2547 self.func = func
2548
2549 def __call__(self, *args, **kwargs):
2550 return self.func(*args, **kwargs)
2551
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002552 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002553
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002554 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002555 self.assertEqual(sig_funclike, sig_func)
2556
2557 sig_funclike = inspect.signature(funclike(func))
2558 self.assertEqual(sig_funclike, sig_func)
2559
2560 # If object is not a duck type of function, then
2561 # signature will try to get a signature for its '__call__'
2562 # method
2563 fl = funclike(func)
2564 del fl.__defaults__
2565 self.assertEqual(self.signature(fl),
2566 ((('args', ..., ..., "var_positional"),
2567 ('kwargs', ..., ..., "var_keyword")),
2568 ...))
2569
Yury Selivanova773de02014-02-21 18:30:53 -05002570 # Test with cython-like builtins:
2571 _orig_isdesc = inspect.ismethoddescriptor
2572 def _isdesc(obj):
2573 if hasattr(obj, '_builtinmock'):
2574 return True
2575 return _orig_isdesc(obj)
2576
2577 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2578 builtin_func = funclike(func)
2579 # Make sure that our mock setup is working
2580 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2581 builtin_func._builtinmock = True
2582 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2583 self.assertEqual(inspect.signature(builtin_func), sig_func)
2584
Yury Selivanov63da7c72014-01-31 14:48:37 -05002585 def test_signature_functionlike_class(self):
2586 # We only want to duck type function-like objects,
2587 # not classes.
2588
2589 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2590 pass
2591
2592 class funclike:
2593 def __init__(self, marker):
2594 pass
2595
2596 __name__ = func.__name__
2597 __code__ = func.__code__
2598 __annotations__ = func.__annotations__
2599 __defaults__ = func.__defaults__
2600 __kwdefaults__ = func.__kwdefaults__
2601
Yury Selivanov63da7c72014-01-31 14:48:37 -05002602 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2603
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002604 def test_signature_on_method(self):
2605 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002606 def __init__(*args):
2607 pass
2608 def m1(self, arg1, arg2=1) -> int:
2609 pass
2610 def m2(*args):
2611 pass
2612 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002613 pass
2614
Yury Selivanov62560fb2014-01-28 12:26:24 -05002615 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002616 ((('arg1', ..., ..., "positional_or_keyword"),
2617 ('arg2', 1, ..., "positional_or_keyword")),
2618 int))
2619
Yury Selivanov62560fb2014-01-28 12:26:24 -05002620 self.assertEqual(self.signature(Test().m2),
2621 ((('args', ..., ..., "var_positional"),),
2622 ...))
2623
2624 self.assertEqual(self.signature(Test),
2625 ((('args', ..., ..., "var_positional"),),
2626 ...))
2627
2628 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2629 self.signature(Test())
2630
Yury Selivanov46c759d2015-05-27 21:56:53 -04002631 def test_signature_wrapped_bound_method(self):
2632 # Issue 24298
2633 class Test:
2634 def m1(self, arg1, arg2=1) -> int:
2635 pass
2636 @functools.wraps(Test().m1)
2637 def m1d(*args, **kwargs):
2638 pass
2639 self.assertEqual(self.signature(m1d),
2640 ((('arg1', ..., ..., "positional_or_keyword"),
2641 ('arg2', 1, ..., "positional_or_keyword")),
2642 int))
2643
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002644 def test_signature_on_classmethod(self):
2645 class Test:
2646 @classmethod
2647 def foo(cls, arg1, *, arg2=1):
2648 pass
2649
2650 meth = Test().foo
2651 self.assertEqual(self.signature(meth),
2652 ((('arg1', ..., ..., "positional_or_keyword"),
2653 ('arg2', 1, ..., "keyword_only")),
2654 ...))
2655
2656 meth = Test.foo
2657 self.assertEqual(self.signature(meth),
2658 ((('arg1', ..., ..., "positional_or_keyword"),
2659 ('arg2', 1, ..., "keyword_only")),
2660 ...))
2661
2662 def test_signature_on_staticmethod(self):
2663 class Test:
2664 @staticmethod
2665 def foo(cls, *, arg):
2666 pass
2667
2668 meth = Test().foo
2669 self.assertEqual(self.signature(meth),
2670 ((('cls', ..., ..., "positional_or_keyword"),
2671 ('arg', ..., ..., "keyword_only")),
2672 ...))
2673
2674 meth = Test.foo
2675 self.assertEqual(self.signature(meth),
2676 ((('cls', ..., ..., "positional_or_keyword"),
2677 ('arg', ..., ..., "keyword_only")),
2678 ...))
2679
2680 def test_signature_on_partial(self):
2681 from functools import partial
2682
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002683 Parameter = inspect.Parameter
2684
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002685 def test():
2686 pass
2687
2688 self.assertEqual(self.signature(partial(test)), ((), ...))
2689
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002690 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002691 inspect.signature(partial(test, 1))
2692
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002693 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002694 inspect.signature(partial(test, a=1))
2695
2696 def test(a, b, *, c, d):
2697 pass
2698
2699 self.assertEqual(self.signature(partial(test)),
2700 ((('a', ..., ..., "positional_or_keyword"),
2701 ('b', ..., ..., "positional_or_keyword"),
2702 ('c', ..., ..., "keyword_only"),
2703 ('d', ..., ..., "keyword_only")),
2704 ...))
2705
2706 self.assertEqual(self.signature(partial(test, 1)),
2707 ((('b', ..., ..., "positional_or_keyword"),
2708 ('c', ..., ..., "keyword_only"),
2709 ('d', ..., ..., "keyword_only")),
2710 ...))
2711
2712 self.assertEqual(self.signature(partial(test, 1, c=2)),
2713 ((('b', ..., ..., "positional_or_keyword"),
2714 ('c', 2, ..., "keyword_only"),
2715 ('d', ..., ..., "keyword_only")),
2716 ...))
2717
2718 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2719 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002720 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002721 ('c', 2, ..., "keyword_only"),
2722 ('d', ..., ..., "keyword_only")),
2723 ...))
2724
2725 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002726 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002727 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002728 ('d', ..., ..., "keyword_only")),
2729 ...))
2730
2731 self.assertEqual(self.signature(partial(test, a=1)),
2732 ((('a', 1, ..., "keyword_only"),
2733 ('b', ..., ..., "keyword_only"),
2734 ('c', ..., ..., "keyword_only"),
2735 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002736 ...))
2737
2738 def test(a, *args, b, **kwargs):
2739 pass
2740
2741 self.assertEqual(self.signature(partial(test, 1)),
2742 ((('args', ..., ..., "var_positional"),
2743 ('b', ..., ..., "keyword_only"),
2744 ('kwargs', ..., ..., "var_keyword")),
2745 ...))
2746
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002747 self.assertEqual(self.signature(partial(test, a=1)),
2748 ((('a', 1, ..., "keyword_only"),
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)),
2754 ((('args', ..., ..., "var_positional"),
2755 ('b', ..., ..., "keyword_only"),
2756 ('kwargs', ..., ..., "var_keyword")),
2757 ...))
2758
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002759 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2760 ((('args', ..., ..., "var_positional"),
2761 ('b', ..., ..., "keyword_only"),
2762 ('kwargs', ..., ..., "var_keyword")),
2763 ...))
2764
2765 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2766 ((('args', ..., ..., "var_positional"),
2767 ('b', 0, ..., "keyword_only"),
2768 ('kwargs', ..., ..., "var_keyword")),
2769 ...))
2770
2771 self.assertEqual(self.signature(partial(test, b=0)),
2772 ((('a', ..., ..., "positional_or_keyword"),
2773 ('args', ..., ..., "var_positional"),
2774 ('b', 0, ..., "keyword_only"),
2775 ('kwargs', ..., ..., "var_keyword")),
2776 ...))
2777
2778 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2779 ((('a', ..., ..., "positional_or_keyword"),
2780 ('args', ..., ..., "var_positional"),
2781 ('b', 0, ..., "keyword_only"),
2782 ('kwargs', ..., ..., "var_keyword")),
2783 ...))
2784
2785 def test(a, b, c:int) -> 42:
2786 pass
2787
2788 sig = test.__signature__ = inspect.signature(test)
2789
2790 self.assertEqual(self.signature(partial(partial(test, 1))),
2791 ((('b', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002792 ('c', ..., int, "positional_or_keyword")),
2793 42))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002794
2795 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002796 ((('c', ..., int, "positional_or_keyword"),),
2797 42))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002798
2799 psig = inspect.signature(partial(partial(test, 1), 2))
2800
2801 def foo(a):
2802 return a
2803 _foo = partial(partial(foo, a=10), a=20)
2804 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002805 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002806 ...))
2807 # check that we don't have any side-effects in signature(),
2808 # and the partial object is still functioning
2809 self.assertEqual(_foo(), 20)
2810
2811 def foo(a, b, c):
2812 return a, b, c
2813 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002814
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002815 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002816 ((('b', 30, ..., "keyword_only"),
2817 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002818 ...))
2819 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002820
2821 def foo(a, b, c, *, d):
2822 return a, b, c, d
2823 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2824 self.assertEqual(self.signature(_foo),
2825 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002826 ('b', 10, ..., "keyword_only"),
2827 ('c', 20, ..., "keyword_only"),
2828 ('d', 30, ..., "keyword_only"),
2829 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002830 ...))
2831 ba = inspect.signature(_foo).bind(a=200, b=11)
2832 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2833
2834 def foo(a=1, b=2, c=3):
2835 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002836 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2837
2838 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002839 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002840
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002841 ba = inspect.signature(_foo).bind(11, 12)
2842 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002843
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002844 ba = inspect.signature(_foo).bind(11, b=12)
2845 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002846
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002847 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002848 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2849
2850 _foo = partial(_foo, b=10, c=20)
2851 ba = inspect.signature(_foo).bind(12)
2852 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2853
2854
2855 def foo(a, b, c, d, **kwargs):
2856 pass
2857 sig = inspect.signature(foo)
2858 params = sig.parameters.copy()
2859 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2860 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2861 foo.__signature__ = inspect.Signature(params.values())
2862 sig = inspect.signature(foo)
2863 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2864
2865 self.assertEqual(self.signature(partial(foo, 1)),
2866 ((('b', ..., ..., 'positional_only'),
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)),
2873 ((('c', ..., ..., 'positional_or_keyword'),
2874 ('d', ..., ..., 'positional_or_keyword'),
2875 ('kwargs', ..., ..., 'var_keyword')),
2876 ...))
2877
2878 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2879 ((('d', ..., ..., 'positional_or_keyword'),
2880 ('kwargs', ..., ..., 'var_keyword')),
2881 ...))
2882
2883 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2884 ((('c', 3, ..., 'keyword_only'),
2885 ('d', ..., ..., 'keyword_only'),
2886 ('kwargs', ..., ..., 'var_keyword')),
2887 ...))
2888
2889 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2890 ((('b', ..., ..., 'positional_only'),
2891 ('c', 3, ..., 'keyword_only'),
2892 ('d', ..., ..., 'keyword_only'),
2893 ('kwargs', ..., ..., 'var_keyword')),
2894 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002895
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002896 def test_signature_on_partialmethod(self):
2897 from functools import partialmethod
2898
2899 class Spam:
2900 def test():
2901 pass
2902 ham = partialmethod(test)
2903
2904 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2905 inspect.signature(Spam.ham)
2906
2907 class Spam:
2908 def test(it, a, *, c) -> 'spam':
2909 pass
2910 ham = partialmethod(test, c=1)
2911
larryhastings74613a42021-04-29 21:16:28 -07002912 self.assertEqual(self.signature(Spam.ham, eval_str=False),
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002913 ((('it', ..., ..., 'positional_or_keyword'),
2914 ('a', ..., ..., 'positional_or_keyword'),
2915 ('c', 1, ..., 'keyword_only')),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002916 'spam'))
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002917
larryhastings74613a42021-04-29 21:16:28 -07002918 self.assertEqual(self.signature(Spam().ham, eval_str=False),
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002919 ((('a', ..., ..., 'positional_or_keyword'),
2920 ('c', 1, ..., 'keyword_only')),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002921 'spam'))
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002922
Yury Selivanov8a387212018-03-06 12:59:45 -05002923 class Spam:
2924 def test(self: 'anno', x):
2925 pass
2926
2927 g = partialmethod(test, 1)
2928
larryhastings74613a42021-04-29 21:16:28 -07002929 self.assertEqual(self.signature(Spam.g, eval_str=False),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002930 ((('self', ..., 'anno', 'positional_or_keyword'),),
Yury Selivanov8a387212018-03-06 12:59:45 -05002931 ...))
2932
Yury Selivanov0486f812014-01-29 12:18:59 -05002933 def test_signature_on_fake_partialmethod(self):
2934 def foo(a): pass
2935 foo._partialmethod = 'spam'
2936 self.assertEqual(str(inspect.signature(foo)), '(a)')
2937
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002938 def test_signature_on_decorated(self):
2939 import functools
2940
2941 def decorator(func):
2942 @functools.wraps(func)
2943 def wrapper(*args, **kwargs) -> int:
2944 return func(*args, **kwargs)
2945 return wrapper
2946
2947 class Foo:
2948 @decorator
2949 def bar(self, a, b):
2950 pass
2951
2952 self.assertEqual(self.signature(Foo.bar),
2953 ((('self', ..., ..., "positional_or_keyword"),
2954 ('a', ..., ..., "positional_or_keyword"),
2955 ('b', ..., ..., "positional_or_keyword")),
2956 ...))
2957
2958 self.assertEqual(self.signature(Foo().bar),
2959 ((('a', ..., ..., "positional_or_keyword"),
2960 ('b', ..., ..., "positional_or_keyword")),
2961 ...))
2962
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002963 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2964 ((('args', ..., ..., "var_positional"),
2965 ('kwargs', ..., ..., "var_keyword")),
2966 ...)) # functools.wraps will copy __annotations__
2967 # from "func" to "wrapper", hence no
2968 # return_annotation
2969
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002970 # Test that we handle method wrappers correctly
2971 def decorator(func):
2972 @functools.wraps(func)
2973 def wrapper(*args, **kwargs) -> int:
2974 return func(42, *args, **kwargs)
2975 sig = inspect.signature(func)
2976 new_params = tuple(sig.parameters.values())[1:]
2977 wrapper.__signature__ = sig.replace(parameters=new_params)
2978 return wrapper
2979
2980 class Foo:
2981 @decorator
2982 def __call__(self, a, b):
2983 pass
2984
2985 self.assertEqual(self.signature(Foo.__call__),
2986 ((('a', ..., ..., "positional_or_keyword"),
2987 ('b', ..., ..., "positional_or_keyword")),
2988 ...))
2989
2990 self.assertEqual(self.signature(Foo().__call__),
2991 ((('b', ..., ..., "positional_or_keyword"),),
2992 ...))
2993
Nick Coghlane8c45d62013-07-28 20:00:01 +10002994 # Test we handle __signature__ partway down the wrapper stack
2995 def wrapped_foo_call():
2996 pass
2997 wrapped_foo_call.__wrapped__ = Foo.__call__
2998
2999 self.assertEqual(self.signature(wrapped_foo_call),
3000 ((('a', ..., ..., "positional_or_keyword"),
3001 ('b', ..., ..., "positional_or_keyword")),
3002 ...))
3003
3004
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003005 def test_signature_on_class(self):
3006 class C:
3007 def __init__(self, a):
3008 pass
3009
3010 self.assertEqual(self.signature(C),
3011 ((('a', ..., ..., "positional_or_keyword"),),
3012 ...))
3013
3014 class CM(type):
3015 def __call__(cls, a):
3016 pass
3017 class C(metaclass=CM):
3018 def __init__(self, b):
3019 pass
3020
3021 self.assertEqual(self.signature(C),
3022 ((('a', ..., ..., "positional_or_keyword"),),
3023 ...))
3024
3025 class CM(type):
3026 def __new__(mcls, name, bases, dct, *, foo=1):
3027 return super().__new__(mcls, name, bases, dct)
3028 class C(metaclass=CM):
3029 def __init__(self, b):
3030 pass
3031
3032 self.assertEqual(self.signature(C),
3033 ((('b', ..., ..., "positional_or_keyword"),),
3034 ...))
3035
3036 self.assertEqual(self.signature(CM),
3037 ((('name', ..., ..., "positional_or_keyword"),
3038 ('bases', ..., ..., "positional_or_keyword"),
3039 ('dct', ..., ..., "positional_or_keyword"),
3040 ('foo', 1, ..., "keyword_only")),
3041 ...))
3042
3043 class CMM(type):
3044 def __new__(mcls, name, bases, dct, *, foo=1):
3045 return super().__new__(mcls, name, bases, dct)
3046 def __call__(cls, nm, bs, dt):
3047 return type(nm, bs, dt)
3048 class CM(type, metaclass=CMM):
3049 def __new__(mcls, name, bases, dct, *, bar=2):
3050 return super().__new__(mcls, name, bases, dct)
3051 class C(metaclass=CM):
3052 def __init__(self, b):
3053 pass
3054
3055 self.assertEqual(self.signature(CMM),
3056 ((('name', ..., ..., "positional_or_keyword"),
3057 ('bases', ..., ..., "positional_or_keyword"),
3058 ('dct', ..., ..., "positional_or_keyword"),
3059 ('foo', 1, ..., "keyword_only")),
3060 ...))
3061
3062 self.assertEqual(self.signature(CM),
3063 ((('nm', ..., ..., "positional_or_keyword"),
3064 ('bs', ..., ..., "positional_or_keyword"),
3065 ('dt', ..., ..., "positional_or_keyword")),
3066 ...))
3067
3068 self.assertEqual(self.signature(C),
3069 ((('b', ..., ..., "positional_or_keyword"),),
3070 ...))
3071
3072 class CM(type):
3073 def __init__(cls, name, bases, dct, *, bar=2):
3074 return super().__init__(name, bases, dct)
3075 class C(metaclass=CM):
3076 def __init__(self, b):
3077 pass
3078
3079 self.assertEqual(self.signature(CM),
3080 ((('name', ..., ..., "positional_or_keyword"),
3081 ('bases', ..., ..., "positional_or_keyword"),
3082 ('dct', ..., ..., "positional_or_keyword"),
3083 ('bar', 2, ..., "keyword_only")),
3084 ...))
3085
Miss Islington (bot)948e39a2021-07-16 06:25:57 -07003086 def test_signature_on_subclass(self):
3087 class A:
3088 def __new__(cls, a=1, *args, **kwargs):
3089 return object.__new__(cls)
3090 class B(A):
3091 def __init__(self, b):
3092 pass
3093 class C(A):
3094 def __new__(cls, a=1, b=2, *args, **kwargs):
3095 return object.__new__(cls)
3096 class D(A):
3097 pass
3098
3099 self.assertEqual(self.signature(B),
3100 ((('b', ..., ..., "positional_or_keyword"),),
3101 ...))
3102 self.assertEqual(self.signature(C),
3103 ((('a', 1, ..., 'positional_or_keyword'),
3104 ('b', 2, ..., 'positional_or_keyword'),
3105 ('args', ..., ..., 'var_positional'),
3106 ('kwargs', ..., ..., 'var_keyword')),
3107 ...))
3108 self.assertEqual(self.signature(D),
3109 ((('a', 1, ..., 'positional_or_keyword'),
3110 ('args', ..., ..., 'var_positional'),
3111 ('kwargs', ..., ..., 'var_keyword')),
3112 ...))
3113
3114 def test_signature_on_generic_subclass(self):
3115 from typing import Generic, TypeVar
3116
3117 T = TypeVar('T')
3118
3119 class A(Generic[T]):
3120 def __init__(self, *, a: int) -> None:
3121 pass
3122
3123 self.assertEqual(self.signature(A),
3124 ((('a', ..., int, 'keyword_only'),),
3125 None))
3126
Yury Selivanov145dff82014-02-01 13:49:29 -05003127 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3128 "Signature information for builtins requires docstrings")
3129 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003130 # Test classes without user-defined __init__ or __new__
3131 class C: pass
3132 self.assertEqual(str(inspect.signature(C)), '()')
3133 class D(C): pass
3134 self.assertEqual(str(inspect.signature(D)), '()')
3135
3136 # Test meta-classes without user-defined __init__ or __new__
3137 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003138 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08003139 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
3140 self.assertEqual(inspect.signature(C), None)
3141 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
3142 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05003143
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003144 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3145 "Signature information for builtins requires docstrings")
3146 def test_signature_on_builtin_class(self):
Antoine Pitrou91f43802019-05-26 17:10:09 +02003147 expected = ('(file, protocol=None, fix_imports=True, '
3148 'buffer_callback=None)')
3149 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003150
3151 class P(_pickle.Pickler): pass
3152 class EmptyTrait: pass
3153 class P2(EmptyTrait, P): pass
Antoine Pitrou91f43802019-05-26 17:10:09 +02003154 self.assertEqual(str(inspect.signature(P)), expected)
3155 self.assertEqual(str(inspect.signature(P2)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05003156
3157 class P3(P2):
3158 def __init__(self, spam):
3159 pass
3160 self.assertEqual(str(inspect.signature(P3)), '(spam)')
3161
3162 class MetaP(type):
3163 def __call__(cls, foo, bar):
3164 pass
3165 class P4(P2, metaclass=MetaP):
3166 pass
3167 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
3168
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003169 def test_signature_on_callable_objects(self):
3170 class Foo:
3171 def __call__(self, a):
3172 pass
3173
3174 self.assertEqual(self.signature(Foo()),
3175 ((('a', ..., ..., "positional_or_keyword"),),
3176 ...))
3177
3178 class Spam:
3179 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003180 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003181 inspect.signature(Spam())
3182
3183 class Bar(Spam, Foo):
3184 pass
3185
3186 self.assertEqual(self.signature(Bar()),
3187 ((('a', ..., ..., "positional_or_keyword"),),
3188 ...))
3189
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003190 class Wrapped:
3191 pass
3192 Wrapped.__wrapped__ = lambda a: None
3193 self.assertEqual(self.signature(Wrapped),
3194 ((('a', ..., ..., "positional_or_keyword"),),
3195 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10003196 # wrapper loop:
3197 Wrapped.__wrapped__ = Wrapped
3198 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3199 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003200
3201 def test_signature_on_lambdas(self):
3202 self.assertEqual(self.signature((lambda a=10: a)),
3203 ((('a', 10, ..., "positional_or_keyword"),),
3204 ...))
3205
3206 def test_signature_equality(self):
3207 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003208 self.assertFalse(inspect.signature(foo) == 42)
3209 self.assertTrue(inspect.signature(foo) != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003210 self.assertTrue(inspect.signature(foo) == ALWAYS_EQ)
3211 self.assertFalse(inspect.signature(foo) != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003212
3213 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003214 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3215 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003216 self.assertEqual(
3217 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003218
3219 def bar(a, *, b:int) -> 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): 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, *, b:int=42) -> 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, *, c) -> 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
3243 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003244 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3245 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003246 self.assertNotEqual(
3247 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003248 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003249 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3250 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003251 self.assertNotEqual(
3252 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003253
3254 def foo(*, a, b, c): pass
3255 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003256 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3257 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003258 self.assertEqual(
3259 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003260
3261 def foo(*, a=1, b, c): pass
3262 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003263 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3264 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003265 self.assertEqual(
3266 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003267
3268 def foo(pos, *, a=1, b, c): pass
3269 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003270 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3271 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003272 self.assertEqual(
3273 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003274
3275 def foo(pos, *, a, b, c): pass
3276 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003277 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3278 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003279 self.assertNotEqual(
3280 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003281
3282 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3283 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003284 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3285 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003286 self.assertEqual(
3287 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003288
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003289 def test_signature_hashable(self):
3290 S = inspect.Signature
3291 P = inspect.Parameter
3292
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003293 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003294 foo_sig = inspect.signature(foo)
3295
3296 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3297
3298 self.assertEqual(hash(foo_sig), hash(manual_sig))
3299 self.assertNotEqual(hash(foo_sig),
3300 hash(manual_sig.replace(return_annotation='spam')))
3301
3302 def bar(a) -> 1: pass
3303 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3304
3305 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003306 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003307 hash(inspect.signature(foo))
3308
Pablo Galindob0544ba2021-04-21 12:41:19 +01003309 def foo(a) -> {}: pass
3310 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3311 hash(inspect.signature(foo))
3312
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003313 def test_signature_str(self):
3314 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3315 pass
3316 self.assertEqual(str(inspect.signature(foo)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003317 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003318
3319 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3320 pass
3321 self.assertEqual(str(inspect.signature(foo)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003322 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003323
3324 def foo():
3325 pass
3326 self.assertEqual(str(inspect.signature(foo)), '()')
3327
Miss Islington (bot)ce7a6af2021-10-27 14:57:07 -07003328 def foo(a: list[str]) -> tuple[str, float]:
3329 pass
3330 self.assertEqual(str(inspect.signature(foo)),
3331 '(a: list[str]) -> tuple[str, float]')
3332
3333 from typing import Tuple
3334 def foo(a: list[str]) -> Tuple[str, float]:
3335 pass
3336 self.assertEqual(str(inspect.signature(foo)),
3337 '(a: list[str]) -> Tuple[str, float]')
3338
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003339 def test_signature_str_positional_only(self):
3340 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003341 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003342
3343 def test(a_po, *, b, **kwargs):
3344 return a_po, kwargs
3345
3346 sig = inspect.signature(test)
3347 new_params = list(sig.parameters.values())
3348 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3349 test.__signature__ = sig.replace(parameters=new_params)
3350
3351 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003352 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003353
Yury Selivanov2393dca2014-01-27 15:07:58 -05003354 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3355 '(foo, /)')
3356
3357 self.assertEqual(str(S(parameters=[
3358 P('foo', P.POSITIONAL_ONLY),
3359 P('bar', P.VAR_KEYWORD)])),
3360 '(foo, /, **bar)')
3361
3362 self.assertEqual(str(S(parameters=[
3363 P('foo', P.POSITIONAL_ONLY),
3364 P('bar', P.VAR_POSITIONAL)])),
3365 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003366
3367 def test_signature_replace_anno(self):
3368 def test() -> 42:
3369 pass
3370
3371 sig = inspect.signature(test)
3372 sig = sig.replace(return_annotation=None)
3373 self.assertIs(sig.return_annotation, None)
3374 sig = sig.replace(return_annotation=sig.empty)
3375 self.assertIs(sig.return_annotation, sig.empty)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003376 sig = sig.replace(return_annotation=42)
3377 self.assertEqual(sig.return_annotation, 42)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003378 self.assertEqual(sig, inspect.signature(test))
3379
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003380 def test_signature_on_mangled_parameters(self):
3381 class Spam:
3382 def foo(self, __p1:1=2, *, __p2:2=3):
3383 pass
3384 class Ham(Spam):
3385 pass
3386
3387 self.assertEqual(self.signature(Spam.foo),
3388 ((('self', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003389 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3390 ('_Spam__p2', 3, 2, "keyword_only")),
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003391 ...))
3392
3393 self.assertEqual(self.signature(Spam.foo),
3394 self.signature(Ham.foo))
3395
Yury Selivanovda396452014-03-27 12:09:24 -04003396 def test_signature_from_callable_python_obj(self):
3397 class MySignature(inspect.Signature): pass
3398 def foo(a, *, b:1): pass
3399 foo_sig = MySignature.from_callable(foo)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003400 self.assertIsInstance(foo_sig, MySignature)
3401
3402 def test_signature_from_callable_class(self):
3403 # A regression test for a class inheriting its signature from `object`.
3404 class MySignature(inspect.Signature): pass
3405 class foo: pass
3406 foo_sig = MySignature.from_callable(foo)
3407 self.assertIsInstance(foo_sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003408
3409 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3410 "Signature information for builtins requires docstrings")
3411 def test_signature_from_callable_builtin_obj(self):
3412 class MySignature(inspect.Signature): pass
3413 sig = MySignature.from_callable(_pickle.Pickler)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003414 self.assertIsInstance(sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003415
larryhastingsf36ba122018-01-28 11:13:09 -08003416 def test_signature_definition_order_preserved_on_kwonly(self):
3417 for fn in signatures_with_lexicographic_keyword_only_parameters():
3418 signature = inspect.signature(fn)
3419 l = list(signature.parameters)
3420 sorted_l = sorted(l)
3421 self.assertTrue(l)
3422 self.assertEqual(l, sorted_l)
3423 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3424 l = list(signature.parameters)
3425 self.assertEqual(l, unsorted_keyword_only_parameters)
3426
Jens Reidel611836a2020-03-18 03:22:46 +01003427 def test_signater_parameters_is_ordered(self):
3428 p1 = inspect.signature(lambda x, y: None).parameters
3429 p2 = inspect.signature(lambda y, x: None).parameters
3430 self.assertNotEqual(p1, p2)
3431
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003432 def test_signature_annotations_with_local_namespaces(self):
3433 class Foo: ...
3434 def func(foo: Foo) -> int: pass
Pablo Galindob0544ba2021-04-21 12:41:19 +01003435 def func2(foo: Foo, bar: 'Bar') -> int: pass
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003436
3437 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3438 with self.subTest(signature_func = signature_func):
3439 sig1 = signature_func(func)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003440 self.assertEqual(sig1.return_annotation, int)
3441 self.assertEqual(sig1.parameters['foo'].annotation, Foo)
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003442
larryhastings74613a42021-04-29 21:16:28 -07003443 sig2 = signature_func(func, locals=locals())
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003444 self.assertEqual(sig2.return_annotation, int)
3445 self.assertEqual(sig2.parameters['foo'].annotation, Foo)
3446
larryhastings74613a42021-04-29 21:16:28 -07003447 sig3 = signature_func(func2, globals={'Bar': int}, locals=locals())
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003448 self.assertEqual(sig3.return_annotation, int)
3449 self.assertEqual(sig3.parameters['foo'].annotation, Foo)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003450 self.assertEqual(sig3.parameters['bar'].annotation, 'Bar')
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003451
larryhastings74613a42021-04-29 21:16:28 -07003452 def test_signature_eval_str(self):
3453 isa = inspect_stringized_annotations
3454 sig = inspect.Signature
3455 par = inspect.Parameter
3456 PORK = inspect.Parameter.POSITIONAL_OR_KEYWORD
3457 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3458 with self.subTest(signature_func = signature_func):
3459 self.assertEqual(
3460 signature_func(isa.MyClass),
3461 sig(
3462 parameters=(
3463 par('a', PORK),
3464 par('b', PORK),
3465 )))
3466 self.assertEqual(
3467 signature_func(isa.function),
3468 sig(
3469 return_annotation='MyClass',
3470 parameters=(
3471 par('a', PORK, annotation='int'),
3472 par('b', PORK, annotation='str'),
3473 )))
3474 self.assertEqual(
3475 signature_func(isa.function2),
3476 sig(
3477 return_annotation='MyClass',
3478 parameters=(
3479 par('a', PORK, annotation='int'),
3480 par('b', PORK, annotation="'str'"),
3481 par('c', PORK, annotation="MyClass"),
3482 )))
3483 self.assertEqual(
3484 signature_func(isa.function3),
3485 sig(
3486 parameters=(
3487 par('a', PORK, annotation="'int'"),
3488 par('b', PORK, annotation="'str'"),
3489 par('c', PORK, annotation="'MyClass'"),
3490 )))
3491
3492 self.assertEqual(signature_func(isa.UnannotatedClass), sig())
3493 self.assertEqual(signature_func(isa.unannotated_function),
3494 sig(
3495 parameters=(
3496 par('a', PORK),
3497 par('b', PORK),
3498 par('c', PORK),
3499 )))
3500
3501 self.assertEqual(
3502 signature_func(isa.MyClass, eval_str=True),
3503 sig(
3504 parameters=(
3505 par('a', PORK),
3506 par('b', PORK),
3507 )))
3508 self.assertEqual(
3509 signature_func(isa.function, eval_str=True),
3510 sig(
3511 return_annotation=isa.MyClass,
3512 parameters=(
3513 par('a', PORK, annotation=int),
3514 par('b', PORK, annotation=str),
3515 )))
3516 self.assertEqual(
3517 signature_func(isa.function2, eval_str=True),
3518 sig(
3519 return_annotation=isa.MyClass,
3520 parameters=(
3521 par('a', PORK, annotation=int),
3522 par('b', PORK, annotation='str'),
3523 par('c', PORK, annotation=isa.MyClass),
3524 )))
3525 self.assertEqual(
3526 signature_func(isa.function3, eval_str=True),
3527 sig(
3528 parameters=(
3529 par('a', PORK, annotation='int'),
3530 par('b', PORK, annotation='str'),
3531 par('c', PORK, annotation='MyClass'),
3532 )))
3533
3534 globalns = {'int': float, 'str': complex}
3535 localns = {'str': tuple, 'MyClass': dict}
3536 with self.assertRaises(NameError):
3537 signature_func(isa.function, eval_str=True, globals=globalns)
3538
3539 self.assertEqual(
3540 signature_func(isa.function, eval_str=True, locals=localns),
3541 sig(
3542 return_annotation=dict,
3543 parameters=(
3544 par('a', PORK, annotation=int),
3545 par('b', PORK, annotation=tuple),
3546 )))
3547
3548 self.assertEqual(
3549 signature_func(isa.function, eval_str=True, globals=globalns, locals=localns),
3550 sig(
3551 return_annotation=dict,
3552 parameters=(
3553 par('a', PORK, annotation=float),
3554 par('b', PORK, annotation=tuple),
3555 )))
3556
3557 def test_signature_none_annotation(self):
3558 class funclike:
3559 # Has to be callable, and have correct
3560 # __code__, __annotations__, __defaults__, __name__,
3561 # and __kwdefaults__ attributes
3562
3563 def __init__(self, func):
3564 self.__name__ = func.__name__
3565 self.__code__ = func.__code__
3566 self.__annotations__ = func.__annotations__
3567 self.__defaults__ = func.__defaults__
3568 self.__kwdefaults__ = func.__kwdefaults__
3569 self.func = func
3570
3571 def __call__(self, *args, **kwargs):
3572 return self.func(*args, **kwargs)
3573
3574 def foo(): pass
3575 foo = funclike(foo)
3576 foo.__annotations__ = None
3577 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3578 with self.subTest(signature_func = signature_func):
3579 self.assertEqual(signature_func(foo), inspect.Signature())
3580 self.assertEqual(inspect.get_annotations(foo), {})
3581
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003582
3583class TestParameterObject(unittest.TestCase):
3584 def test_signature_parameter_kinds(self):
3585 P = inspect.Parameter
3586 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3587 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3588
3589 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3590 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3591
3592 def test_signature_parameter_object(self):
3593 p = inspect.Parameter('foo', default=10,
3594 kind=inspect.Parameter.POSITIONAL_ONLY)
3595 self.assertEqual(p.name, 'foo')
3596 self.assertEqual(p.default, 10)
3597 self.assertIs(p.annotation, p.empty)
3598 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3599
Dong-hee Naa9cab432018-05-30 00:04:08 +09003600 with self.assertRaisesRegex(ValueError, "value '123' is "
3601 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003602 inspect.Parameter('foo', default=10, kind='123')
3603
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003604 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003605 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3606
Yury Selivanov2393dca2014-01-27 15:07:58 -05003607 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003608 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3609
Yury Selivanov2393dca2014-01-27 15:07:58 -05003610 with self.assertRaisesRegex(ValueError,
3611 'is not a valid parameter name'):
3612 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3613
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003614 with self.assertRaisesRegex(ValueError,
3615 'is not a valid parameter name'):
3616 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3617
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003618 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003619 inspect.Parameter('a', default=42,
3620 kind=inspect.Parameter.VAR_KEYWORD)
3621
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003622 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003623 inspect.Parameter('a', default=42,
3624 kind=inspect.Parameter.VAR_POSITIONAL)
3625
3626 p = inspect.Parameter('a', default=42,
3627 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003628 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003629 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3630
3631 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003632 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003633
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003634 def test_signature_parameter_hashable(self):
3635 P = inspect.Parameter
3636 foo = P('foo', kind=P.POSITIONAL_ONLY)
3637 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3638 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3639 default=42)))
3640 self.assertNotEqual(hash(foo),
3641 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3642
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003643 def test_signature_parameter_equality(self):
3644 P = inspect.Parameter
3645 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3646
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003647 self.assertTrue(p == p)
3648 self.assertFalse(p != p)
3649 self.assertFalse(p == 42)
3650 self.assertTrue(p != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003651 self.assertTrue(p == ALWAYS_EQ)
3652 self.assertFalse(p != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003653
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003654 self.assertTrue(p == P('foo', default=42,
3655 kind=inspect.Parameter.KEYWORD_ONLY))
3656 self.assertFalse(p != P('foo', default=42,
3657 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003658
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003659 def test_signature_parameter_replace(self):
3660 p = inspect.Parameter('foo', default=42,
3661 kind=inspect.Parameter.KEYWORD_ONLY)
3662
3663 self.assertIsNot(p, p.replace())
3664 self.assertEqual(p, p.replace())
3665
3666 p2 = p.replace(annotation=1)
3667 self.assertEqual(p2.annotation, 1)
3668 p2 = p2.replace(annotation=p2.empty)
3669 self.assertEqual(p, p2)
3670
3671 p2 = p2.replace(name='bar')
3672 self.assertEqual(p2.name, 'bar')
3673 self.assertNotEqual(p2, p)
3674
Yury Selivanov2393dca2014-01-27 15:07:58 -05003675 with self.assertRaisesRegex(ValueError,
3676 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003677 p2 = p2.replace(name=p2.empty)
3678
3679 p2 = p2.replace(name='foo', default=None)
3680 self.assertIs(p2.default, None)
3681 self.assertNotEqual(p2, p)
3682
3683 p2 = p2.replace(name='foo', default=p2.empty)
3684 self.assertIs(p2.default, p2.empty)
3685
3686
3687 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3688 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3689 self.assertNotEqual(p2, p)
3690
Dong-hee Naa9cab432018-05-30 00:04:08 +09003691 with self.assertRaisesRegex(ValueError,
3692 "value <class 'inspect._empty'> "
3693 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003694 p2 = p2.replace(kind=p2.empty)
3695
3696 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3697 self.assertEqual(p2, p)
3698
3699 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003700 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3701 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003702
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003703 @cpython_only
3704 def test_signature_parameter_implicit(self):
3705 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003706 'implicit arguments must be passed as '
3707 'positional or keyword arguments, '
3708 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003709 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3710
3711 param = inspect.Parameter(
3712 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3713 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3714 self.assertEqual(param.name, 'implicit0')
3715
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003716 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003717 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003718
3719 with self.assertRaises(AttributeError):
3720 p.foo = 'bar'
3721
3722 with self.assertRaises(AttributeError):
3723 p.kind = 123
3724
3725
3726class TestSignatureBind(unittest.TestCase):
3727 @staticmethod
3728 def call(func, *args, **kwargs):
3729 sig = inspect.signature(func)
3730 ba = sig.bind(*args, **kwargs)
3731 return func(*ba.args, **ba.kwargs)
3732
3733 def test_signature_bind_empty(self):
3734 def test():
3735 return 42
3736
3737 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003738 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003739 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003740 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003741 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003742 with self.assertRaisesRegex(
3743 TypeError, "got an unexpected keyword argument 'spam'"):
3744
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003745 self.call(test, spam=1)
3746
3747 def test_signature_bind_var(self):
3748 def test(*args, **kwargs):
3749 return args, kwargs
3750
3751 self.assertEqual(self.call(test), ((), {}))
3752 self.assertEqual(self.call(test, 1), ((1,), {}))
3753 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3754 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3755 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3756 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3757 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3758 ((1, 2), {'foo': 'bar'}))
3759
3760 def test_signature_bind_just_args(self):
3761 def test(a, b, c):
3762 return a, b, c
3763
3764 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3765
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003766 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003767 self.call(test, 1, 2, 3, 4)
3768
Yury Selivanov86872752015-05-19 00:27:49 -04003769 with self.assertRaisesRegex(TypeError,
3770 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003771 self.call(test, 1)
3772
Yury Selivanov86872752015-05-19 00:27:49 -04003773 with self.assertRaisesRegex(TypeError,
3774 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003775 self.call(test)
3776
3777 def test(a, b, c=10):
3778 return a, b, c
3779 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3780 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3781
3782 def test(a=1, b=2, c=3):
3783 return a, b, c
3784 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3785 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3786 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3787
3788 def test_signature_bind_varargs_order(self):
3789 def test(*args):
3790 return args
3791
3792 self.assertEqual(self.call(test), ())
3793 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3794
3795 def test_signature_bind_args_and_varargs(self):
3796 def test(a, b, c=3, *args):
3797 return a, b, c, args
3798
3799 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3800 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3801 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3802 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3803
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003804 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003805 "multiple values for argument 'c'"):
3806 self.call(test, 1, 2, 3, c=4)
3807
3808 def test_signature_bind_just_kwargs(self):
3809 def test(**kwargs):
3810 return kwargs
3811
3812 self.assertEqual(self.call(test), {})
3813 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3814 {'foo': 'bar', 'spam': 'ham'})
3815
3816 def test_signature_bind_args_and_kwargs(self):
3817 def test(a, b, c=3, **kwargs):
3818 return a, b, c, kwargs
3819
3820 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3821 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3822 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3823 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3824 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3825 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3826 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3827 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3828 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3829 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3830 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3831 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3832 (1, 2, 4, {'foo': 'bar'}))
3833 self.assertEqual(self.call(test, c=5, a=4, b=3),
3834 (4, 3, 5, {}))
3835
3836 def test_signature_bind_kwonly(self):
3837 def test(*, foo):
3838 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003839 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003840 'too many positional arguments'):
3841 self.call(test, 1)
3842 self.assertEqual(self.call(test, foo=1), 1)
3843
3844 def test(a, *, foo=1, bar):
3845 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003846 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003847 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003848 self.call(test, 1)
3849
3850 def test(foo, *, bar):
3851 return foo, bar
3852 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3853 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3854
Yury Selivanov86872752015-05-19 00:27:49 -04003855 with self.assertRaisesRegex(
3856 TypeError, "got an unexpected keyword argument 'spam'"):
3857
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003858 self.call(test, bar=2, foo=1, spam=10)
3859
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003860 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003861 'too many positional arguments'):
3862 self.call(test, 1, 2)
3863
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003864 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003865 'too many positional arguments'):
3866 self.call(test, 1, 2, bar=2)
3867
Yury Selivanov86872752015-05-19 00:27:49 -04003868 with self.assertRaisesRegex(
3869 TypeError, "got an unexpected keyword argument 'spam'"):
3870
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003871 self.call(test, 1, bar=2, spam='ham')
3872
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003873 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003874 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003875 self.call(test, 1)
3876
3877 def test(foo, *, bar, **bin):
3878 return foo, bar, bin
3879 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3880 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3881 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3882 (1, 2, {'spam': 'ham'}))
3883 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3884 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003885 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003886 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003887 self.call(test, spam='ham', bar=2)
3888 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3889 (1, 2, {'bin': 1, 'spam': 10}))
3890
3891 def test_signature_bind_arguments(self):
3892 def test(a, *args, b, z=100, **kwargs):
3893 pass
3894 sig = inspect.signature(test)
3895 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3896 # we won't have 'z' argument in the bound arguments object, as we didn't
3897 # pass it to the 'bind'
3898 self.assertEqual(tuple(ba.arguments.items()),
3899 (('a', 10), ('args', (20,)), ('b', 30),
3900 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3901 self.assertEqual(ba.kwargs,
3902 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3903 self.assertEqual(ba.args, (10, 20))
3904
3905 def test_signature_bind_positional_only(self):
3906 P = inspect.Parameter
3907
3908 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3909 return a_po, b_po, c_po, foo, bar, kwargs
3910
3911 sig = inspect.signature(test)
3912 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3913 for name in ('a_po', 'b_po', 'c_po'):
3914 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3915 new_sig = sig.replace(parameters=new_params.values())
3916 test.__signature__ = new_sig
3917
3918 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3919 (1, 2, 4, 5, 6, {}))
3920
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003921 self.assertEqual(self.call(test, 1, 2),
3922 (1, 2, 3, 42, 50, {}))
3923
3924 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3925 (1, 2, 3, 4, 5, {}))
3926
3927 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3928 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3929
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003930 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003931 self.call(test, 1, 2, c_po=4)
3932
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003933 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003934 self.call(test, a_po=1, b_po=2)
3935
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003936 def test_signature_bind_with_self_arg(self):
3937 # Issue #17071: one of the parameters is named "self
3938 def test(a, self, b):
3939 pass
3940 sig = inspect.signature(test)
3941 ba = sig.bind(1, 2, 3)
3942 self.assertEqual(ba.args, (1, 2, 3))
3943 ba = sig.bind(1, self=2, b=3)
3944 self.assertEqual(ba.args, (1, 2, 3))
3945
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003946 def test_signature_bind_vararg_name(self):
3947 def test(a, *args):
3948 return a, args
3949 sig = inspect.signature(test)
3950
Yury Selivanov86872752015-05-19 00:27:49 -04003951 with self.assertRaisesRegex(
3952 TypeError, "got an unexpected keyword argument 'args'"):
3953
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003954 sig.bind(a=0, args=1)
3955
3956 def test(*args, **kwargs):
3957 return args, kwargs
3958 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3959
3960 sig = inspect.signature(test)
3961 ba = sig.bind(args=1)
3962 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3963
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003964 @cpython_only
3965 def test_signature_bind_implicit_arg(self):
3966 # Issue #19611: getcallargs should work with set comprehensions
3967 def make_set():
3968 return {z * z for z in range(5)}
3969 setcomp_code = make_set.__code__.co_consts[1]
3970 setcomp_func = types.FunctionType(setcomp_code, {})
3971
3972 iterator = iter(range(5))
3973 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3974
Pablo Galindof3ef06a2019-10-15 12:40:02 +01003975 def test_signature_bind_posonly_kwargs(self):
3976 def foo(bar, /, **kwargs):
3977 return bar, kwargs.get(bar)
3978
3979 sig = inspect.signature(foo)
3980 result = sig.bind("pos-only", bar="keyword")
3981
3982 self.assertEqual(result.kwargs, {"bar": "keyword"})
3983 self.assertIn(("bar", "pos-only"), result.arguments.items())
3984
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003985
3986class TestBoundArguments(unittest.TestCase):
3987 def test_signature_bound_arguments_unhashable(self):
3988 def foo(a): pass
3989 ba = inspect.signature(foo).bind(1)
3990
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003991 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003992 hash(ba)
3993
3994 def test_signature_bound_arguments_equality(self):
3995 def foo(a): pass
3996 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003997 self.assertTrue(ba == ba)
3998 self.assertFalse(ba != ba)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003999 self.assertTrue(ba == ALWAYS_EQ)
4000 self.assertFalse(ba != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004001
4002 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03004003 self.assertTrue(ba == ba2)
4004 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004005
4006 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03004007 self.assertFalse(ba == ba3)
4008 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004009 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03004010 self.assertTrue(ba == ba3)
4011 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004012
4013 def bar(b): pass
4014 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03004015 self.assertFalse(ba == ba4)
4016 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004017
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04004018 def foo(*, a, b): pass
4019 sig = inspect.signature(foo)
4020 ba1 = sig.bind(a=1, b=2)
4021 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03004022 self.assertTrue(ba1 == ba2)
4023 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04004024
Yury Selivanova5d63dd2014-03-27 11:31:43 -04004025 def test_signature_bound_arguments_pickle(self):
4026 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
4027 sig = inspect.signature(foo)
4028 ba = sig.bind(20, 30, z={})
4029
4030 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
4031 with self.subTest(pickle_ver=ver):
4032 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
4033 self.assertEqual(ba, ba_pickled)
4034
Yury Selivanov3f6538f2015-05-14 18:47:17 -04004035 def test_signature_bound_arguments_repr(self):
4036 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
4037 sig = inspect.signature(foo)
4038 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04004039 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04004040
Yury Selivanovb907a512015-05-16 13:45:09 -04004041 def test_signature_bound_arguments_apply_defaults(self):
4042 def foo(a, b=1, *args, c:1={}, **kw): pass
4043 sig = inspect.signature(foo)
4044
4045 ba = sig.bind(20)
4046 ba.apply_defaults()
4047 self.assertEqual(
4048 list(ba.arguments.items()),
4049 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
4050
4051 # Make sure that we preserve the order:
4052 # i.e. 'c' should be *before* 'kw'.
4053 ba = sig.bind(10, 20, 30, d=1)
4054 ba.apply_defaults()
4055 self.assertEqual(
4056 list(ba.arguments.items()),
4057 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
4058
4059 # Make sure that BoundArguments produced by bind_partial()
4060 # are supported.
4061 def foo(a, b): pass
4062 sig = inspect.signature(foo)
4063 ba = sig.bind_partial(20)
4064 ba.apply_defaults()
4065 self.assertEqual(
4066 list(ba.arguments.items()),
4067 [('a', 20)])
4068
4069 # Test no args
4070 def foo(): pass
4071 sig = inspect.signature(foo)
4072 ba = sig.bind()
4073 ba.apply_defaults()
4074 self.assertEqual(list(ba.arguments.items()), [])
4075
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05004076 # Make sure a no-args binding still acquires proper defaults.
4077 def foo(a='spam'): pass
4078 sig = inspect.signature(foo)
4079 ba = sig.bind()
4080 ba.apply_defaults()
4081 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
4082
Rémi Lapeyre2cca8ef2020-01-28 13:47:03 +01004083 def test_signature_bound_arguments_arguments_type(self):
4084 def foo(a): pass
4085 ba = inspect.signature(foo).bind(1)
4086 self.assertIs(type(ba.arguments), dict)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004087
Yury Selivanovd82eddc2014-01-29 11:24:39 -05004088class TestSignaturePrivateHelpers(unittest.TestCase):
4089 def test_signature_get_bound_param(self):
4090 getter = inspect._signature_get_bound_param
4091
4092 self.assertEqual(getter('($self)'), 'self')
4093 self.assertEqual(getter('($self, obj)'), 'self')
4094 self.assertEqual(getter('($cls, /, obj)'), 'cls')
4095
Larry Hastings2623c8c2014-02-08 22:15:29 -08004096 def _strip_non_python_syntax(self, input,
4097 clean_signature, self_parameter, last_positional_only):
4098 computed_clean_signature, \
4099 computed_self_parameter, \
4100 computed_last_positional_only = \
4101 inspect._signature_strip_non_python_syntax(input)
4102 self.assertEqual(computed_clean_signature, clean_signature)
4103 self.assertEqual(computed_self_parameter, self_parameter)
4104 self.assertEqual(computed_last_positional_only, last_positional_only)
4105
4106 def test_signature_strip_non_python_syntax(self):
4107 self._strip_non_python_syntax(
4108 "($module, /, path, mode, *, dir_fd=None, " +
4109 "effective_ids=False,\n follow_symlinks=True)",
4110 "(module, path, mode, *, dir_fd=None, " +
4111 "effective_ids=False, follow_symlinks=True)",
4112 0,
4113 0)
4114
4115 self._strip_non_python_syntax(
4116 "($module, word, salt, /)",
4117 "(module, word, salt)",
4118 0,
4119 2)
4120
4121 self._strip_non_python_syntax(
4122 "(x, y=None, z=None, /)",
4123 "(x, y=None, z=None)",
4124 None,
4125 2)
4126
4127 self._strip_non_python_syntax(
4128 "(x, y=None, z=None)",
4129 "(x, y=None, z=None)",
4130 None,
4131 None)
4132
4133 self._strip_non_python_syntax(
4134 "(x,\n y=None,\n z = None )",
4135 "(x, y=None, z=None)",
4136 None,
4137 None)
4138
4139 self._strip_non_python_syntax(
4140 "",
4141 "",
4142 None,
4143 None)
4144
4145 self._strip_non_python_syntax(
4146 None,
4147 None,
4148 None,
4149 None)
4150
Nick Coghlan9c680b02015-04-13 12:54:54 -04004151class TestSignatureDefinitions(unittest.TestCase):
4152 # This test case provides a home for checking that particular APIs
4153 # have signatures available for introspection
4154
4155 @cpython_only
4156 @unittest.skipIf(MISSING_C_DOCSTRINGS,
4157 "Signature information for builtins requires docstrings")
4158 def test_builtins_have_signatures(self):
4159 # This checks all builtin callables in CPython have signatures
4160 # A few have signatures Signature can't yet handle, so we skip those
4161 # since they will have to wait until PEP 457 adds the required
4162 # introspection support to the inspect module
4163 # Some others also haven't been converted yet for various other
4164 # reasons, so we also skip those for the time being, but design
4165 # the test to fail in order to indicate when it needs to be
4166 # updated.
4167 no_signature = set()
4168 # These need PEP 457 groups
4169 needs_groups = {"range", "slice", "dir", "getattr",
4170 "next", "iter", "vars"}
4171 no_signature |= needs_groups
Joshua Bronsonf0a6fde2021-03-23 18:47:21 -04004172 # These have unrepresentable parameter default values of NULL
4173 needs_null = {"anext"}
4174 no_signature |= needs_null
Nick Coghlan9c680b02015-04-13 12:54:54 -04004175 # These need PEP 457 groups or a signature change to accept None
4176 needs_semantic_update = {"round"}
4177 no_signature |= needs_semantic_update
4178 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04004179 needs_varargs = {"breakpoint", "min", "max", "print",
4180 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04004181 no_signature |= needs_varargs
4182 # These simply weren't covered in the initial AC conversion
4183 # for builtin callables
4184 not_converted_yet = {"open", "__import__"}
4185 no_signature |= not_converted_yet
4186 # These builtin types are expected to provide introspection info
4187 types_with_signatures = set()
4188 # Check the signatures we expect to be there
4189 ns = vars(builtins)
4190 for name, obj in sorted(ns.items()):
4191 if not callable(obj):
4192 continue
4193 # The builtin types haven't been converted to AC yet
4194 if isinstance(obj, type) and (name not in types_with_signatures):
4195 # Note that this also skips all the exception types
4196 no_signature.add(name)
4197 if (name in no_signature):
4198 # Not yet converted
4199 continue
4200 with self.subTest(builtin=name):
4201 self.assertIsNotNone(inspect.signature(obj))
4202 # Check callables that haven't been converted don't claim a signature
4203 # This ensures this test will start failing as more signatures are
4204 # added, so the affected items can be moved into the scope of the
4205 # regression test above
4206 for name in no_signature:
4207 with self.subTest(builtin=name):
4208 self.assertIsNone(obj.__text_signature__)
4209
Serhiy Storchakad53cf992019-05-06 22:40:27 +03004210 def test_python_function_override_signature(self):
4211 def func(*args, **kwargs):
4212 pass
4213 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
4214 sig = inspect.signature(func)
4215 self.assertIsNotNone(sig)
4216 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
4217 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
4218 sig = inspect.signature(func)
4219 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
4220
Yury Selivanovd82eddc2014-01-29 11:24:39 -05004221
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01004222class NTimesUnwrappable:
4223 def __init__(self, n):
4224 self.n = n
4225 self._next = None
4226
4227 @property
4228 def __wrapped__(self):
4229 if self.n <= 0:
4230 raise Exception("Unwrapped too many times")
4231 if self._next is None:
4232 self._next = NTimesUnwrappable(self.n - 1)
4233 return self._next
4234
Nick Coghlane8c45d62013-07-28 20:00:01 +10004235class TestUnwrap(unittest.TestCase):
4236
4237 def test_unwrap_one(self):
4238 def func(a, b):
4239 return a + b
4240 wrapper = functools.lru_cache(maxsize=20)(func)
4241 self.assertIs(inspect.unwrap(wrapper), func)
4242
4243 def test_unwrap_several(self):
4244 def func(a, b):
4245 return a + b
4246 wrapper = func
4247 for __ in range(10):
4248 @functools.wraps(wrapper)
4249 def wrapper():
4250 pass
4251 self.assertIsNot(wrapper.__wrapped__, func)
4252 self.assertIs(inspect.unwrap(wrapper), func)
4253
4254 def test_stop(self):
4255 def func1(a, b):
4256 return a + b
4257 @functools.wraps(func1)
4258 def func2():
4259 pass
4260 @functools.wraps(func2)
4261 def wrapper():
4262 pass
4263 func2.stop_here = 1
4264 unwrapped = inspect.unwrap(wrapper,
4265 stop=(lambda f: hasattr(f, "stop_here")))
4266 self.assertIs(unwrapped, func2)
4267
4268 def test_cycle(self):
4269 def func1(): pass
4270 func1.__wrapped__ = func1
4271 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4272 inspect.unwrap(func1)
4273
4274 def func2(): pass
4275 func2.__wrapped__ = func1
4276 func1.__wrapped__ = func2
4277 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4278 inspect.unwrap(func1)
4279 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4280 inspect.unwrap(func2)
4281
4282 def test_unhashable(self):
4283 def func(): pass
4284 func.__wrapped__ = None
4285 class C:
4286 __hash__ = None
4287 __wrapped__ = func
4288 self.assertIsNone(inspect.unwrap(C()))
4289
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01004290 def test_recursion_limit(self):
4291 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
4292 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
4293 inspect.unwrap(obj)
4294
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004295class TestMain(unittest.TestCase):
4296 def test_only_source(self):
4297 module = importlib.import_module('unittest')
4298 rc, out, err = assert_python_ok('-m', 'inspect',
4299 'unittest')
4300 lines = out.decode().splitlines()
4301 # ignore the final newline
4302 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
4303 self.assertEqual(err, b'')
4304
Yury Selivanov42407ab2014-06-23 10:23:50 -07004305 def test_custom_getattr(self):
4306 def foo():
4307 pass
4308 foo.__signature__ = 42
4309 with self.assertRaises(TypeError):
4310 inspect.signature(foo)
4311
Brett Cannon634a8fc2013-10-02 10:25:42 -04004312 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04004313 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004314 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004315 rc, out, err = assert_python_ok('-m', 'inspect',
4316 'concurrent.futures:ThreadPoolExecutor')
4317 lines = out.decode().splitlines()
4318 # ignore the final newline
4319 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04004320 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004321 self.assertEqual(err, b'')
4322
4323 def test_builtins(self):
4324 module = importlib.import_module('unittest')
4325 _, out, err = assert_python_failure('-m', 'inspect',
4326 'sys')
4327 lines = err.decode().splitlines()
4328 self.assertEqual(lines, ["Can't get info for builtin modules."])
4329
4330 def test_details(self):
4331 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01004332 args = support.optim_args_from_interpreter_flags()
4333 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004334 'unittest', '--details')
4335 output = out.decode()
4336 # Just a quick sanity check on the output
4337 self.assertIn(module.__name__, output)
4338 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01004339 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004340 self.assertEqual(err, b'')
4341
4342
Yury Selivanovef1e7502014-12-08 16:05:34 -05004343class TestReload(unittest.TestCase):
4344
4345 src_before = textwrap.dedent("""\
4346def foo():
4347 print("Bla")
4348 """)
4349
4350 src_after = textwrap.dedent("""\
4351def foo():
4352 print("Oh no!")
4353 """)
4354
4355 def assertInspectEqual(self, path, source):
4356 inspected_src = inspect.getsource(source)
Inada Naokifb786922021-04-06 11:18:41 +09004357 with open(path, encoding='utf-8') as src:
Yury Selivanovef1e7502014-12-08 16:05:34 -05004358 self.assertEqual(
4359 src.read().splitlines(True),
4360 inspected_src.splitlines(True)
4361 )
4362
4363 def test_getsource_reload(self):
4364 # see issue 1218234
4365 with _ready_to_import('reload_bug', self.src_before) as (name, path):
4366 module = importlib.import_module(name)
4367 self.assertInspectEqual(path, module)
Inada Naokifb786922021-04-06 11:18:41 +09004368 with open(path, 'w', encoding='utf-8') as src:
Yury Selivanovef1e7502014-12-08 16:05:34 -05004369 src.write(self.src_after)
4370 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004371
Nick Coghlane8c45d62013-07-28 20:00:01 +10004372
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004373if __name__ == "__main__":
Serhiy Storchakabedce352021-09-19 22:36:03 +03004374 unittest.main()