blob: 88eaabe6765ab2b41ea1df98edca1ffa6cf535a3 [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 re
14import shutil
15import sys
16import types
Yury Selivanovef1e7502014-12-08 16:05:34 -050017import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080018import unicodedata
19import unittest
Yury Selivanova773de02014-02-21 18:30:53 -050020import unittest.mock
Yury Selivanov75445082015-05-11 22:57:16 -040021import warnings
Larry Hastings5c661892014-01-24 06:17:25 -080022
Brett Cannon634a8fc2013-10-02 10:25:42 -040023try:
24 from concurrent.futures import ThreadPoolExecutor
25except ImportError:
26 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000027
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020028from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Nick Coghlanf9e227e2014-08-17 14:01:19 +100029from test.support import MISSING_C_DOCSTRINGS, cpython_only
Berker Peksagce643912015-05-06 06:33:17 +030030from test.support.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000031from test import inspect_fodder as mod
32from test import inspect_fodder2 as mod2
Victor Stinner9def2842016-01-18 12:15:08 +010033from test import support
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000034
Yury Selivanovef1e7502014-12-08 16:05:34 -050035from test.test_import import _ready_to_import
36
R. David Murray74b89242009-05-13 17:33:03 +000037
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000038# Functions tested in this suite:
39# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000040# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
41# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
Berker Peksagfa3922c2015-07-31 04:11:29 +030042# getclasstree, getargvalues, formatargspec, formatargvalues,
Christian Heimes7131fd92008-02-19 14:21:46 +000043# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000044
Nick Coghlanf088e5e2008-12-14 11:50:48 +000045# NOTE: There are some additional tests relating to interaction with
46# zipimport in the test_zipimport_support test module.
47
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000048modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000049if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000050 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000051
Christian Heimesa3538eb2007-11-06 11:44:48 +000052# Normalize file names: on Windows, the case of file names of compiled
53# modules depends on the path used to start the python executable.
54modfile = normcase(modfile)
55
56def revise(filename, *args):
57 return (normcase(filename),) + args
58
Georg Brandl1a3284e2007-12-02 09:40:06 +000059import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000060
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000061git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000062
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000063class IsTestBase(unittest.TestCase):
64 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
65 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000066 inspect.ismodule, inspect.istraceback,
Yury Selivanov75445082015-05-11 22:57:16 -040067 inspect.isgenerator, inspect.isgeneratorfunction,
Yury Selivanoveb636452016-09-08 22:01:51 -070068 inspect.iscoroutine, inspect.iscoroutinefunction,
69 inspect.isasyncgen, inspect.isasyncgenfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000070
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000071 def istest(self, predicate, exp):
72 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000073 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000074
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000075 for other in self.predicates - set([predicate]):
Yury Selivanov75445082015-05-11 22:57:16 -040076 if (predicate == inspect.isgeneratorfunction or \
Yury Selivanoveb636452016-09-08 22:01:51 -070077 predicate == inspect.isasyncgenfunction or \
Yury Selivanov75445082015-05-11 22:57:16 -040078 predicate == inspect.iscoroutinefunction) and \
Christian Heimes7131fd92008-02-19 14:21:46 +000079 other == inspect.isfunction:
80 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000081 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000082
Christian Heimes7131fd92008-02-19 14:21:46 +000083def generator_function_example(self):
84 for i in range(2):
85 yield i
86
Yury Selivanoveb636452016-09-08 22:01:51 -070087async def async_generator_function_example(self):
88 async for i in range(2):
89 yield i
90
Yury Selivanov75445082015-05-11 22:57:16 -040091async def coroutine_function_example(self):
92 return 'spam'
93
94@types.coroutine
95def gen_coroutine_function_example(self):
96 yield
97 return 'spam'
98
Serhiy Storchaka3018cc42015-07-18 23:19:05 +030099class EqualsToAll:
100 def __eq__(self, other):
101 return True
Yury Selivanova5d63dd2014-03-27 11:31:43 -0400102
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000103class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +0000104
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000105 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200106 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000107 self.istest(inspect.isbuiltin, 'sys.exit')
108 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +0000109 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200110 try:
111 1/0
112 except:
113 tb = sys.exc_info()[2]
114 self.istest(inspect.isframe, 'tb.tb_frame')
115 self.istest(inspect.istraceback, 'tb')
116 if hasattr(types, 'GetSetDescriptorType'):
117 self.istest(inspect.isgetsetdescriptor,
118 'type(tb.tb_frame).f_locals')
119 else:
120 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
121 finally:
122 # Clear traceback and all the frames and local variables hanging to it.
123 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000124 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000125 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000126 self.istest(inspect.ismethod, 'git.argue')
127 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000128 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000129 self.istest(inspect.isgenerator, '(x for x in range(2))')
130 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanoveb636452016-09-08 22:01:51 -0700131 self.istest(inspect.isasyncgen,
132 'async_generator_function_example(1)')
133 self.istest(inspect.isasyncgenfunction,
134 'async_generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400135
136 with warnings.catch_warnings():
137 warnings.simplefilter("ignore")
138 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
139 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
140
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000141 if hasattr(types, 'MemberDescriptorType'):
142 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
143 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000144 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000145
Yury Selivanov75445082015-05-11 22:57:16 -0400146 def test_iscoroutine(self):
147 gen_coro = gen_coroutine_function_example(1)
148 coro = coroutine_function_example(1)
149
Yury Selivanov5376ba92015-06-22 12:19:30 -0400150 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400151 inspect.iscoroutinefunction(gen_coroutine_function_example))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400152 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400153
154 self.assertTrue(
155 inspect.isgeneratorfunction(gen_coroutine_function_example))
156 self.assertTrue(inspect.isgenerator(gen_coro))
157
158 self.assertTrue(
159 inspect.iscoroutinefunction(coroutine_function_example))
160 self.assertTrue(inspect.iscoroutine(coro))
161
162 self.assertFalse(
163 inspect.isgeneratorfunction(coroutine_function_example))
164 self.assertFalse(inspect.isgenerator(coro))
165
166 coro.close(); gen_coro.close() # silence warnings
167
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400168 def test_isawaitable(self):
169 def gen(): yield
170 self.assertFalse(inspect.isawaitable(gen()))
171
172 coro = coroutine_function_example(1)
173 gen_coro = gen_coroutine_function_example(1)
174
175 self.assertTrue(inspect.isawaitable(coro))
176 self.assertTrue(inspect.isawaitable(gen_coro))
177
178 class Future:
179 def __await__():
180 pass
181 self.assertTrue(inspect.isawaitable(Future()))
182 self.assertFalse(inspect.isawaitable(Future))
183
184 class NotFuture: pass
185 not_fut = NotFuture()
186 not_fut.__await__ = lambda: None
187 self.assertFalse(inspect.isawaitable(not_fut))
188
189 coro.close(); gen_coro.close() # silence warnings
190
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000191 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000192 self.assertTrue(inspect.isroutine(mod.spam))
193 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000194
Benjamin Petersonc4656002009-01-17 22:41:18 +0000195 def test_isclass(self):
196 self.istest(inspect.isclass, 'mod.StupidGit')
197 self.assertTrue(inspect.isclass(list))
198
199 class CustomGetattr(object):
200 def __getattr__(self, attr):
201 return None
202 self.assertFalse(inspect.isclass(CustomGetattr()))
203
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000204 def test_get_slot_members(self):
205 class C(object):
206 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000207 x = C()
208 x.a = 42
209 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000210 self.assertIn('a', members)
211 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000212
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000213 def test_isabstract(self):
214 from abc import ABCMeta, abstractmethod
215
216 class AbstractClassExample(metaclass=ABCMeta):
217
218 @abstractmethod
219 def foo(self):
220 pass
221
222 class ClassExample(AbstractClassExample):
223 def foo(self):
224 pass
225
226 a = ClassExample()
227
228 # Test general behaviour.
229 self.assertTrue(inspect.isabstract(AbstractClassExample))
230 self.assertFalse(inspect.isabstract(ClassExample))
231 self.assertFalse(inspect.isabstract(a))
232 self.assertFalse(inspect.isabstract(int))
233 self.assertFalse(inspect.isabstract(5))
234
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000235
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000236class TestInterpreterStack(IsTestBase):
237 def __init__(self, *args, **kwargs):
238 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000239
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000240 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000241
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000242 def test_abuse_done(self):
243 self.istest(inspect.istraceback, 'git.ex[2]')
244 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000245
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000246 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000247 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000248 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000249 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000250 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000251 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000252 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000253 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000254 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000255 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400256 # Test named tuple fields
257 record = mod.st[0]
258 self.assertIs(record.frame, mod.fr)
259 self.assertEqual(record.lineno, 16)
260 self.assertEqual(record.filename, mod.__file__)
261 self.assertEqual(record.function, 'eggs')
262 self.assertIn('inspect.stack()', record.code_context[0])
263 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000264
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000265 def test_trace(self):
266 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000267 self.assertEqual(revise(*git.tr[0][1:]),
268 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
269 self.assertEqual(revise(*git.tr[1][1:]),
270 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
271 self.assertEqual(revise(*git.tr[2][1:]),
272 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000273
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000274 def test_frame(self):
275 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
276 self.assertEqual(args, ['x', 'y'])
277 self.assertEqual(varargs, None)
278 self.assertEqual(varkw, None)
279 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
280 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
281 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000282
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000283 def test_previous_frame(self):
284 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000285 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000286 self.assertEqual(varargs, 'g')
287 self.assertEqual(varkw, 'h')
288 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000289 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000290
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000291class GetSourceBase(unittest.TestCase):
292 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000293 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000294
Yury Selivanov6738b112015-05-16 10:10:21 -0400295 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000296 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000297 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000298
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000299 def sourcerange(self, top, bottom):
300 lines = self.source.split("\n")
301 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000302
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000303 def assertSourceEqual(self, obj, top, bottom):
304 self.assertEqual(inspect.getsource(obj),
305 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000306
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000307class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000308 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000309
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000310 def test_getclasses(self):
311 classes = inspect.getmembers(mod, inspect.isclass)
312 self.assertEqual(classes,
313 [('FesteringGob', mod.FesteringGob),
314 ('MalodorousPervert', mod.MalodorousPervert),
315 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300316 ('StupidGit', mod.StupidGit),
317 ('Tit', mod.MalodorousPervert),
318 ])
319 tree = inspect.getclasstree([cls[1] for cls in classes])
320 self.assertEqual(tree,
321 [(object, ()),
322 [(mod.ParrotDroppings, (object,)),
323 [(mod.FesteringGob, (mod.MalodorousPervert,
324 mod.ParrotDroppings))
325 ],
326 (mod.StupidGit, (object,)),
327 [(mod.MalodorousPervert, (mod.StupidGit,)),
328 [(mod.FesteringGob, (mod.MalodorousPervert,
329 mod.ParrotDroppings))
330 ]
331 ]
332 ]
333 ])
334 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000335 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000336 [(object, ()),
337 [(mod.ParrotDroppings, (object,)),
338 (mod.StupidGit, (object,)),
339 [(mod.MalodorousPervert, (mod.StupidGit,)),
340 [(mod.FesteringGob, (mod.MalodorousPervert,
341 mod.ParrotDroppings))
342 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000343 ]
344 ]
345 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000346
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000347 def test_getfunctions(self):
348 functions = inspect.getmembers(mod, inspect.isfunction)
349 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300350 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000351 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000352
R. David Murray378c0cf2010-02-24 01:46:21 +0000353 @unittest.skipIf(sys.flags.optimize >= 2,
354 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000355 def test_getdoc(self):
356 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
357 self.assertEqual(inspect.getdoc(mod.StupidGit),
358 'A longer,\n\nindented\n\ndocstring.')
359 self.assertEqual(inspect.getdoc(git.abuse),
360 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000361
Serhiy Storchaka5cf2b7252015-04-03 22:38:53 +0300362 @unittest.skipIf(sys.flags.optimize >= 2,
363 "Docstrings are omitted with -O2 and above")
364 def test_getdoc_inherited(self):
365 self.assertEqual(inspect.getdoc(mod.FesteringGob),
366 'A longer,\n\nindented\n\ndocstring.')
367 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
368 'Another\n\ndocstring\n\ncontaining\n\ntabs')
369 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
370 'Another\n\ndocstring\n\ncontaining\n\ntabs')
371 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
372 'The automatic gainsaying.')
373
374 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
375 def test_finddoc(self):
376 finddoc = inspect._finddoc
377 self.assertEqual(finddoc(int), int.__doc__)
378 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
379 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
380 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
381 self.assertEqual(finddoc(int.real), int.real.__doc__)
382
Georg Brandl0c77a822008-06-10 16:37:50 +0000383 def test_cleandoc(self):
384 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
385 'An\nindented\ndocstring.')
386
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000387 def test_getcomments(self):
388 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
389 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000390
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000391 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000392 # Check actual module
393 self.assertEqual(inspect.getmodule(mod), mod)
394 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000395 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000396 # Check a method (no __module__ attribute, falls back to filename)
397 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
398 # Do it again (check the caching isn't broken)
399 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
400 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000401 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000402 # Check filename override
403 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000404
Berker Peksagff0e3b72017-01-02 06:57:43 +0300405 def test_getframeinfo_get_first_line(self):
406 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
407 self.assertEqual(frame_info.code_context[0], "# line 1\n")
408 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
409
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000410 def test_getsource(self):
411 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200412 self.assertSourceEqual(mod.StupidGit, 21, 51)
413 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000414
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000415 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000416 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
417 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000418 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100419 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000420 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000421 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200422 try:
423 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
424 finally:
425 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000426
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000427 def test_getfile(self):
428 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000429
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500430 def test_getfile_class_without_module(self):
431 class CM(type):
432 @property
433 def __module__(cls):
434 raise AttributeError
435 class C(metaclass=CM):
436 pass
437 with self.assertRaises(TypeError):
438 inspect.getfile(C)
439
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000440 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000441 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000442 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000443 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000444 m.__file__ = "<string>" # hopefully not a real filename...
445 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000446 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000447 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000448 del sys.modules[name]
449 inspect.getmodule(compile('a=10','','single'))
450
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500451 def test_proceed_with_fake_filename(self):
452 '''doctest monkeypatches linecache to enable inspection'''
453 fn, source = '<test>', 'def x(): pass\n'
454 getlines = linecache.getlines
455 def monkey(filename, module_globals=None):
456 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300457 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500458 else:
459 return getlines(filename, module_globals)
460 linecache.getlines = monkey
461 try:
462 ns = {}
463 exec(compile(source, fn, 'single'), ns)
464 inspect.getsource(ns["x"])
465 finally:
466 linecache.getlines = getlines
467
Antoine Pitroua8723a02015-04-15 00:41:29 +0200468 def test_getsource_on_code_object(self):
469 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
470
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000471class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000472 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000473
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000474 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000475 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000476
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000477 def test_replacing_decorator(self):
478 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000479
Yury Selivanov081bbf62014-09-26 17:34:54 -0400480 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200481 self.assertSourceEqual(mod2.real, 130, 132)
482
483 def test_decorator_with_lambda(self):
484 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400485
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000486class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000487 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000488 def test_oneline_lambda(self):
489 # Test inspect.getsource with a one-line lambda function.
490 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000491
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000492 def test_threeline_lambda(self):
493 # Test inspect.getsource with a three-line lambda function,
494 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000495 self.assertSourceEqual(mod2.tll, 28, 30)
496
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000497 def test_twoline_indented_lambda(self):
498 # Test inspect.getsource with a two-line lambda function,
499 # where the second line _is_ indented.
500 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000501
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000502 def test_onelinefunc(self):
503 # Test inspect.getsource with a regular one-line function.
504 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000505
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000506 def test_manyargs(self):
507 # Test inspect.getsource with a regular function where
508 # the arguments are on two lines and _not_ indented and
509 # the body on the second line with the last arguments.
510 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000511
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000512 def test_twolinefunc(self):
513 # Test inspect.getsource with a regular function where
514 # the body is on two lines, following the argument list and
515 # continued on the next line by a \\.
516 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000517
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000518 def test_lambda_in_list(self):
519 # Test inspect.getsource with a one-line lambda function
520 # defined in a list, indented.
521 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000522
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000523 def test_anonymous(self):
524 # Test inspect.getsource with a lambda function defined
525 # as argument to another function.
526 self.assertSourceEqual(mod2.anonymous, 55, 55)
527
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000528class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000529 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000530
531 def test_with_comment(self):
532 self.assertSourceEqual(mod2.with_comment, 58, 59)
533
534 def test_multiline_sig(self):
535 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
536
Armin Rigodd5c0232005-09-25 11:45:45 +0000537 def test_nested_class(self):
538 self.assertSourceEqual(mod2.func69().func71, 71, 72)
539
540 def test_one_liner_followed_by_non_name(self):
541 self.assertSourceEqual(mod2.func77, 77, 77)
542
543 def test_one_liner_dedent_non_name(self):
544 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
545
546 def test_with_comment_instead_of_docstring(self):
547 self.assertSourceEqual(mod2.func88, 88, 90)
548
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000549 def test_method_in_dynamic_class(self):
550 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
551
R David Murray32562d72014-10-03 11:15:38 -0400552 # This should not skip for CPython, but might on a repackaged python where
553 # unicodedata is not an external module, or on pypy.
554 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
555 unicodedata.__file__.endswith('.py'),
556 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000557 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200558 self.assertRaises(OSError, inspect.getsource, unicodedata)
559 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000560
R. David Murraya1b37402010-06-17 02:04:29 +0000561 def test_findsource_code_in_linecache(self):
562 lines = ["x=1"]
563 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200564 self.assertRaises(OSError, inspect.findsource, co)
565 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000566 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200567 try:
568 self.assertEqual(inspect.findsource(co), (lines,0))
569 self.assertEqual(inspect.getsource(co), lines[0])
570 finally:
571 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000572
Ezio Melotti1b145922013-03-30 05:17:24 +0200573 def test_findsource_without_filename(self):
574 for fname in ['', '<string>']:
575 co = compile('x=1', fname, "exec")
576 self.assertRaises(IOError, inspect.findsource, co)
577 self.assertRaises(IOError, inspect.getsource, co)
578
Antoine Pitroua8723a02015-04-15 00:41:29 +0200579 def test_getsource_on_method(self):
580 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
581
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300582 def test_nested_func(self):
583 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
584
585
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000586class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400587 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000588 self.tempdir = TESTFN + '_dir'
589 os.mkdir(self.tempdir)
590 with open(os.path.join(self.tempdir,
591 'inspect_fodder3%spy' % os.extsep), 'w') as f:
592 f.write("class X:\n pass # No EOL")
593 with DirsOnSysPath(self.tempdir):
594 import inspect_fodder3 as mod3
595 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400596 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000597
598 def tearDown(self):
599 shutil.rmtree(self.tempdir)
600
601 def test_class(self):
602 self.assertSourceEqual(self.fodderModule.X, 1, 2)
603
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100604
605class _BrokenDataDescriptor(object):
606 """
607 A broken data descriptor. See bug #1785.
608 """
609 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700610 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100611
612 def __set__(*args):
613 raise RuntimeError
614
615 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700616 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100617
618
619class _BrokenMethodDescriptor(object):
620 """
621 A broken method descriptor. See bug #1785.
622 """
623 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700624 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100625
626 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700627 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100628
629
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000630# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000631def attrs_wo_objs(cls):
632 return [t[:3] for t in inspect.classify_class_attrs(cls)]
633
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100634
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000635class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000636 def test_newstyle_mro(self):
637 # The same w/ new-class MRO.
638 class A(object): pass
639 class B(A): pass
640 class C(A): pass
641 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000642
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000643 expected = (D, B, C, A, object)
644 got = inspect.getmro(D)
645 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000646
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500647 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
648 varkw_e=None, defaults_e=None, formatted=None):
649 with self.assertWarns(DeprecationWarning):
650 args, varargs, varkw, defaults = inspect.getargspec(routine)
651 self.assertEqual(args, args_e)
652 self.assertEqual(varargs, varargs_e)
653 self.assertEqual(varkw, varkw_e)
654 self.assertEqual(defaults, defaults_e)
655 if formatted is not None:
656 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
657 formatted)
658
Christian Heimes3795b532007-11-08 13:48:53 +0000659 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
660 varkw_e=None, defaults_e=None,
661 kwonlyargs_e=[], kwonlydefaults_e=None,
662 ann_e={}, formatted=None):
663 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
664 inspect.getfullargspec(routine)
665 self.assertEqual(args, args_e)
666 self.assertEqual(varargs, varargs_e)
667 self.assertEqual(varkw, varkw_e)
668 self.assertEqual(defaults, defaults_e)
669 self.assertEqual(kwonlyargs, kwonlyargs_e)
670 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
671 self.assertEqual(ann, ann_e)
672 if formatted is not None:
673 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
674 kwonlyargs, kwonlydefaults, ann),
675 formatted)
676
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500677 def test_getargspec(self):
678 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
679
680 self.assertArgSpecEquals(mod.spam,
681 ['a', 'b', 'c', 'd', 'e', 'f'],
682 'g', 'h', (3, 4, 5),
683 '(a, b, c, d=3, e=4, f=5, *g, **h)')
684
685 self.assertRaises(ValueError, self.assertArgSpecEquals,
686 mod2.keyworded, [])
687
688 self.assertRaises(ValueError, self.assertArgSpecEquals,
689 mod2.annotated, [])
690 self.assertRaises(ValueError, self.assertArgSpecEquals,
691 mod2.keyword_only_arg, [])
692
693
Christian Heimes3795b532007-11-08 13:48:53 +0000694 def test_getfullargspec(self):
695 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
696 kwonlyargs_e=['arg2'],
697 kwonlydefaults_e={'arg2':1},
698 formatted='(*arg1, arg2=1)')
699
700 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000701 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000702 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000703 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
704 kwonlyargs_e=['arg'],
705 formatted='(*, arg)')
706
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500707 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500708 # Issue 20684: low level introspection API must ignore __wrapped__
709 @functools.wraps(mod.spam)
710 def ham(x, y):
711 pass
712 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500713 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500714 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
715 self.assertFullArgSpecEquals(functools.partial(ham),
716 ['x', 'y'], formatted='(x, y)')
717 # Other variants
718 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500719 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
720 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500721 class C:
722 @functools.wraps(mod.spam)
723 def ham(self, x, y):
724 pass
725 pham = functools.partialmethod(ham)
726 @functools.wraps(mod.spam)
727 def __call__(self, x, y):
728 pass
729 check_method(C())
730 check_method(C.ham)
731 check_method(C().ham)
732 check_method(C.pham)
733 check_method(C().pham)
734
735 class C_new:
736 @functools.wraps(mod.spam)
737 def __new__(self, x, y):
738 pass
739 check_method(C_new)
740
741 class C_init:
742 @functools.wraps(mod.spam)
743 def __init__(self, x, y):
744 pass
745 check_method(C_init)
746
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500747 def test_getfullargspec_signature_attr(self):
748 def test():
749 pass
750 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
751 test.__signature__ = inspect.Signature(parameters=(spam_param,))
752
753 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
754
Yury Selivanov4cb93912014-01-29 11:54:12 -0500755 def test_getfullargspec_signature_annos(self):
756 def test(a:'spam') -> 'ham': pass
757 spec = inspect.getfullargspec(test)
758 self.assertEqual(test.__annotations__, spec.annotations)
759
760 def test(): pass
761 spec = inspect.getfullargspec(test)
762 self.assertEqual(test.__annotations__, spec.annotations)
763
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500764 @unittest.skipIf(MISSING_C_DOCSTRINGS,
765 "Signature information for builtins requires docstrings")
766 def test_getfullargspec_builtin_methods(self):
767 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
768 args_e=['self', 'obj'], formatted='(self, obj)')
769
770 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
771 args_e=['self', 'obj'], formatted='(self, obj)')
772
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500773 self.assertFullArgSpecEquals(
774 os.stat,
775 args_e=['path'],
776 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
777 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
778 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
779
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200780 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500781 @unittest.skipIf(MISSING_C_DOCSTRINGS,
782 "Signature information for builtins requires docstrings")
783 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200784 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500785 builtin = _testcapi.docstring_with_signature_with_defaults
786 spec = inspect.getfullargspec(builtin)
787 self.assertEqual(spec.defaults[0], 'avocado')
788
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200789 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500790 @unittest.skipIf(MISSING_C_DOCSTRINGS,
791 "Signature information for builtins requires docstrings")
792 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200793 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500794 builtin = _testcapi.docstring_no_signature
795 with self.assertRaises(TypeError):
796 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000797
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500798 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000799 class A(object):
800 def m(self):
801 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500802 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000803
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000804 def test_classify_newstyle(self):
805 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000806
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000807 def s(): pass
808 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000809
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000810 def c(cls): pass
811 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000812
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000813 def getp(self): pass
814 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000815
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000816 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000817
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000818 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000819
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000820 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000821
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100822 dd = _BrokenDataDescriptor()
823 md = _BrokenMethodDescriptor()
824
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000825 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500826
827 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
828 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
829
Benjamin Peterson577473f2010-01-19 00:09:57 +0000830 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
831 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
832 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000833 self.assertIn(('m', 'method', A), attrs,
834 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000835 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
836 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100837 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
838 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000839
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000840 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000841
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000842 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000843
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000844 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000845 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
846 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
847 self.assertIn(('p', 'property', A), attrs, 'missing property')
848 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
849 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
850 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100851 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
852 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000853
854
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000855 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000856
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000857 def m(self): pass
858 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000859
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000860 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000861 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
862 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
863 self.assertIn(('p', 'property', A), attrs, 'missing property')
864 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
865 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
866 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100867 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
868 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000869
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000870 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000871
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000872 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000873
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000874 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000875 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
876 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
877 self.assertIn(('p', 'property', A), attrs, 'missing property')
878 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
879 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
880 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100881 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
882 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
883
884 def test_classify_builtin_types(self):
885 # Simple sanity check that all built-in types can have their
886 # attributes classified.
887 for name in dir(__builtins__):
888 builtin = getattr(__builtins__, name)
889 if isinstance(builtin, type):
890 inspect.classify_class_attrs(builtin)
891
Ethan Furman63c141c2013-10-18 00:27:39 -0700892 def test_classify_DynamicClassAttribute(self):
893 class Meta(type):
894 def __getattr__(self, name):
895 if name == 'ham':
896 return 'spam'
897 return super().__getattr__(name)
898 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700899 @types.DynamicClassAttribute
900 def ham(self):
901 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700902 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
903 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700904 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700905 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
906
Yury Selivanovbf341fb2015-05-21 15:41:57 -0400907 def test_classify_overrides_bool(self):
908 class NoBool(object):
909 def __eq__(self, other):
910 return NoBool()
911
912 def __bool__(self):
913 raise NotImplementedError(
914 "This object does not specify a boolean value")
915
916 class HasNB(object):
917 dd = NoBool()
918
919 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
920 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
921
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700922 def test_classify_metaclass_class_attribute(self):
923 class Meta(type):
924 fish = 'slap'
925 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200926 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700927 class Class(metaclass=Meta):
928 pass
929 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
930 self.assertIn(should_find, inspect.classify_class_attrs(Class))
931
Ethan Furman63c141c2013-10-18 00:27:39 -0700932 def test_classify_VirtualAttribute(self):
933 class Meta(type):
934 def __dir__(cls):
935 return ['__class__', '__module__', '__name__', 'BOOM']
936 def __getattr__(self, name):
937 if name =='BOOM':
938 return 42
939 return super().__getattr(name)
940 class Class(metaclass=Meta):
941 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700942 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700943 self.assertIn(should_find, inspect.classify_class_attrs(Class))
944
945 def test_classify_VirtualAttribute_multi_classes(self):
946 class Meta1(type):
947 def __dir__(cls):
948 return ['__class__', '__module__', '__name__', 'one']
949 def __getattr__(self, name):
950 if name =='one':
951 return 1
952 return super().__getattr__(name)
953 class Meta2(type):
954 def __dir__(cls):
955 return ['__class__', '__module__', '__name__', 'two']
956 def __getattr__(self, name):
957 if name =='two':
958 return 2
959 return super().__getattr__(name)
960 class Meta3(Meta1, Meta2):
961 def __dir__(cls):
962 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
963 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
964 def __getattr__(self, name):
965 if name =='three':
966 return 3
967 return super().__getattr__(name)
968 class Class1(metaclass=Meta1):
969 pass
970 class Class2(Class1, metaclass=Meta3):
971 pass
972
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700973 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
974 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
975 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700976 cca = inspect.classify_class_attrs(Class2)
977 for sf in (should_find1, should_find2, should_find3):
978 self.assertIn(sf, cca)
979
980 def test_classify_class_attrs_with_buggy_dir(self):
981 class M(type):
982 def __dir__(cls):
983 return ['__class__', '__name__', 'missing']
984 class C(metaclass=M):
985 pass
986 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
987 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700988
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100989 def test_getmembers_descriptors(self):
990 class A(object):
991 dd = _BrokenDataDescriptor()
992 md = _BrokenMethodDescriptor()
993
994 def pred_wrapper(pred):
995 # A quick'n'dirty way to discard standard attributes of new-style
996 # classes.
997 class Empty(object):
998 pass
999 def wrapped(x):
1000 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1001 return False
1002 return pred(x)
1003 return wrapped
1004
1005 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1006 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1007
1008 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1009 [('md', A.__dict__['md'])])
1010 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1011 [('dd', A.__dict__['dd'])])
1012
1013 class B(A):
1014 pass
1015
1016 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1017 [('md', A.__dict__['md'])])
1018 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1019 [('dd', A.__dict__['dd'])])
1020
Antoine Pitrou0c603812012-01-18 17:40:18 +01001021 def test_getmembers_method(self):
1022 class B:
1023 def f(self):
1024 pass
1025
1026 self.assertIn(('f', B.f), inspect.getmembers(B))
1027 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1028 b = B()
1029 self.assertIn(('f', b.f), inspect.getmembers(b))
1030 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1031
Ethan Furmane03ea372013-09-25 07:14:41 -07001032 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001033 class M(type):
1034 def __getattr__(cls, name):
1035 if name == 'eggs':
1036 return 'scrambled'
1037 return super().__getattr__(name)
1038 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001039 @types.DynamicClassAttribute
1040 def eggs(self):
1041 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001042 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1043 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1044
1045 def test_getmembers_with_buggy_dir(self):
1046 class M(type):
1047 def __dir__(cls):
1048 return ['__class__', '__name__', 'missing']
1049 class C(metaclass=M):
1050 pass
1051 attrs = [a[0] for a in inspect.getmembers(C)]
1052 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001053
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001054
Nick Coghlan2f92e542012-06-23 19:39:55 +10001055_global_ref = object()
1056class TestGetClosureVars(unittest.TestCase):
1057
1058 def test_name_resolution(self):
1059 # Basic test of the 4 different resolution mechanisms
1060 def f(nonlocal_ref):
1061 def g(local_ref):
1062 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1063 return g
1064 _arg = object()
1065 nonlocal_vars = {"nonlocal_ref": _arg}
1066 global_vars = {"_global_ref": _global_ref}
1067 builtin_vars = {"print": print}
1068 unbound_names = {"unbound_ref"}
1069 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1070 builtin_vars, unbound_names)
1071 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1072
1073 def test_generator_closure(self):
1074 def f(nonlocal_ref):
1075 def g(local_ref):
1076 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1077 yield
1078 return g
1079 _arg = object()
1080 nonlocal_vars = {"nonlocal_ref": _arg}
1081 global_vars = {"_global_ref": _global_ref}
1082 builtin_vars = {"print": print}
1083 unbound_names = {"unbound_ref"}
1084 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1085 builtin_vars, unbound_names)
1086 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1087
1088 def test_method_closure(self):
1089 class C:
1090 def f(self, nonlocal_ref):
1091 def g(local_ref):
1092 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1093 return g
1094 _arg = object()
1095 nonlocal_vars = {"nonlocal_ref": _arg}
1096 global_vars = {"_global_ref": _global_ref}
1097 builtin_vars = {"print": print}
1098 unbound_names = {"unbound_ref"}
1099 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1100 builtin_vars, unbound_names)
1101 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1102
1103 def test_nonlocal_vars(self):
1104 # More complex tests of nonlocal resolution
1105 def _nonlocal_vars(f):
1106 return inspect.getclosurevars(f).nonlocals
1107
1108 def make_adder(x):
1109 def add(y):
1110 return x + y
1111 return add
1112
1113 def curry(func, arg1):
1114 return lambda arg2: func(arg1, arg2)
1115
1116 def less_than(a, b):
1117 return a < b
1118
1119 # The infamous Y combinator.
1120 def Y(le):
1121 def g(f):
1122 return le(lambda x: f(f)(x))
1123 Y.g_ref = g
1124 return g(g)
1125
1126 def check_y_combinator(func):
1127 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1128
1129 inc = make_adder(1)
1130 add_two = make_adder(2)
1131 greater_than_five = curry(less_than, 5)
1132
1133 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1134 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1135 self.assertEqual(_nonlocal_vars(greater_than_five),
1136 {'arg1': 5, 'func': less_than})
1137 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1138 {'x': 3})
1139 Y(check_y_combinator)
1140
1141 def test_getclosurevars_empty(self):
1142 def foo(): pass
1143 _empty = inspect.ClosureVars({}, {}, {}, set())
1144 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1145 self.assertEqual(inspect.getclosurevars(foo), _empty)
1146
1147 def test_getclosurevars_error(self):
1148 class T: pass
1149 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1150 self.assertRaises(TypeError, inspect.getclosurevars, list)
1151 self.assertRaises(TypeError, inspect.getclosurevars, {})
1152
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001153 def _private_globals(self):
1154 code = """def f(): print(path)"""
1155 ns = {}
1156 exec(code, ns)
1157 return ns["f"], ns
1158
1159 def test_builtins_fallback(self):
1160 f, ns = self._private_globals()
1161 ns.pop("__builtins__", None)
1162 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1163 self.assertEqual(inspect.getclosurevars(f), expected)
1164
1165 def test_builtins_as_dict(self):
1166 f, ns = self._private_globals()
1167 ns["__builtins__"] = {"path":1}
1168 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1169 self.assertEqual(inspect.getclosurevars(f), expected)
1170
1171 def test_builtins_as_module(self):
1172 f, ns = self._private_globals()
1173 ns["__builtins__"] = os
1174 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1175 self.assertEqual(inspect.getclosurevars(f), expected)
1176
Nick Coghlan2f92e542012-06-23 19:39:55 +10001177
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001178class TestGetcallargsFunctions(unittest.TestCase):
1179
1180 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1181 locs = dict(locs or {}, func=func)
1182 r1 = eval('func(%s)' % call_params_string, None, locs)
1183 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1184 locs)
1185 self.assertEqual(r1, r2)
1186
1187 def assertEqualException(self, func, call_param_string, locs=None):
1188 locs = dict(locs or {}, func=func)
1189 try:
1190 eval('func(%s)' % call_param_string, None, locs)
1191 except Exception as e:
1192 ex1 = e
1193 else:
1194 self.fail('Exception not raised')
1195 try:
1196 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1197 locs)
1198 except Exception as e:
1199 ex2 = e
1200 else:
1201 self.fail('Exception not raised')
1202 self.assertIs(type(ex1), type(ex2))
1203 self.assertEqual(str(ex1), str(ex2))
1204 del ex1, ex2
1205
1206 def makeCallable(self, signature):
1207 """Create a function that returns its locals()"""
1208 code = "lambda %s: locals()"
1209 return eval(code % signature)
1210
1211 def test_plain(self):
1212 f = self.makeCallable('a, b=1')
1213 self.assertEqualCallArgs(f, '2')
1214 self.assertEqualCallArgs(f, '2, 3')
1215 self.assertEqualCallArgs(f, 'a=2')
1216 self.assertEqualCallArgs(f, 'b=3, a=2')
1217 self.assertEqualCallArgs(f, '2, b=3')
1218 # expand *iterable / **mapping
1219 self.assertEqualCallArgs(f, '*(2,)')
1220 self.assertEqualCallArgs(f, '*[2]')
1221 self.assertEqualCallArgs(f, '*(2, 3)')
1222 self.assertEqualCallArgs(f, '*[2, 3]')
1223 self.assertEqualCallArgs(f, '**{"a":2}')
1224 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1225 self.assertEqualCallArgs(f, '2, **{"b":3}')
1226 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1227 # expand UserList / UserDict
1228 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1229 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1230 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1231 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1232 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1233
1234 def test_varargs(self):
1235 f = self.makeCallable('a, b=1, *c')
1236 self.assertEqualCallArgs(f, '2')
1237 self.assertEqualCallArgs(f, '2, 3')
1238 self.assertEqualCallArgs(f, '2, 3, 4')
1239 self.assertEqualCallArgs(f, '*(2,3,4)')
1240 self.assertEqualCallArgs(f, '2, *[3,4]')
1241 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1242
1243 def test_varkw(self):
1244 f = self.makeCallable('a, b=1, **c')
1245 self.assertEqualCallArgs(f, 'a=2')
1246 self.assertEqualCallArgs(f, '2, b=3, c=4')
1247 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1248 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1249 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1250 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1251 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1252 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1253 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1254
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001255 def test_varkw_only(self):
1256 # issue11256:
1257 f = self.makeCallable('**c')
1258 self.assertEqualCallArgs(f, '')
1259 self.assertEqualCallArgs(f, 'a=1')
1260 self.assertEqualCallArgs(f, 'a=1, b=2')
1261 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1262 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1263 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1264
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001265 def test_keyword_only(self):
1266 f = self.makeCallable('a=3, *, c, d=2')
1267 self.assertEqualCallArgs(f, 'c=3')
1268 self.assertEqualCallArgs(f, 'c=3, a=3')
1269 self.assertEqualCallArgs(f, 'a=2, c=4')
1270 self.assertEqualCallArgs(f, '4, c=4')
1271 self.assertEqualException(f, '')
1272 self.assertEqualException(f, '3')
1273 self.assertEqualException(f, 'a=3')
1274 self.assertEqualException(f, 'd=4')
1275
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001276 f = self.makeCallable('*, c, d=2')
1277 self.assertEqualCallArgs(f, 'c=3')
1278 self.assertEqualCallArgs(f, 'c=3, d=4')
1279 self.assertEqualCallArgs(f, 'd=4, c=3')
1280
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001281 def test_multiple_features(self):
1282 f = self.makeCallable('a, b=2, *f, **g')
1283 self.assertEqualCallArgs(f, '2, 3, 7')
1284 self.assertEqualCallArgs(f, '2, 3, x=8')
1285 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1286 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1287 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1288 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1289 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1290 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1291 '(4,[5,6])]), **collections.UserDict('
1292 'y=9, z=10)')
1293
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001294 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1295 self.assertEqualCallArgs(f, '2, 3, x=8')
1296 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1297 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1298 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1299 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1300 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1301 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1302 '(4,[5,6])]), q=0, **collections.UserDict('
1303 'y=9, z=10)')
1304
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001305 def test_errors(self):
1306 f0 = self.makeCallable('')
1307 f1 = self.makeCallable('a, b')
1308 f2 = self.makeCallable('a, b=1')
1309 # f0 takes no arguments
1310 self.assertEqualException(f0, '1')
1311 self.assertEqualException(f0, 'x=1')
1312 self.assertEqualException(f0, '1,x=1')
1313 # f1 takes exactly 2 arguments
1314 self.assertEqualException(f1, '')
1315 self.assertEqualException(f1, '1')
1316 self.assertEqualException(f1, 'a=2')
1317 self.assertEqualException(f1, 'b=3')
1318 # f2 takes at least 1 argument
1319 self.assertEqualException(f2, '')
1320 self.assertEqualException(f2, 'b=3')
1321 for f in f1, f2:
1322 # f1/f2 takes exactly/at most 2 arguments
1323 self.assertEqualException(f, '2, 3, 4')
1324 self.assertEqualException(f, '1, 2, 3, a=1')
1325 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001326 # XXX: success of this one depends on dict order
1327 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001328 # f got an unexpected keyword argument
1329 self.assertEqualException(f, 'c=2')
1330 self.assertEqualException(f, '2, c=3')
1331 self.assertEqualException(f, '2, 3, c=4')
1332 self.assertEqualException(f, '2, c=4, b=3')
1333 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1334 # f got multiple values for keyword argument
1335 self.assertEqualException(f, '1, a=2')
1336 self.assertEqualException(f, '1, **{"a":2}')
1337 self.assertEqualException(f, '1, 2, b=3')
1338 # XXX: Python inconsistency
1339 # - for functions and bound methods: unexpected keyword 'c'
1340 # - for unbound methods: multiple values for keyword 'a'
1341 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001342 # issue11256:
1343 f3 = self.makeCallable('**c')
1344 self.assertEqualException(f3, '1, 2')
1345 self.assertEqualException(f3, '1, 2, a=1, b=2')
1346 f4 = self.makeCallable('*, a, b=0')
1347 self.assertEqualException(f3, '1, 2')
1348 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001349
Yury Selivanov875df202014-03-27 18:23:03 -04001350 # issue #20816: getcallargs() fails to iterate over non-existent
1351 # kwonlydefaults and raises a wrong TypeError
1352 def f5(*, a): pass
1353 with self.assertRaisesRegex(TypeError,
1354 'missing 1 required keyword-only'):
1355 inspect.getcallargs(f5)
1356
1357
Yury Selivanovdccfa132014-03-27 18:42:52 -04001358 # issue20817:
1359 def f6(a, b, c):
1360 pass
1361 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1362 inspect.getcallargs(f6)
1363
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001364class TestGetcallargsMethods(TestGetcallargsFunctions):
1365
1366 def setUp(self):
1367 class Foo(object):
1368 pass
1369 self.cls = Foo
1370 self.inst = Foo()
1371
1372 def makeCallable(self, signature):
1373 assert 'self' not in signature
1374 mk = super(TestGetcallargsMethods, self).makeCallable
1375 self.cls.method = mk('self, ' + signature)
1376 return self.inst.method
1377
1378class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1379
1380 def makeCallable(self, signature):
1381 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1382 return self.cls.method
1383
1384 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1385 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1386 *self._getAssertEqualParams(func, call_params_string, locs))
1387
1388 def assertEqualException(self, func, call_params_string, locs=None):
1389 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1390 *self._getAssertEqualParams(func, call_params_string, locs))
1391
1392 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1393 assert 'inst' not in call_params_string
1394 locs = dict(locs or {}, inst=self.inst)
1395 return (func, 'inst,' + call_params_string, locs)
1396
Michael Foord95fc51d2010-11-20 15:07:30 +00001397
1398class TestGetattrStatic(unittest.TestCase):
1399
1400 def test_basic(self):
1401 class Thing(object):
1402 x = object()
1403
1404 thing = Thing()
1405 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1406 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1407 with self.assertRaises(AttributeError):
1408 inspect.getattr_static(thing, 'y')
1409
1410 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1411
1412 def test_inherited(self):
1413 class Thing(object):
1414 x = object()
1415 class OtherThing(Thing):
1416 pass
1417
1418 something = OtherThing()
1419 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1420
1421 def test_instance_attr(self):
1422 class Thing(object):
1423 x = 2
1424 def __init__(self, x):
1425 self.x = x
1426 thing = Thing(3)
1427 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1428 del thing.x
1429 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1430
1431 def test_property(self):
1432 class Thing(object):
1433 @property
1434 def x(self):
1435 raise AttributeError("I'm pretending not to exist")
1436 thing = Thing()
1437 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1438
Ezio Melotti75cbd732011-04-28 00:59:29 +03001439 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001440 class descriptor(object):
1441 def __get__(*_):
1442 raise AttributeError("I'm pretending not to exist")
1443 desc = descriptor()
1444 class Thing(object):
1445 x = desc
1446 thing = Thing()
1447 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1448
1449 def test_classAttribute(self):
1450 class Thing(object):
1451 x = object()
1452
1453 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1454
Ethan Furmane03ea372013-09-25 07:14:41 -07001455 def test_classVirtualAttribute(self):
1456 class Thing(object):
1457 @types.DynamicClassAttribute
1458 def x(self):
1459 return self._x
1460 _x = object()
1461
1462 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1463
Michael Foord95fc51d2010-11-20 15:07:30 +00001464 def test_inherited_classattribute(self):
1465 class Thing(object):
1466 x = object()
1467 class OtherThing(Thing):
1468 pass
1469
1470 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1471
1472 def test_slots(self):
1473 class Thing(object):
1474 y = 'bar'
1475 __slots__ = ['x']
1476 def __init__(self):
1477 self.x = 'foo'
1478 thing = Thing()
1479 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1480 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1481
1482 del thing.x
1483 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1484
1485 def test_metaclass(self):
1486 class meta(type):
1487 attr = 'foo'
1488 class Thing(object, metaclass=meta):
1489 pass
1490 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1491
1492 class sub(meta):
1493 pass
1494 class OtherThing(object, metaclass=sub):
1495 x = 3
1496 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1497
1498 class OtherOtherThing(OtherThing):
1499 pass
1500 # this test is odd, but it was added as it exposed a bug
1501 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1502
1503 def test_no_dict_no_slots(self):
1504 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1505 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1506
1507 def test_no_dict_no_slots_instance_member(self):
1508 # returns descriptor
1509 with open(__file__) as handle:
1510 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1511
1512 def test_inherited_slots(self):
1513 # returns descriptor
1514 class Thing(object):
1515 __slots__ = ['x']
1516 def __init__(self):
1517 self.x = 'foo'
1518
1519 class OtherThing(Thing):
1520 pass
1521 # it would be nice if this worked...
1522 # we get the descriptor instead of the instance attribute
1523 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1524
1525 def test_descriptor(self):
1526 class descriptor(object):
1527 def __get__(self, instance, owner):
1528 return 3
1529 class Foo(object):
1530 d = descriptor()
1531
1532 foo = Foo()
1533
1534 # for a non data descriptor we return the instance attribute
1535 foo.__dict__['d'] = 1
1536 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1537
1538 # if the descriptor is a data-desciptor we should return the
1539 # descriptor
1540 descriptor.__set__ = lambda s, i, v: None
1541 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1542
1543
1544 def test_metaclass_with_descriptor(self):
1545 class descriptor(object):
1546 def __get__(self, instance, owner):
1547 return 3
1548 class meta(type):
1549 d = descriptor()
1550 class Thing(object, metaclass=meta):
1551 pass
1552 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1553
1554
Michael Foordcc7ebb82010-11-20 16:20:16 +00001555 def test_class_as_property(self):
1556 class Base(object):
1557 foo = 3
1558
1559 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001560 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001561 @property
1562 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001563 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001564 return object
1565
Michael Foord35184ed2010-11-20 16:58:30 +00001566 instance = Something()
1567 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1568 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001569 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1570
Michael Foorde5162652010-11-20 16:40:44 +00001571 def test_mro_as_property(self):
1572 class Meta(type):
1573 @property
1574 def __mro__(self):
1575 return (object,)
1576
1577 class Base(object):
1578 foo = 3
1579
1580 class Something(Base, metaclass=Meta):
1581 pass
1582
1583 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1584 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1585
Michael Foorddcebe0f2011-03-15 19:20:44 -04001586 def test_dict_as_property(self):
1587 test = self
1588 test.called = False
1589
1590 class Foo(dict):
1591 a = 3
1592 @property
1593 def __dict__(self):
1594 test.called = True
1595 return {}
1596
1597 foo = Foo()
1598 foo.a = 4
1599 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1600 self.assertFalse(test.called)
1601
1602 def test_custom_object_dict(self):
1603 test = self
1604 test.called = False
1605
1606 class Custom(dict):
1607 def get(self, key, default=None):
1608 test.called = True
1609 super().get(key, default)
1610
1611 class Foo(object):
1612 a = 3
1613 foo = Foo()
1614 foo.__dict__ = Custom()
1615 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1616 self.assertFalse(test.called)
1617
1618 def test_metaclass_dict_as_property(self):
1619 class Meta(type):
1620 @property
1621 def __dict__(self):
1622 self.executed = True
1623
1624 class Thing(metaclass=Meta):
1625 executed = False
1626
1627 def __init__(self):
1628 self.spam = 42
1629
1630 instance = Thing()
1631 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1632 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001633
Michael Foorda51623b2011-12-18 22:01:40 +00001634 def test_module(self):
1635 sentinel = object()
1636 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1637 sentinel)
1638
Michael Foord3ba95f82011-12-22 01:13:37 +00001639 def test_metaclass_with_metaclass_with_dict_as_property(self):
1640 class MetaMeta(type):
1641 @property
1642 def __dict__(self):
1643 self.executed = True
1644 return dict(spam=42)
1645
1646 class Meta(type, metaclass=MetaMeta):
1647 executed = False
1648
1649 class Thing(metaclass=Meta):
1650 pass
1651
1652 with self.assertRaises(AttributeError):
1653 inspect.getattr_static(Thing, "spam")
1654 self.assertFalse(Thing.executed)
1655
Nick Coghlane0f04652010-11-21 03:44:04 +00001656class TestGetGeneratorState(unittest.TestCase):
1657
1658 def setUp(self):
1659 def number_generator():
1660 for number in range(5):
1661 yield number
1662 self.generator = number_generator()
1663
1664 def _generatorstate(self):
1665 return inspect.getgeneratorstate(self.generator)
1666
1667 def test_created(self):
1668 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1669
1670 def test_suspended(self):
1671 next(self.generator)
1672 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1673
1674 def test_closed_after_exhaustion(self):
1675 for i in self.generator:
1676 pass
1677 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1678
1679 def test_closed_after_immediate_exception(self):
1680 with self.assertRaises(RuntimeError):
1681 self.generator.throw(RuntimeError)
1682 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1683
1684 def test_running(self):
1685 # As mentioned on issue #10220, checking for the RUNNING state only
1686 # makes sense inside the generator itself.
1687 # The following generator checks for this by using the closure's
1688 # reference to self and the generator state checking helper method
1689 def running_check_generator():
1690 for number in range(5):
1691 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1692 yield number
1693 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1694 self.generator = running_check_generator()
1695 # Running up to the first yield
1696 next(self.generator)
1697 # Running after the first yield
1698 next(self.generator)
1699
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001700 def test_easy_debugging(self):
1701 # repr() and str() of a generator state should contain the state name
1702 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1703 for name in names:
1704 state = getattr(inspect, name)
1705 self.assertIn(name, repr(state))
1706 self.assertIn(name, str(state))
1707
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001708 def test_getgeneratorlocals(self):
1709 def each(lst, a=None):
1710 b=(1, 2, 3)
1711 for v in lst:
1712 if v == 3:
1713 c = 12
1714 yield v
1715
1716 numbers = each([1, 2, 3])
1717 self.assertEqual(inspect.getgeneratorlocals(numbers),
1718 {'a': None, 'lst': [1, 2, 3]})
1719 next(numbers)
1720 self.assertEqual(inspect.getgeneratorlocals(numbers),
1721 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1722 'b': (1, 2, 3)})
1723 next(numbers)
1724 self.assertEqual(inspect.getgeneratorlocals(numbers),
1725 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1726 'b': (1, 2, 3)})
1727 next(numbers)
1728 self.assertEqual(inspect.getgeneratorlocals(numbers),
1729 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1730 'b': (1, 2, 3), 'c': 12})
1731 try:
1732 next(numbers)
1733 except StopIteration:
1734 pass
1735 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1736
1737 def test_getgeneratorlocals_empty(self):
1738 def yield_one():
1739 yield 1
1740 one = yield_one()
1741 self.assertEqual(inspect.getgeneratorlocals(one), {})
1742 try:
1743 next(one)
1744 except StopIteration:
1745 pass
1746 self.assertEqual(inspect.getgeneratorlocals(one), {})
1747
1748 def test_getgeneratorlocals_error(self):
1749 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1750 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1751 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1752 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1753
Nick Coghlane0f04652010-11-21 03:44:04 +00001754
Yury Selivanov5376ba92015-06-22 12:19:30 -04001755class TestGetCoroutineState(unittest.TestCase):
1756
1757 def setUp(self):
1758 @types.coroutine
1759 def number_coroutine():
1760 for number in range(5):
1761 yield number
1762 async def coroutine():
1763 await number_coroutine()
1764 self.coroutine = coroutine()
1765
1766 def tearDown(self):
1767 self.coroutine.close()
1768
1769 def _coroutinestate(self):
1770 return inspect.getcoroutinestate(self.coroutine)
1771
1772 def test_created(self):
1773 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1774
1775 def test_suspended(self):
1776 self.coroutine.send(None)
1777 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1778
1779 def test_closed_after_exhaustion(self):
1780 while True:
1781 try:
1782 self.coroutine.send(None)
1783 except StopIteration:
1784 break
1785
1786 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1787
1788 def test_closed_after_immediate_exception(self):
1789 with self.assertRaises(RuntimeError):
1790 self.coroutine.throw(RuntimeError)
1791 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1792
1793 def test_easy_debugging(self):
1794 # repr() and str() of a coroutine state should contain the state name
1795 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1796 for name in names:
1797 state = getattr(inspect, name)
1798 self.assertIn(name, repr(state))
1799 self.assertIn(name, str(state))
1800
1801 def test_getcoroutinelocals(self):
1802 @types.coroutine
1803 def gencoro():
1804 yield
1805
1806 gencoro = gencoro()
1807 async def func(a=None):
1808 b = 'spam'
1809 await gencoro
1810
1811 coro = func()
1812 self.assertEqual(inspect.getcoroutinelocals(coro),
1813 {'a': None, 'gencoro': gencoro})
1814 coro.send(None)
1815 self.assertEqual(inspect.getcoroutinelocals(coro),
1816 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
1817
1818
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001819class MySignature(inspect.Signature):
1820 # Top-level to make it picklable;
1821 # used in test_signature_object_pickle
1822 pass
1823
1824class MyParameter(inspect.Parameter):
1825 # Top-level to make it picklable;
1826 # used in test_signature_object_pickle
1827 pass
1828
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001829
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001830
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001831class TestSignatureObject(unittest.TestCase):
1832 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04001833 def signature(func, **kw):
1834 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001835 return (tuple((param.name,
1836 (... if param.default is param.empty else param.default),
1837 (... if param.annotation is param.empty
1838 else param.annotation),
1839 str(param.kind).lower())
1840 for param in sig.parameters.values()),
1841 (... if sig.return_annotation is sig.empty
1842 else sig.return_annotation))
1843
1844 def test_signature_object(self):
1845 S = inspect.Signature
1846 P = inspect.Parameter
1847
1848 self.assertEqual(str(S()), '()')
1849
Yury Selivanov07a9e452014-01-29 10:58:16 -05001850 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001851 pass
1852 sig = inspect.signature(test)
1853 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001854 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001855 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001856 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001857 args = sig.parameters['args']
1858 ko = sig.parameters['ko']
1859 kwargs = sig.parameters['kwargs']
1860
1861 S((po, pk, args, ko, kwargs))
1862
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001863 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001864 S((pk, po, args, ko, kwargs))
1865
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001866 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001867 S((po, args, pk, ko, kwargs))
1868
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001869 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001870 S((args, po, pk, ko, kwargs))
1871
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001872 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001873 S((po, pk, args, kwargs, ko))
1874
1875 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001876 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001877 S((po, pk, args, kwargs2, ko))
1878
Yury Selivanov07a9e452014-01-29 10:58:16 -05001879 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1880 S((pod, po))
1881
1882 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1883 S((po, pkd, pk))
1884
1885 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1886 S((pkd, pk))
1887
Yury Selivanov374375d2014-03-27 12:41:53 -04001888 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04001889 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04001890
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001891 def test_signature_object_pickle(self):
1892 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1893 foo_partial = functools.partial(foo, a=1)
1894
1895 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001896
1897 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1898 with self.subTest(pickle_ver=ver, subclass=False):
1899 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1900 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001901
1902 # Test that basic sub-classing works
1903 sig = inspect.signature(foo)
1904 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1905 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1906 mysig = MySignature().replace(parameters=myparams.values(),
1907 return_annotation=sig.return_annotation)
1908 self.assertTrue(isinstance(mysig, MySignature))
1909 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1910
1911 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1912 with self.subTest(pickle_ver=ver, subclass=True):
1913 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1914 self.assertEqual(mysig, sig_pickled)
1915 self.assertTrue(isinstance(sig_pickled, MySignature))
1916 self.assertTrue(isinstance(sig_pickled.parameters['z'],
1917 MyParameter))
1918
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001919 def test_signature_immutability(self):
1920 def test(a):
1921 pass
1922 sig = inspect.signature(test)
1923
1924 with self.assertRaises(AttributeError):
1925 sig.foo = 'bar'
1926
1927 with self.assertRaises(TypeError):
1928 sig.parameters['a'] = None
1929
1930 def test_signature_on_noarg(self):
1931 def test():
1932 pass
1933 self.assertEqual(self.signature(test), ((), ...))
1934
1935 def test_signature_on_wargs(self):
1936 def test(a, b:'foo') -> 123:
1937 pass
1938 self.assertEqual(self.signature(test),
1939 ((('a', ..., ..., "positional_or_keyword"),
1940 ('b', ..., 'foo', "positional_or_keyword")),
1941 123))
1942
1943 def test_signature_on_wkwonly(self):
1944 def test(*, a:float, b:str) -> int:
1945 pass
1946 self.assertEqual(self.signature(test),
1947 ((('a', ..., float, "keyword_only"),
1948 ('b', ..., str, "keyword_only")),
1949 int))
1950
1951 def test_signature_on_complex_args(self):
1952 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1953 pass
1954 self.assertEqual(self.signature(test),
1955 ((('a', ..., ..., "positional_or_keyword"),
1956 ('b', 10, 'foo', "positional_or_keyword"),
1957 ('args', ..., 'bar', "var_positional"),
1958 ('spam', ..., 'baz', "keyword_only"),
1959 ('ham', 123, ..., "keyword_only"),
1960 ('kwargs', ..., int, "var_keyword")),
1961 ...))
1962
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001963 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001964 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1965 "Signature information for builtins requires docstrings")
1966 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001967 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001968
Larry Hastings5c661892014-01-24 06:17:25 -08001969 def test_unbound_method(o):
1970 """Use this to test unbound methods (things that should have a self)"""
1971 signature = inspect.signature(o)
1972 self.assertTrue(isinstance(signature, inspect.Signature))
1973 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1974 return signature
1975
1976 def test_callable(o):
1977 """Use this to test bound methods or normal callables (things that don't expect self)"""
1978 signature = inspect.signature(o)
1979 self.assertTrue(isinstance(signature, inspect.Signature))
1980 if signature.parameters:
1981 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1982 return signature
1983
1984 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001985 def p(name): return signature.parameters[name].default
1986 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001987 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001988 self.assertEqual(p('d'), 3.14)
1989 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001990 self.assertEqual(p('n'), None)
1991 self.assertEqual(p('t'), True)
1992 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001993 self.assertEqual(p('local'), 3)
1994 self.assertEqual(p('sys'), sys.maxsize)
1995 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001996
Larry Hastings5c661892014-01-24 06:17:25 -08001997 test_callable(object)
1998
1999 # normal method
2000 # (PyMethodDescr_Type, "method_descriptor")
2001 test_unbound_method(_pickle.Pickler.dump)
2002 d = _pickle.Pickler(io.StringIO())
2003 test_callable(d.dump)
2004
2005 # static method
2006 test_callable(str.maketrans)
2007 test_callable('abc'.maketrans)
2008
2009 # class method
2010 test_callable(dict.fromkeys)
2011 test_callable({}.fromkeys)
2012
2013 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2014 test_unbound_method(type.__call__)
2015 test_unbound_method(int.__add__)
2016 test_callable((3).__add__)
2017
2018 # _PyMethodWrapper_Type
2019 # support for 'method-wrapper'
2020 test_callable(min.__call__)
2021
Larry Hastings2623c8c2014-02-08 22:15:29 -08002022 # This doesn't work now.
2023 # (We don't have a valid signature for "type" in 3.4)
2024 with self.assertRaisesRegex(ValueError, "no signature found"):
2025 class ThisWorksNow:
2026 __call__ = type
2027 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002028
Yury Selivanov056e2652014-03-02 12:25:27 -05002029 # Regression test for issue #20786
2030 test_unbound_method(dict.__delitem__)
2031 test_unbound_method(property.__delete__)
2032
Zachary Ware8ef887c2015-04-13 18:22:35 -05002033 # Regression test for issue #20586
2034 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2035
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002036 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002037 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2038 "Signature information for builtins requires docstrings")
2039 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002040 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002041 func = _testcapi.docstring_with_signature_with_defaults
2042
2043 def decorator(func):
2044 @functools.wraps(func)
2045 def wrapper(*args, **kwargs) -> int:
2046 return func(*args, **kwargs)
2047 return wrapper
2048
2049 decorated_func = decorator(func)
2050
2051 self.assertEqual(inspect.signature(func),
2052 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002053
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002054 def wrapper_like(*args, **kwargs) -> int: pass
2055 self.assertEqual(inspect.signature(decorated_func,
2056 follow_wrapped=False),
2057 inspect.signature(wrapper_like))
2058
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002059 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002060 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002061 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002062 with self.assertRaisesRegex(ValueError,
2063 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002064 inspect.signature(_testcapi.docstring_no_signature)
2065
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002066 with self.assertRaisesRegex(ValueError,
2067 'no signature found for builtin'):
2068 inspect.signature(str)
2069
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002070 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002071 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002072 inspect.signature(42)
2073
Yury Selivanov63da7c72014-01-31 14:48:37 -05002074 def test_signature_from_functionlike_object(self):
2075 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2076 pass
2077
2078 class funclike:
2079 # Has to be callable, and have correct
2080 # __code__, __annotations__, __defaults__, __name__,
2081 # and __kwdefaults__ attributes
2082
2083 def __init__(self, func):
2084 self.__name__ = func.__name__
2085 self.__code__ = func.__code__
2086 self.__annotations__ = func.__annotations__
2087 self.__defaults__ = func.__defaults__
2088 self.__kwdefaults__ = func.__kwdefaults__
2089 self.func = func
2090
2091 def __call__(self, *args, **kwargs):
2092 return self.func(*args, **kwargs)
2093
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002094 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002095
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002096 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002097 self.assertEqual(sig_funclike, sig_func)
2098
2099 sig_funclike = inspect.signature(funclike(func))
2100 self.assertEqual(sig_funclike, sig_func)
2101
2102 # If object is not a duck type of function, then
2103 # signature will try to get a signature for its '__call__'
2104 # method
2105 fl = funclike(func)
2106 del fl.__defaults__
2107 self.assertEqual(self.signature(fl),
2108 ((('args', ..., ..., "var_positional"),
2109 ('kwargs', ..., ..., "var_keyword")),
2110 ...))
2111
Yury Selivanova773de02014-02-21 18:30:53 -05002112 # Test with cython-like builtins:
2113 _orig_isdesc = inspect.ismethoddescriptor
2114 def _isdesc(obj):
2115 if hasattr(obj, '_builtinmock'):
2116 return True
2117 return _orig_isdesc(obj)
2118
2119 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2120 builtin_func = funclike(func)
2121 # Make sure that our mock setup is working
2122 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2123 builtin_func._builtinmock = True
2124 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2125 self.assertEqual(inspect.signature(builtin_func), sig_func)
2126
Yury Selivanov63da7c72014-01-31 14:48:37 -05002127 def test_signature_functionlike_class(self):
2128 # We only want to duck type function-like objects,
2129 # not classes.
2130
2131 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2132 pass
2133
2134 class funclike:
2135 def __init__(self, marker):
2136 pass
2137
2138 __name__ = func.__name__
2139 __code__ = func.__code__
2140 __annotations__ = func.__annotations__
2141 __defaults__ = func.__defaults__
2142 __kwdefaults__ = func.__kwdefaults__
2143
Yury Selivanov63da7c72014-01-31 14:48:37 -05002144 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2145
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002146 def test_signature_on_method(self):
2147 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002148 def __init__(*args):
2149 pass
2150 def m1(self, arg1, arg2=1) -> int:
2151 pass
2152 def m2(*args):
2153 pass
2154 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002155 pass
2156
Yury Selivanov62560fb2014-01-28 12:26:24 -05002157 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002158 ((('arg1', ..., ..., "positional_or_keyword"),
2159 ('arg2', 1, ..., "positional_or_keyword")),
2160 int))
2161
Yury Selivanov62560fb2014-01-28 12:26:24 -05002162 self.assertEqual(self.signature(Test().m2),
2163 ((('args', ..., ..., "var_positional"),),
2164 ...))
2165
2166 self.assertEqual(self.signature(Test),
2167 ((('args', ..., ..., "var_positional"),),
2168 ...))
2169
2170 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2171 self.signature(Test())
2172
Yury Selivanov46c759d2015-05-27 21:56:53 -04002173 def test_signature_wrapped_bound_method(self):
2174 # Issue 24298
2175 class Test:
2176 def m1(self, arg1, arg2=1) -> int:
2177 pass
2178 @functools.wraps(Test().m1)
2179 def m1d(*args, **kwargs):
2180 pass
2181 self.assertEqual(self.signature(m1d),
2182 ((('arg1', ..., ..., "positional_or_keyword"),
2183 ('arg2', 1, ..., "positional_or_keyword")),
2184 int))
2185
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002186 def test_signature_on_classmethod(self):
2187 class Test:
2188 @classmethod
2189 def foo(cls, arg1, *, arg2=1):
2190 pass
2191
2192 meth = Test().foo
2193 self.assertEqual(self.signature(meth),
2194 ((('arg1', ..., ..., "positional_or_keyword"),
2195 ('arg2', 1, ..., "keyword_only")),
2196 ...))
2197
2198 meth = Test.foo
2199 self.assertEqual(self.signature(meth),
2200 ((('arg1', ..., ..., "positional_or_keyword"),
2201 ('arg2', 1, ..., "keyword_only")),
2202 ...))
2203
2204 def test_signature_on_staticmethod(self):
2205 class Test:
2206 @staticmethod
2207 def foo(cls, *, arg):
2208 pass
2209
2210 meth = Test().foo
2211 self.assertEqual(self.signature(meth),
2212 ((('cls', ..., ..., "positional_or_keyword"),
2213 ('arg', ..., ..., "keyword_only")),
2214 ...))
2215
2216 meth = Test.foo
2217 self.assertEqual(self.signature(meth),
2218 ((('cls', ..., ..., "positional_or_keyword"),
2219 ('arg', ..., ..., "keyword_only")),
2220 ...))
2221
2222 def test_signature_on_partial(self):
2223 from functools import partial
2224
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002225 Parameter = inspect.Parameter
2226
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002227 def test():
2228 pass
2229
2230 self.assertEqual(self.signature(partial(test)), ((), ...))
2231
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002232 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002233 inspect.signature(partial(test, 1))
2234
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002235 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002236 inspect.signature(partial(test, a=1))
2237
2238 def test(a, b, *, c, d):
2239 pass
2240
2241 self.assertEqual(self.signature(partial(test)),
2242 ((('a', ..., ..., "positional_or_keyword"),
2243 ('b', ..., ..., "positional_or_keyword"),
2244 ('c', ..., ..., "keyword_only"),
2245 ('d', ..., ..., "keyword_only")),
2246 ...))
2247
2248 self.assertEqual(self.signature(partial(test, 1)),
2249 ((('b', ..., ..., "positional_or_keyword"),
2250 ('c', ..., ..., "keyword_only"),
2251 ('d', ..., ..., "keyword_only")),
2252 ...))
2253
2254 self.assertEqual(self.signature(partial(test, 1, c=2)),
2255 ((('b', ..., ..., "positional_or_keyword"),
2256 ('c', 2, ..., "keyword_only"),
2257 ('d', ..., ..., "keyword_only")),
2258 ...))
2259
2260 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2261 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002262 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002263 ('c', 2, ..., "keyword_only"),
2264 ('d', ..., ..., "keyword_only")),
2265 ...))
2266
2267 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002268 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002269 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002270 ('d', ..., ..., "keyword_only")),
2271 ...))
2272
2273 self.assertEqual(self.signature(partial(test, a=1)),
2274 ((('a', 1, ..., "keyword_only"),
2275 ('b', ..., ..., "keyword_only"),
2276 ('c', ..., ..., "keyword_only"),
2277 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002278 ...))
2279
2280 def test(a, *args, b, **kwargs):
2281 pass
2282
2283 self.assertEqual(self.signature(partial(test, 1)),
2284 ((('args', ..., ..., "var_positional"),
2285 ('b', ..., ..., "keyword_only"),
2286 ('kwargs', ..., ..., "var_keyword")),
2287 ...))
2288
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002289 self.assertEqual(self.signature(partial(test, a=1)),
2290 ((('a', 1, ..., "keyword_only"),
2291 ('b', ..., ..., "keyword_only"),
2292 ('kwargs', ..., ..., "var_keyword")),
2293 ...))
2294
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002295 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2296 ((('args', ..., ..., "var_positional"),
2297 ('b', ..., ..., "keyword_only"),
2298 ('kwargs', ..., ..., "var_keyword")),
2299 ...))
2300
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002301 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2302 ((('args', ..., ..., "var_positional"),
2303 ('b', ..., ..., "keyword_only"),
2304 ('kwargs', ..., ..., "var_keyword")),
2305 ...))
2306
2307 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2308 ((('args', ..., ..., "var_positional"),
2309 ('b', 0, ..., "keyword_only"),
2310 ('kwargs', ..., ..., "var_keyword")),
2311 ...))
2312
2313 self.assertEqual(self.signature(partial(test, b=0)),
2314 ((('a', ..., ..., "positional_or_keyword"),
2315 ('args', ..., ..., "var_positional"),
2316 ('b', 0, ..., "keyword_only"),
2317 ('kwargs', ..., ..., "var_keyword")),
2318 ...))
2319
2320 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2321 ((('a', ..., ..., "positional_or_keyword"),
2322 ('args', ..., ..., "var_positional"),
2323 ('b', 0, ..., "keyword_only"),
2324 ('kwargs', ..., ..., "var_keyword")),
2325 ...))
2326
2327 def test(a, b, c:int) -> 42:
2328 pass
2329
2330 sig = test.__signature__ = inspect.signature(test)
2331
2332 self.assertEqual(self.signature(partial(partial(test, 1))),
2333 ((('b', ..., ..., "positional_or_keyword"),
2334 ('c', ..., int, "positional_or_keyword")),
2335 42))
2336
2337 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2338 ((('c', ..., int, "positional_or_keyword"),),
2339 42))
2340
2341 psig = inspect.signature(partial(partial(test, 1), 2))
2342
2343 def foo(a):
2344 return a
2345 _foo = partial(partial(foo, a=10), a=20)
2346 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002347 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002348 ...))
2349 # check that we don't have any side-effects in signature(),
2350 # and the partial object is still functioning
2351 self.assertEqual(_foo(), 20)
2352
2353 def foo(a, b, c):
2354 return a, b, c
2355 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002356
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002357 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002358 ((('b', 30, ..., "keyword_only"),
2359 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002360 ...))
2361 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002362
2363 def foo(a, b, c, *, d):
2364 return a, b, c, d
2365 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2366 self.assertEqual(self.signature(_foo),
2367 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002368 ('b', 10, ..., "keyword_only"),
2369 ('c', 20, ..., "keyword_only"),
2370 ('d', 30, ..., "keyword_only"),
2371 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002372 ...))
2373 ba = inspect.signature(_foo).bind(a=200, b=11)
2374 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2375
2376 def foo(a=1, b=2, c=3):
2377 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002378 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2379
2380 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002381 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002382
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002383 ba = inspect.signature(_foo).bind(11, 12)
2384 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002385
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002386 ba = inspect.signature(_foo).bind(11, b=12)
2387 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002388
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002389 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002390 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2391
2392 _foo = partial(_foo, b=10, c=20)
2393 ba = inspect.signature(_foo).bind(12)
2394 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2395
2396
2397 def foo(a, b, c, d, **kwargs):
2398 pass
2399 sig = inspect.signature(foo)
2400 params = sig.parameters.copy()
2401 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2402 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2403 foo.__signature__ = inspect.Signature(params.values())
2404 sig = inspect.signature(foo)
2405 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2406
2407 self.assertEqual(self.signature(partial(foo, 1)),
2408 ((('b', ..., ..., 'positional_only'),
2409 ('c', ..., ..., 'positional_or_keyword'),
2410 ('d', ..., ..., 'positional_or_keyword'),
2411 ('kwargs', ..., ..., 'var_keyword')),
2412 ...))
2413
2414 self.assertEqual(self.signature(partial(foo, 1, 2)),
2415 ((('c', ..., ..., 'positional_or_keyword'),
2416 ('d', ..., ..., 'positional_or_keyword'),
2417 ('kwargs', ..., ..., 'var_keyword')),
2418 ...))
2419
2420 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2421 ((('d', ..., ..., 'positional_or_keyword'),
2422 ('kwargs', ..., ..., 'var_keyword')),
2423 ...))
2424
2425 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2426 ((('c', 3, ..., 'keyword_only'),
2427 ('d', ..., ..., 'keyword_only'),
2428 ('kwargs', ..., ..., 'var_keyword')),
2429 ...))
2430
2431 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2432 ((('b', ..., ..., 'positional_only'),
2433 ('c', 3, ..., 'keyword_only'),
2434 ('d', ..., ..., 'keyword_only'),
2435 ('kwargs', ..., ..., 'var_keyword')),
2436 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002437
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002438 def test_signature_on_partialmethod(self):
2439 from functools import partialmethod
2440
2441 class Spam:
2442 def test():
2443 pass
2444 ham = partialmethod(test)
2445
2446 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2447 inspect.signature(Spam.ham)
2448
2449 class Spam:
2450 def test(it, a, *, c) -> 'spam':
2451 pass
2452 ham = partialmethod(test, c=1)
2453
2454 self.assertEqual(self.signature(Spam.ham),
2455 ((('it', ..., ..., 'positional_or_keyword'),
2456 ('a', ..., ..., 'positional_or_keyword'),
2457 ('c', 1, ..., 'keyword_only')),
2458 'spam'))
2459
2460 self.assertEqual(self.signature(Spam().ham),
2461 ((('a', ..., ..., 'positional_or_keyword'),
2462 ('c', 1, ..., 'keyword_only')),
2463 'spam'))
2464
Yury Selivanov0486f812014-01-29 12:18:59 -05002465 def test_signature_on_fake_partialmethod(self):
2466 def foo(a): pass
2467 foo._partialmethod = 'spam'
2468 self.assertEqual(str(inspect.signature(foo)), '(a)')
2469
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002470 def test_signature_on_decorated(self):
2471 import functools
2472
2473 def decorator(func):
2474 @functools.wraps(func)
2475 def wrapper(*args, **kwargs) -> int:
2476 return func(*args, **kwargs)
2477 return wrapper
2478
2479 class Foo:
2480 @decorator
2481 def bar(self, a, b):
2482 pass
2483
2484 self.assertEqual(self.signature(Foo.bar),
2485 ((('self', ..., ..., "positional_or_keyword"),
2486 ('a', ..., ..., "positional_or_keyword"),
2487 ('b', ..., ..., "positional_or_keyword")),
2488 ...))
2489
2490 self.assertEqual(self.signature(Foo().bar),
2491 ((('a', ..., ..., "positional_or_keyword"),
2492 ('b', ..., ..., "positional_or_keyword")),
2493 ...))
2494
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002495 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2496 ((('args', ..., ..., "var_positional"),
2497 ('kwargs', ..., ..., "var_keyword")),
2498 ...)) # functools.wraps will copy __annotations__
2499 # from "func" to "wrapper", hence no
2500 # return_annotation
2501
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002502 # Test that we handle method wrappers correctly
2503 def decorator(func):
2504 @functools.wraps(func)
2505 def wrapper(*args, **kwargs) -> int:
2506 return func(42, *args, **kwargs)
2507 sig = inspect.signature(func)
2508 new_params = tuple(sig.parameters.values())[1:]
2509 wrapper.__signature__ = sig.replace(parameters=new_params)
2510 return wrapper
2511
2512 class Foo:
2513 @decorator
2514 def __call__(self, a, b):
2515 pass
2516
2517 self.assertEqual(self.signature(Foo.__call__),
2518 ((('a', ..., ..., "positional_or_keyword"),
2519 ('b', ..., ..., "positional_or_keyword")),
2520 ...))
2521
2522 self.assertEqual(self.signature(Foo().__call__),
2523 ((('b', ..., ..., "positional_or_keyword"),),
2524 ...))
2525
Nick Coghlane8c45d62013-07-28 20:00:01 +10002526 # Test we handle __signature__ partway down the wrapper stack
2527 def wrapped_foo_call():
2528 pass
2529 wrapped_foo_call.__wrapped__ = Foo.__call__
2530
2531 self.assertEqual(self.signature(wrapped_foo_call),
2532 ((('a', ..., ..., "positional_or_keyword"),
2533 ('b', ..., ..., "positional_or_keyword")),
2534 ...))
2535
2536
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002537 def test_signature_on_class(self):
2538 class C:
2539 def __init__(self, a):
2540 pass
2541
2542 self.assertEqual(self.signature(C),
2543 ((('a', ..., ..., "positional_or_keyword"),),
2544 ...))
2545
2546 class CM(type):
2547 def __call__(cls, a):
2548 pass
2549 class C(metaclass=CM):
2550 def __init__(self, b):
2551 pass
2552
2553 self.assertEqual(self.signature(C),
2554 ((('a', ..., ..., "positional_or_keyword"),),
2555 ...))
2556
2557 class CM(type):
2558 def __new__(mcls, name, bases, dct, *, foo=1):
2559 return super().__new__(mcls, name, bases, dct)
2560 class C(metaclass=CM):
2561 def __init__(self, b):
2562 pass
2563
2564 self.assertEqual(self.signature(C),
2565 ((('b', ..., ..., "positional_or_keyword"),),
2566 ...))
2567
2568 self.assertEqual(self.signature(CM),
2569 ((('name', ..., ..., "positional_or_keyword"),
2570 ('bases', ..., ..., "positional_or_keyword"),
2571 ('dct', ..., ..., "positional_or_keyword"),
2572 ('foo', 1, ..., "keyword_only")),
2573 ...))
2574
2575 class CMM(type):
2576 def __new__(mcls, name, bases, dct, *, foo=1):
2577 return super().__new__(mcls, name, bases, dct)
2578 def __call__(cls, nm, bs, dt):
2579 return type(nm, bs, dt)
2580 class CM(type, metaclass=CMM):
2581 def __new__(mcls, name, bases, dct, *, bar=2):
2582 return super().__new__(mcls, name, bases, dct)
2583 class C(metaclass=CM):
2584 def __init__(self, b):
2585 pass
2586
2587 self.assertEqual(self.signature(CMM),
2588 ((('name', ..., ..., "positional_or_keyword"),
2589 ('bases', ..., ..., "positional_or_keyword"),
2590 ('dct', ..., ..., "positional_or_keyword"),
2591 ('foo', 1, ..., "keyword_only")),
2592 ...))
2593
2594 self.assertEqual(self.signature(CM),
2595 ((('nm', ..., ..., "positional_or_keyword"),
2596 ('bs', ..., ..., "positional_or_keyword"),
2597 ('dt', ..., ..., "positional_or_keyword")),
2598 ...))
2599
2600 self.assertEqual(self.signature(C),
2601 ((('b', ..., ..., "positional_or_keyword"),),
2602 ...))
2603
2604 class CM(type):
2605 def __init__(cls, name, bases, dct, *, bar=2):
2606 return super().__init__(name, bases, dct)
2607 class C(metaclass=CM):
2608 def __init__(self, b):
2609 pass
2610
2611 self.assertEqual(self.signature(CM),
2612 ((('name', ..., ..., "positional_or_keyword"),
2613 ('bases', ..., ..., "positional_or_keyword"),
2614 ('dct', ..., ..., "positional_or_keyword"),
2615 ('bar', 2, ..., "keyword_only")),
2616 ...))
2617
Yury Selivanov145dff82014-02-01 13:49:29 -05002618 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2619 "Signature information for builtins requires docstrings")
2620 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002621 # Test classes without user-defined __init__ or __new__
2622 class C: pass
2623 self.assertEqual(str(inspect.signature(C)), '()')
2624 class D(C): pass
2625 self.assertEqual(str(inspect.signature(D)), '()')
2626
2627 # Test meta-classes without user-defined __init__ or __new__
2628 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002629 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002630 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2631 self.assertEqual(inspect.signature(C), None)
2632 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2633 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002634
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002635 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2636 "Signature information for builtins requires docstrings")
2637 def test_signature_on_builtin_class(self):
2638 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2639 '(file, protocol=None, fix_imports=True)')
2640
2641 class P(_pickle.Pickler): pass
2642 class EmptyTrait: pass
2643 class P2(EmptyTrait, P): pass
2644 self.assertEqual(str(inspect.signature(P)),
2645 '(file, protocol=None, fix_imports=True)')
2646 self.assertEqual(str(inspect.signature(P2)),
2647 '(file, protocol=None, fix_imports=True)')
2648
2649 class P3(P2):
2650 def __init__(self, spam):
2651 pass
2652 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2653
2654 class MetaP(type):
2655 def __call__(cls, foo, bar):
2656 pass
2657 class P4(P2, metaclass=MetaP):
2658 pass
2659 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2660
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002661 def test_signature_on_callable_objects(self):
2662 class Foo:
2663 def __call__(self, a):
2664 pass
2665
2666 self.assertEqual(self.signature(Foo()),
2667 ((('a', ..., ..., "positional_or_keyword"),),
2668 ...))
2669
2670 class Spam:
2671 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002672 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002673 inspect.signature(Spam())
2674
2675 class Bar(Spam, Foo):
2676 pass
2677
2678 self.assertEqual(self.signature(Bar()),
2679 ((('a', ..., ..., "positional_or_keyword"),),
2680 ...))
2681
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002682 class Wrapped:
2683 pass
2684 Wrapped.__wrapped__ = lambda a: None
2685 self.assertEqual(self.signature(Wrapped),
2686 ((('a', ..., ..., "positional_or_keyword"),),
2687 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002688 # wrapper loop:
2689 Wrapped.__wrapped__ = Wrapped
2690 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2691 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002692
2693 def test_signature_on_lambdas(self):
2694 self.assertEqual(self.signature((lambda a=10: a)),
2695 ((('a', 10, ..., "positional_or_keyword"),),
2696 ...))
2697
2698 def test_signature_equality(self):
2699 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002700 self.assertFalse(inspect.signature(foo) == 42)
2701 self.assertTrue(inspect.signature(foo) != 42)
2702 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2703 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002704
2705 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002706 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2707 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002708 self.assertEqual(
2709 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002710
2711 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002712 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2713 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002714 self.assertNotEqual(
2715 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002716
2717 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002718 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2719 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002720 self.assertNotEqual(
2721 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002722
2723 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002724 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2725 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002726 self.assertNotEqual(
2727 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002728
2729 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002730 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2731 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002732 self.assertNotEqual(
2733 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002734
2735 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002736 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2737 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002738 self.assertNotEqual(
2739 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002740 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002741 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
2742 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002743 self.assertNotEqual(
2744 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002745
2746 def foo(*, a, b, c): pass
2747 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002748 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2749 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002750 self.assertEqual(
2751 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002752
2753 def foo(*, a=1, b, c): pass
2754 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002755 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2756 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002757 self.assertEqual(
2758 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002759
2760 def foo(pos, *, a=1, b, c): pass
2761 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002762 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2763 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002764 self.assertEqual(
2765 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002766
2767 def foo(pos, *, a, b, c): pass
2768 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002769 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2770 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002771 self.assertNotEqual(
2772 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002773
2774 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2775 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002776 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2777 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002778 self.assertEqual(
2779 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002780
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002781 def test_signature_hashable(self):
2782 S = inspect.Signature
2783 P = inspect.Parameter
2784
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002785 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002786 foo_sig = inspect.signature(foo)
2787
2788 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2789
2790 self.assertEqual(hash(foo_sig), hash(manual_sig))
2791 self.assertNotEqual(hash(foo_sig),
2792 hash(manual_sig.replace(return_annotation='spam')))
2793
2794 def bar(a) -> 1: pass
2795 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2796
2797 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002798 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002799 hash(inspect.signature(foo))
2800
2801 def foo(a) -> {}: pass
2802 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2803 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002804
2805 def test_signature_str(self):
2806 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2807 pass
2808 self.assertEqual(str(inspect.signature(foo)),
2809 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2810
2811 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2812 pass
2813 self.assertEqual(str(inspect.signature(foo)),
2814 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2815
2816 def foo():
2817 pass
2818 self.assertEqual(str(inspect.signature(foo)), '()')
2819
2820 def test_signature_str_positional_only(self):
2821 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002822 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002823
2824 def test(a_po, *, b, **kwargs):
2825 return a_po, kwargs
2826
2827 sig = inspect.signature(test)
2828 new_params = list(sig.parameters.values())
2829 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2830 test.__signature__ = sig.replace(parameters=new_params)
2831
2832 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002833 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002834
Yury Selivanov2393dca2014-01-27 15:07:58 -05002835 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2836 '(foo, /)')
2837
2838 self.assertEqual(str(S(parameters=[
2839 P('foo', P.POSITIONAL_ONLY),
2840 P('bar', P.VAR_KEYWORD)])),
2841 '(foo, /, **bar)')
2842
2843 self.assertEqual(str(S(parameters=[
2844 P('foo', P.POSITIONAL_ONLY),
2845 P('bar', P.VAR_POSITIONAL)])),
2846 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002847
2848 def test_signature_replace_anno(self):
2849 def test() -> 42:
2850 pass
2851
2852 sig = inspect.signature(test)
2853 sig = sig.replace(return_annotation=None)
2854 self.assertIs(sig.return_annotation, None)
2855 sig = sig.replace(return_annotation=sig.empty)
2856 self.assertIs(sig.return_annotation, sig.empty)
2857 sig = sig.replace(return_annotation=42)
2858 self.assertEqual(sig.return_annotation, 42)
2859 self.assertEqual(sig, inspect.signature(test))
2860
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002861 def test_signature_on_mangled_parameters(self):
2862 class Spam:
2863 def foo(self, __p1:1=2, *, __p2:2=3):
2864 pass
2865 class Ham(Spam):
2866 pass
2867
2868 self.assertEqual(self.signature(Spam.foo),
2869 ((('self', ..., ..., "positional_or_keyword"),
2870 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2871 ('_Spam__p2', 3, 2, "keyword_only")),
2872 ...))
2873
2874 self.assertEqual(self.signature(Spam.foo),
2875 self.signature(Ham.foo))
2876
Yury Selivanovda396452014-03-27 12:09:24 -04002877 def test_signature_from_callable_python_obj(self):
2878 class MySignature(inspect.Signature): pass
2879 def foo(a, *, b:1): pass
2880 foo_sig = MySignature.from_callable(foo)
2881 self.assertTrue(isinstance(foo_sig, MySignature))
2882
2883 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2884 "Signature information for builtins requires docstrings")
2885 def test_signature_from_callable_builtin_obj(self):
2886 class MySignature(inspect.Signature): pass
2887 sig = MySignature.from_callable(_pickle.Pickler)
2888 self.assertTrue(isinstance(sig, MySignature))
2889
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002890
2891class TestParameterObject(unittest.TestCase):
2892 def test_signature_parameter_kinds(self):
2893 P = inspect.Parameter
2894 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2895 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2896
2897 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2898 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2899
2900 def test_signature_parameter_object(self):
2901 p = inspect.Parameter('foo', default=10,
2902 kind=inspect.Parameter.POSITIONAL_ONLY)
2903 self.assertEqual(p.name, 'foo')
2904 self.assertEqual(p.default, 10)
2905 self.assertIs(p.annotation, p.empty)
2906 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2907
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002908 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002909 inspect.Parameter('foo', default=10, kind='123')
2910
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002911 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002912 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2913
Yury Selivanov2393dca2014-01-27 15:07:58 -05002914 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002915 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2916
Yury Selivanov2393dca2014-01-27 15:07:58 -05002917 with self.assertRaisesRegex(ValueError,
2918 'is not a valid parameter name'):
2919 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2920
Nick Coghlanb4b966e2016-06-04 14:40:03 -07002921 with self.assertRaisesRegex(ValueError,
2922 'is not a valid parameter name'):
2923 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
2924
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002925 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002926 inspect.Parameter('a', default=42,
2927 kind=inspect.Parameter.VAR_KEYWORD)
2928
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002929 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002930 inspect.Parameter('a', default=42,
2931 kind=inspect.Parameter.VAR_POSITIONAL)
2932
2933 p = inspect.Parameter('a', default=42,
2934 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002935 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002936 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2937
2938 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002939 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002940
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002941 def test_signature_parameter_hashable(self):
2942 P = inspect.Parameter
2943 foo = P('foo', kind=P.POSITIONAL_ONLY)
2944 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
2945 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
2946 default=42)))
2947 self.assertNotEqual(hash(foo),
2948 hash(foo.replace(kind=P.VAR_POSITIONAL)))
2949
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002950 def test_signature_parameter_equality(self):
2951 P = inspect.Parameter
2952 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2953
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002954 self.assertTrue(p == p)
2955 self.assertFalse(p != p)
2956 self.assertFalse(p == 42)
2957 self.assertTrue(p != 42)
2958 self.assertTrue(p == EqualsToAll())
2959 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002960
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002961 self.assertTrue(p == P('foo', default=42,
2962 kind=inspect.Parameter.KEYWORD_ONLY))
2963 self.assertFalse(p != P('foo', default=42,
2964 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002965
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002966 def test_signature_parameter_replace(self):
2967 p = inspect.Parameter('foo', default=42,
2968 kind=inspect.Parameter.KEYWORD_ONLY)
2969
2970 self.assertIsNot(p, p.replace())
2971 self.assertEqual(p, p.replace())
2972
2973 p2 = p.replace(annotation=1)
2974 self.assertEqual(p2.annotation, 1)
2975 p2 = p2.replace(annotation=p2.empty)
2976 self.assertEqual(p, p2)
2977
2978 p2 = p2.replace(name='bar')
2979 self.assertEqual(p2.name, 'bar')
2980 self.assertNotEqual(p2, p)
2981
Yury Selivanov2393dca2014-01-27 15:07:58 -05002982 with self.assertRaisesRegex(ValueError,
2983 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002984 p2 = p2.replace(name=p2.empty)
2985
2986 p2 = p2.replace(name='foo', default=None)
2987 self.assertIs(p2.default, None)
2988 self.assertNotEqual(p2, p)
2989
2990 p2 = p2.replace(name='foo', default=p2.empty)
2991 self.assertIs(p2.default, p2.empty)
2992
2993
2994 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2995 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2996 self.assertNotEqual(p2, p)
2997
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002998 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002999 p2 = p2.replace(kind=p2.empty)
3000
3001 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3002 self.assertEqual(p2, p)
3003
3004 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003005 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3006 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003007
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003008 @cpython_only
3009 def test_signature_parameter_implicit(self):
3010 with self.assertRaisesRegex(ValueError,
3011 'implicit arguments must be passed in as'):
3012 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3013
3014 param = inspect.Parameter(
3015 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3016 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3017 self.assertEqual(param.name, 'implicit0')
3018
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003019 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003020 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003021
3022 with self.assertRaises(AttributeError):
3023 p.foo = 'bar'
3024
3025 with self.assertRaises(AttributeError):
3026 p.kind = 123
3027
3028
3029class TestSignatureBind(unittest.TestCase):
3030 @staticmethod
3031 def call(func, *args, **kwargs):
3032 sig = inspect.signature(func)
3033 ba = sig.bind(*args, **kwargs)
3034 return func(*ba.args, **ba.kwargs)
3035
3036 def test_signature_bind_empty(self):
3037 def test():
3038 return 42
3039
3040 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003041 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003042 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003043 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003044 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003045 with self.assertRaisesRegex(
3046 TypeError, "got an unexpected keyword argument 'spam'"):
3047
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003048 self.call(test, spam=1)
3049
3050 def test_signature_bind_var(self):
3051 def test(*args, **kwargs):
3052 return args, kwargs
3053
3054 self.assertEqual(self.call(test), ((), {}))
3055 self.assertEqual(self.call(test, 1), ((1,), {}))
3056 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3057 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3058 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3059 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3060 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3061 ((1, 2), {'foo': 'bar'}))
3062
3063 def test_signature_bind_just_args(self):
3064 def test(a, b, c):
3065 return a, b, c
3066
3067 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3068
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003069 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003070 self.call(test, 1, 2, 3, 4)
3071
Yury Selivanov86872752015-05-19 00:27:49 -04003072 with self.assertRaisesRegex(TypeError,
3073 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003074 self.call(test, 1)
3075
Yury Selivanov86872752015-05-19 00:27:49 -04003076 with self.assertRaisesRegex(TypeError,
3077 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003078 self.call(test)
3079
3080 def test(a, b, c=10):
3081 return a, b, c
3082 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3083 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3084
3085 def test(a=1, b=2, c=3):
3086 return a, b, c
3087 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3088 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3089 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3090
3091 def test_signature_bind_varargs_order(self):
3092 def test(*args):
3093 return args
3094
3095 self.assertEqual(self.call(test), ())
3096 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3097
3098 def test_signature_bind_args_and_varargs(self):
3099 def test(a, b, c=3, *args):
3100 return a, b, c, args
3101
3102 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3103 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3104 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3105 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3106
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003107 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003108 "multiple values for argument 'c'"):
3109 self.call(test, 1, 2, 3, c=4)
3110
3111 def test_signature_bind_just_kwargs(self):
3112 def test(**kwargs):
3113 return kwargs
3114
3115 self.assertEqual(self.call(test), {})
3116 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3117 {'foo': 'bar', 'spam': 'ham'})
3118
3119 def test_signature_bind_args_and_kwargs(self):
3120 def test(a, b, c=3, **kwargs):
3121 return a, b, c, kwargs
3122
3123 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3124 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3125 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3126 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3127 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3128 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3129 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3130 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3131 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3132 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3133 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3134 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3135 (1, 2, 4, {'foo': 'bar'}))
3136 self.assertEqual(self.call(test, c=5, a=4, b=3),
3137 (4, 3, 5, {}))
3138
3139 def test_signature_bind_kwonly(self):
3140 def test(*, foo):
3141 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003142 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003143 'too many positional arguments'):
3144 self.call(test, 1)
3145 self.assertEqual(self.call(test, foo=1), 1)
3146
3147 def test(a, *, foo=1, bar):
3148 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003149 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003150 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003151 self.call(test, 1)
3152
3153 def test(foo, *, bar):
3154 return foo, bar
3155 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3156 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3157
Yury Selivanov86872752015-05-19 00:27:49 -04003158 with self.assertRaisesRegex(
3159 TypeError, "got an unexpected keyword argument 'spam'"):
3160
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003161 self.call(test, bar=2, foo=1, spam=10)
3162
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003163 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003164 'too many positional arguments'):
3165 self.call(test, 1, 2)
3166
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003167 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003168 'too many positional arguments'):
3169 self.call(test, 1, 2, bar=2)
3170
Yury Selivanov86872752015-05-19 00:27:49 -04003171 with self.assertRaisesRegex(
3172 TypeError, "got an unexpected keyword argument 'spam'"):
3173
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003174 self.call(test, 1, bar=2, spam='ham')
3175
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003176 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003177 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003178 self.call(test, 1)
3179
3180 def test(foo, *, bar, **bin):
3181 return foo, bar, bin
3182 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3183 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3184 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3185 (1, 2, {'spam': 'ham'}))
3186 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3187 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003188 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003189 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003190 self.call(test, spam='ham', bar=2)
3191 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3192 (1, 2, {'bin': 1, 'spam': 10}))
3193
3194 def test_signature_bind_arguments(self):
3195 def test(a, *args, b, z=100, **kwargs):
3196 pass
3197 sig = inspect.signature(test)
3198 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3199 # we won't have 'z' argument in the bound arguments object, as we didn't
3200 # pass it to the 'bind'
3201 self.assertEqual(tuple(ba.arguments.items()),
3202 (('a', 10), ('args', (20,)), ('b', 30),
3203 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3204 self.assertEqual(ba.kwargs,
3205 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3206 self.assertEqual(ba.args, (10, 20))
3207
3208 def test_signature_bind_positional_only(self):
3209 P = inspect.Parameter
3210
3211 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3212 return a_po, b_po, c_po, foo, bar, kwargs
3213
3214 sig = inspect.signature(test)
3215 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3216 for name in ('a_po', 'b_po', 'c_po'):
3217 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3218 new_sig = sig.replace(parameters=new_params.values())
3219 test.__signature__ = new_sig
3220
3221 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3222 (1, 2, 4, 5, 6, {}))
3223
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003224 self.assertEqual(self.call(test, 1, 2),
3225 (1, 2, 3, 42, 50, {}))
3226
3227 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3228 (1, 2, 3, 4, 5, {}))
3229
3230 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3231 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3232
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003233 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003234 self.call(test, 1, 2, c_po=4)
3235
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003236 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003237 self.call(test, a_po=1, b_po=2)
3238
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003239 def test_signature_bind_with_self_arg(self):
3240 # Issue #17071: one of the parameters is named "self
3241 def test(a, self, b):
3242 pass
3243 sig = inspect.signature(test)
3244 ba = sig.bind(1, 2, 3)
3245 self.assertEqual(ba.args, (1, 2, 3))
3246 ba = sig.bind(1, self=2, b=3)
3247 self.assertEqual(ba.args, (1, 2, 3))
3248
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003249 def test_signature_bind_vararg_name(self):
3250 def test(a, *args):
3251 return a, args
3252 sig = inspect.signature(test)
3253
Yury Selivanov86872752015-05-19 00:27:49 -04003254 with self.assertRaisesRegex(
3255 TypeError, "got an unexpected keyword argument 'args'"):
3256
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003257 sig.bind(a=0, args=1)
3258
3259 def test(*args, **kwargs):
3260 return args, kwargs
3261 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3262
3263 sig = inspect.signature(test)
3264 ba = sig.bind(args=1)
3265 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3266
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003267 @cpython_only
3268 def test_signature_bind_implicit_arg(self):
3269 # Issue #19611: getcallargs should work with set comprehensions
3270 def make_set():
3271 return {z * z for z in range(5)}
3272 setcomp_code = make_set.__code__.co_consts[1]
3273 setcomp_func = types.FunctionType(setcomp_code, {})
3274
3275 iterator = iter(range(5))
3276 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3277
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003278
3279class TestBoundArguments(unittest.TestCase):
3280 def test_signature_bound_arguments_unhashable(self):
3281 def foo(a): pass
3282 ba = inspect.signature(foo).bind(1)
3283
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003284 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003285 hash(ba)
3286
3287 def test_signature_bound_arguments_equality(self):
3288 def foo(a): pass
3289 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003290 self.assertTrue(ba == ba)
3291 self.assertFalse(ba != ba)
3292 self.assertTrue(ba == EqualsToAll())
3293 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003294
3295 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003296 self.assertTrue(ba == ba2)
3297 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003298
3299 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003300 self.assertFalse(ba == ba3)
3301 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003302 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003303 self.assertTrue(ba == ba3)
3304 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003305
3306 def bar(b): pass
3307 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003308 self.assertFalse(ba == ba4)
3309 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003310
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003311 def foo(*, a, b): pass
3312 sig = inspect.signature(foo)
3313 ba1 = sig.bind(a=1, b=2)
3314 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003315 self.assertTrue(ba1 == ba2)
3316 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003317
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003318 def test_signature_bound_arguments_pickle(self):
3319 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3320 sig = inspect.signature(foo)
3321 ba = sig.bind(20, 30, z={})
3322
3323 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3324 with self.subTest(pickle_ver=ver):
3325 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3326 self.assertEqual(ba, ba_pickled)
3327
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003328 def test_signature_bound_arguments_repr(self):
3329 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3330 sig = inspect.signature(foo)
3331 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003332 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003333
Yury Selivanovb907a512015-05-16 13:45:09 -04003334 def test_signature_bound_arguments_apply_defaults(self):
3335 def foo(a, b=1, *args, c:1={}, **kw): pass
3336 sig = inspect.signature(foo)
3337
3338 ba = sig.bind(20)
3339 ba.apply_defaults()
3340 self.assertEqual(
3341 list(ba.arguments.items()),
3342 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3343
3344 # Make sure that we preserve the order:
3345 # i.e. 'c' should be *before* 'kw'.
3346 ba = sig.bind(10, 20, 30, d=1)
3347 ba.apply_defaults()
3348 self.assertEqual(
3349 list(ba.arguments.items()),
3350 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3351
3352 # Make sure that BoundArguments produced by bind_partial()
3353 # are supported.
3354 def foo(a, b): pass
3355 sig = inspect.signature(foo)
3356 ba = sig.bind_partial(20)
3357 ba.apply_defaults()
3358 self.assertEqual(
3359 list(ba.arguments.items()),
3360 [('a', 20)])
3361
3362 # Test no args
3363 def foo(): pass
3364 sig = inspect.signature(foo)
3365 ba = sig.bind()
3366 ba.apply_defaults()
3367 self.assertEqual(list(ba.arguments.items()), [])
3368
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003369 # Make sure a no-args binding still acquires proper defaults.
3370 def foo(a='spam'): pass
3371 sig = inspect.signature(foo)
3372 ba = sig.bind()
3373 ba.apply_defaults()
3374 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3375
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003376
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003377class TestSignaturePrivateHelpers(unittest.TestCase):
3378 def test_signature_get_bound_param(self):
3379 getter = inspect._signature_get_bound_param
3380
3381 self.assertEqual(getter('($self)'), 'self')
3382 self.assertEqual(getter('($self, obj)'), 'self')
3383 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3384
Larry Hastings2623c8c2014-02-08 22:15:29 -08003385 def _strip_non_python_syntax(self, input,
3386 clean_signature, self_parameter, last_positional_only):
3387 computed_clean_signature, \
3388 computed_self_parameter, \
3389 computed_last_positional_only = \
3390 inspect._signature_strip_non_python_syntax(input)
3391 self.assertEqual(computed_clean_signature, clean_signature)
3392 self.assertEqual(computed_self_parameter, self_parameter)
3393 self.assertEqual(computed_last_positional_only, last_positional_only)
3394
3395 def test_signature_strip_non_python_syntax(self):
3396 self._strip_non_python_syntax(
3397 "($module, /, path, mode, *, dir_fd=None, " +
3398 "effective_ids=False,\n follow_symlinks=True)",
3399 "(module, path, mode, *, dir_fd=None, " +
3400 "effective_ids=False, follow_symlinks=True)",
3401 0,
3402 0)
3403
3404 self._strip_non_python_syntax(
3405 "($module, word, salt, /)",
3406 "(module, word, salt)",
3407 0,
3408 2)
3409
3410 self._strip_non_python_syntax(
3411 "(x, y=None, z=None, /)",
3412 "(x, y=None, z=None)",
3413 None,
3414 2)
3415
3416 self._strip_non_python_syntax(
3417 "(x, y=None, z=None)",
3418 "(x, y=None, z=None)",
3419 None,
3420 None)
3421
3422 self._strip_non_python_syntax(
3423 "(x,\n y=None,\n z = None )",
3424 "(x, y=None, z=None)",
3425 None,
3426 None)
3427
3428 self._strip_non_python_syntax(
3429 "",
3430 "",
3431 None,
3432 None)
3433
3434 self._strip_non_python_syntax(
3435 None,
3436 None,
3437 None,
3438 None)
3439
Nick Coghlan9c680b02015-04-13 12:54:54 -04003440class TestSignatureDefinitions(unittest.TestCase):
3441 # This test case provides a home for checking that particular APIs
3442 # have signatures available for introspection
3443
3444 @cpython_only
3445 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3446 "Signature information for builtins requires docstrings")
3447 def test_builtins_have_signatures(self):
3448 # This checks all builtin callables in CPython have signatures
3449 # A few have signatures Signature can't yet handle, so we skip those
3450 # since they will have to wait until PEP 457 adds the required
3451 # introspection support to the inspect module
3452 # Some others also haven't been converted yet for various other
3453 # reasons, so we also skip those for the time being, but design
3454 # the test to fail in order to indicate when it needs to be
3455 # updated.
3456 no_signature = set()
3457 # These need PEP 457 groups
3458 needs_groups = {"range", "slice", "dir", "getattr",
3459 "next", "iter", "vars"}
3460 no_signature |= needs_groups
3461 # These need PEP 457 groups or a signature change to accept None
3462 needs_semantic_update = {"round"}
3463 no_signature |= needs_semantic_update
3464 # These need *args support in Argument Clinic
3465 needs_varargs = {"min", "max", "print", "__build_class__"}
3466 no_signature |= needs_varargs
3467 # These simply weren't covered in the initial AC conversion
3468 # for builtin callables
3469 not_converted_yet = {"open", "__import__"}
3470 no_signature |= not_converted_yet
3471 # These builtin types are expected to provide introspection info
3472 types_with_signatures = set()
3473 # Check the signatures we expect to be there
3474 ns = vars(builtins)
3475 for name, obj in sorted(ns.items()):
3476 if not callable(obj):
3477 continue
3478 # The builtin types haven't been converted to AC yet
3479 if isinstance(obj, type) and (name not in types_with_signatures):
3480 # Note that this also skips all the exception types
3481 no_signature.add(name)
3482 if (name in no_signature):
3483 # Not yet converted
3484 continue
3485 with self.subTest(builtin=name):
3486 self.assertIsNotNone(inspect.signature(obj))
3487 # Check callables that haven't been converted don't claim a signature
3488 # This ensures this test will start failing as more signatures are
3489 # added, so the affected items can be moved into the scope of the
3490 # regression test above
3491 for name in no_signature:
3492 with self.subTest(builtin=name):
3493 self.assertIsNone(obj.__text_signature__)
3494
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003495
Nick Coghlane8c45d62013-07-28 20:00:01 +10003496class TestUnwrap(unittest.TestCase):
3497
3498 def test_unwrap_one(self):
3499 def func(a, b):
3500 return a + b
3501 wrapper = functools.lru_cache(maxsize=20)(func)
3502 self.assertIs(inspect.unwrap(wrapper), func)
3503
3504 def test_unwrap_several(self):
3505 def func(a, b):
3506 return a + b
3507 wrapper = func
3508 for __ in range(10):
3509 @functools.wraps(wrapper)
3510 def wrapper():
3511 pass
3512 self.assertIsNot(wrapper.__wrapped__, func)
3513 self.assertIs(inspect.unwrap(wrapper), func)
3514
3515 def test_stop(self):
3516 def func1(a, b):
3517 return a + b
3518 @functools.wraps(func1)
3519 def func2():
3520 pass
3521 @functools.wraps(func2)
3522 def wrapper():
3523 pass
3524 func2.stop_here = 1
3525 unwrapped = inspect.unwrap(wrapper,
3526 stop=(lambda f: hasattr(f, "stop_here")))
3527 self.assertIs(unwrapped, func2)
3528
3529 def test_cycle(self):
3530 def func1(): pass
3531 func1.__wrapped__ = func1
3532 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3533 inspect.unwrap(func1)
3534
3535 def func2(): pass
3536 func2.__wrapped__ = func1
3537 func1.__wrapped__ = func2
3538 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3539 inspect.unwrap(func1)
3540 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3541 inspect.unwrap(func2)
3542
3543 def test_unhashable(self):
3544 def func(): pass
3545 func.__wrapped__ = None
3546 class C:
3547 __hash__ = None
3548 __wrapped__ = func
3549 self.assertIsNone(inspect.unwrap(C()))
3550
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003551class TestMain(unittest.TestCase):
3552 def test_only_source(self):
3553 module = importlib.import_module('unittest')
3554 rc, out, err = assert_python_ok('-m', 'inspect',
3555 'unittest')
3556 lines = out.decode().splitlines()
3557 # ignore the final newline
3558 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3559 self.assertEqual(err, b'')
3560
Yury Selivanov42407ab2014-06-23 10:23:50 -07003561 def test_custom_getattr(self):
3562 def foo():
3563 pass
3564 foo.__signature__ = 42
3565 with self.assertRaises(TypeError):
3566 inspect.signature(foo)
3567
Brett Cannon634a8fc2013-10-02 10:25:42 -04003568 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003569 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003570 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003571 rc, out, err = assert_python_ok('-m', 'inspect',
3572 'concurrent.futures:ThreadPoolExecutor')
3573 lines = out.decode().splitlines()
3574 # ignore the final newline
3575 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003576 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003577 self.assertEqual(err, b'')
3578
3579 def test_builtins(self):
3580 module = importlib.import_module('unittest')
3581 _, out, err = assert_python_failure('-m', 'inspect',
3582 'sys')
3583 lines = err.decode().splitlines()
3584 self.assertEqual(lines, ["Can't get info for builtin modules."])
3585
3586 def test_details(self):
3587 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003588 args = support.optim_args_from_interpreter_flags()
3589 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003590 'unittest', '--details')
3591 output = out.decode()
3592 # Just a quick sanity check on the output
3593 self.assertIn(module.__name__, output)
3594 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003595 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003596 self.assertEqual(err, b'')
3597
3598
Yury Selivanovef1e7502014-12-08 16:05:34 -05003599class TestReload(unittest.TestCase):
3600
3601 src_before = textwrap.dedent("""\
3602def foo():
3603 print("Bla")
3604 """)
3605
3606 src_after = textwrap.dedent("""\
3607def foo():
3608 print("Oh no!")
3609 """)
3610
3611 def assertInspectEqual(self, path, source):
3612 inspected_src = inspect.getsource(source)
3613 with open(path) as src:
3614 self.assertEqual(
3615 src.read().splitlines(True),
3616 inspected_src.splitlines(True)
3617 )
3618
3619 def test_getsource_reload(self):
3620 # see issue 1218234
3621 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3622 module = importlib.import_module(name)
3623 self.assertInspectEqual(path, module)
3624 with open(path, 'w') as src:
3625 src.write(self.src_after)
3626 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003627
Nick Coghlane8c45d62013-07-28 20:00:01 +10003628
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003629def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003630 run_unittest(
3631 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3632 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3633 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003634 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003635 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003636 TestBoundArguments, TestSignaturePrivateHelpers,
3637 TestSignatureDefinitions,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003638 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
3639 TestGetCoroutineState
Michael Foord95fc51d2010-11-20 15:07:30 +00003640 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003641
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003642if __name__ == "__main__":
3643 test_main()