blob: cfea281c70db11a92dd700d7bc4d16190c11ba87 [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')
Berker Peksag948171b2017-03-17 14:59:16 +0300390 # If the object source file is not available, return None.
391 co = compile('x=1', '_non_existing_filename.py', 'exec')
392 self.assertIsNone(inspect.getcomments(co))
393 # If the object has been defined in C, return None.
394 self.assertIsNone(inspect.getcomments(list))
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000395
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000396 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000397 # Check actual module
398 self.assertEqual(inspect.getmodule(mod), mod)
399 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000400 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000401 # Check a method (no __module__ attribute, falls back to filename)
402 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
403 # Do it again (check the caching isn't broken)
404 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
405 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000406 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000407 # Check filename override
408 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000409
Berker Peksagff0e3b72017-01-02 06:57:43 +0300410 def test_getframeinfo_get_first_line(self):
411 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
412 self.assertEqual(frame_info.code_context[0], "# line 1\n")
413 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
414
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000415 def test_getsource(self):
416 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200417 self.assertSourceEqual(mod.StupidGit, 21, 51)
418 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000419
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000420 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000421 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
422 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000423 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100424 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000425 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000426 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200427 try:
428 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
429 finally:
430 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000431
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000432 def test_getfile(self):
433 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000434
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500435 def test_getfile_class_without_module(self):
436 class CM(type):
437 @property
438 def __module__(cls):
439 raise AttributeError
440 class C(metaclass=CM):
441 pass
442 with self.assertRaises(TypeError):
443 inspect.getfile(C)
444
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000445 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000446 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000447 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000448 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000449 m.__file__ = "<string>" # hopefully not a real filename...
450 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000451 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000452 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000453 del sys.modules[name]
454 inspect.getmodule(compile('a=10','','single'))
455
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500456 def test_proceed_with_fake_filename(self):
457 '''doctest monkeypatches linecache to enable inspection'''
458 fn, source = '<test>', 'def x(): pass\n'
459 getlines = linecache.getlines
460 def monkey(filename, module_globals=None):
461 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300462 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500463 else:
464 return getlines(filename, module_globals)
465 linecache.getlines = monkey
466 try:
467 ns = {}
468 exec(compile(source, fn, 'single'), ns)
469 inspect.getsource(ns["x"])
470 finally:
471 linecache.getlines = getlines
472
Antoine Pitroua8723a02015-04-15 00:41:29 +0200473 def test_getsource_on_code_object(self):
474 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
475
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000476class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000477 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000478
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000479 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000480 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000481
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000482 def test_replacing_decorator(self):
483 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000484
Yury Selivanov081bbf62014-09-26 17:34:54 -0400485 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200486 self.assertSourceEqual(mod2.real, 130, 132)
487
488 def test_decorator_with_lambda(self):
489 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400490
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000491class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000492 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000493 def test_oneline_lambda(self):
494 # Test inspect.getsource with a one-line lambda function.
495 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000496
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000497 def test_threeline_lambda(self):
498 # Test inspect.getsource with a three-line lambda function,
499 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000500 self.assertSourceEqual(mod2.tll, 28, 30)
501
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000502 def test_twoline_indented_lambda(self):
503 # Test inspect.getsource with a two-line lambda function,
504 # where the second line _is_ indented.
505 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000506
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000507 def test_onelinefunc(self):
508 # Test inspect.getsource with a regular one-line function.
509 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000510
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000511 def test_manyargs(self):
512 # Test inspect.getsource with a regular function where
513 # the arguments are on two lines and _not_ indented and
514 # the body on the second line with the last arguments.
515 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000516
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000517 def test_twolinefunc(self):
518 # Test inspect.getsource with a regular function where
519 # the body is on two lines, following the argument list and
520 # continued on the next line by a \\.
521 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000522
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000523 def test_lambda_in_list(self):
524 # Test inspect.getsource with a one-line lambda function
525 # defined in a list, indented.
526 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000527
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000528 def test_anonymous(self):
529 # Test inspect.getsource with a lambda function defined
530 # as argument to another function.
531 self.assertSourceEqual(mod2.anonymous, 55, 55)
532
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000533class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000534 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000535
536 def test_with_comment(self):
537 self.assertSourceEqual(mod2.with_comment, 58, 59)
538
539 def test_multiline_sig(self):
540 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
541
Armin Rigodd5c0232005-09-25 11:45:45 +0000542 def test_nested_class(self):
543 self.assertSourceEqual(mod2.func69().func71, 71, 72)
544
545 def test_one_liner_followed_by_non_name(self):
546 self.assertSourceEqual(mod2.func77, 77, 77)
547
548 def test_one_liner_dedent_non_name(self):
549 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
550
551 def test_with_comment_instead_of_docstring(self):
552 self.assertSourceEqual(mod2.func88, 88, 90)
553
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000554 def test_method_in_dynamic_class(self):
555 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
556
R David Murray32562d72014-10-03 11:15:38 -0400557 # This should not skip for CPython, but might on a repackaged python where
558 # unicodedata is not an external module, or on pypy.
559 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
560 unicodedata.__file__.endswith('.py'),
561 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000562 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200563 self.assertRaises(OSError, inspect.getsource, unicodedata)
564 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000565
R. David Murraya1b37402010-06-17 02:04:29 +0000566 def test_findsource_code_in_linecache(self):
567 lines = ["x=1"]
568 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200569 self.assertRaises(OSError, inspect.findsource, co)
570 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000571 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200572 try:
573 self.assertEqual(inspect.findsource(co), (lines,0))
574 self.assertEqual(inspect.getsource(co), lines[0])
575 finally:
576 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000577
Ezio Melotti1b145922013-03-30 05:17:24 +0200578 def test_findsource_without_filename(self):
579 for fname in ['', '<string>']:
580 co = compile('x=1', fname, "exec")
581 self.assertRaises(IOError, inspect.findsource, co)
582 self.assertRaises(IOError, inspect.getsource, co)
583
Antoine Pitroua8723a02015-04-15 00:41:29 +0200584 def test_getsource_on_method(self):
585 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
586
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300587 def test_nested_func(self):
588 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
589
590
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000591class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400592 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000593 self.tempdir = TESTFN + '_dir'
594 os.mkdir(self.tempdir)
595 with open(os.path.join(self.tempdir,
596 'inspect_fodder3%spy' % os.extsep), 'w') as f:
597 f.write("class X:\n pass # No EOL")
598 with DirsOnSysPath(self.tempdir):
599 import inspect_fodder3 as mod3
600 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400601 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000602
603 def tearDown(self):
604 shutil.rmtree(self.tempdir)
605
606 def test_class(self):
607 self.assertSourceEqual(self.fodderModule.X, 1, 2)
608
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100609
610class _BrokenDataDescriptor(object):
611 """
612 A broken data descriptor. See bug #1785.
613 """
614 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700615 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100616
617 def __set__(*args):
618 raise RuntimeError
619
620 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700621 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100622
623
624class _BrokenMethodDescriptor(object):
625 """
626 A broken method descriptor. See bug #1785.
627 """
628 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700629 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100630
631 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700632 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100633
634
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000635# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000636def attrs_wo_objs(cls):
637 return [t[:3] for t in inspect.classify_class_attrs(cls)]
638
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100639
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000640class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000641 def test_newstyle_mro(self):
642 # The same w/ new-class MRO.
643 class A(object): pass
644 class B(A): pass
645 class C(A): pass
646 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000647
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000648 expected = (D, B, C, A, object)
649 got = inspect.getmro(D)
650 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000651
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500652 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
653 varkw_e=None, defaults_e=None, formatted=None):
654 with self.assertWarns(DeprecationWarning):
655 args, varargs, varkw, defaults = inspect.getargspec(routine)
656 self.assertEqual(args, args_e)
657 self.assertEqual(varargs, varargs_e)
658 self.assertEqual(varkw, varkw_e)
659 self.assertEqual(defaults, defaults_e)
660 if formatted is not None:
661 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
662 formatted)
663
Christian Heimes3795b532007-11-08 13:48:53 +0000664 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
665 varkw_e=None, defaults_e=None,
666 kwonlyargs_e=[], kwonlydefaults_e=None,
667 ann_e={}, formatted=None):
668 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
669 inspect.getfullargspec(routine)
670 self.assertEqual(args, args_e)
671 self.assertEqual(varargs, varargs_e)
672 self.assertEqual(varkw, varkw_e)
673 self.assertEqual(defaults, defaults_e)
674 self.assertEqual(kwonlyargs, kwonlyargs_e)
675 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
676 self.assertEqual(ann, ann_e)
677 if formatted is not None:
678 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
679 kwonlyargs, kwonlydefaults, ann),
680 formatted)
681
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500682 def test_getargspec(self):
683 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
684
685 self.assertArgSpecEquals(mod.spam,
686 ['a', 'b', 'c', 'd', 'e', 'f'],
687 'g', 'h', (3, 4, 5),
688 '(a, b, c, d=3, e=4, f=5, *g, **h)')
689
690 self.assertRaises(ValueError, self.assertArgSpecEquals,
691 mod2.keyworded, [])
692
693 self.assertRaises(ValueError, self.assertArgSpecEquals,
694 mod2.annotated, [])
695 self.assertRaises(ValueError, self.assertArgSpecEquals,
696 mod2.keyword_only_arg, [])
697
698
Christian Heimes3795b532007-11-08 13:48:53 +0000699 def test_getfullargspec(self):
700 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
701 kwonlyargs_e=['arg2'],
702 kwonlydefaults_e={'arg2':1},
703 formatted='(*arg1, arg2=1)')
704
705 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000706 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000707 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000708 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
709 kwonlyargs_e=['arg'],
710 formatted='(*, arg)')
711
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500712 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500713 # Issue 20684: low level introspection API must ignore __wrapped__
714 @functools.wraps(mod.spam)
715 def ham(x, y):
716 pass
717 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500718 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500719 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
720 self.assertFullArgSpecEquals(functools.partial(ham),
721 ['x', 'y'], formatted='(x, y)')
722 # Other variants
723 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500724 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
725 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500726 class C:
727 @functools.wraps(mod.spam)
728 def ham(self, x, y):
729 pass
730 pham = functools.partialmethod(ham)
731 @functools.wraps(mod.spam)
732 def __call__(self, x, y):
733 pass
734 check_method(C())
735 check_method(C.ham)
736 check_method(C().ham)
737 check_method(C.pham)
738 check_method(C().pham)
739
740 class C_new:
741 @functools.wraps(mod.spam)
742 def __new__(self, x, y):
743 pass
744 check_method(C_new)
745
746 class C_init:
747 @functools.wraps(mod.spam)
748 def __init__(self, x, y):
749 pass
750 check_method(C_init)
751
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500752 def test_getfullargspec_signature_attr(self):
753 def test():
754 pass
755 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
756 test.__signature__ = inspect.Signature(parameters=(spam_param,))
757
758 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
759
Yury Selivanov4cb93912014-01-29 11:54:12 -0500760 def test_getfullargspec_signature_annos(self):
761 def test(a:'spam') -> 'ham': pass
762 spec = inspect.getfullargspec(test)
763 self.assertEqual(test.__annotations__, spec.annotations)
764
765 def test(): pass
766 spec = inspect.getfullargspec(test)
767 self.assertEqual(test.__annotations__, spec.annotations)
768
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500769 @unittest.skipIf(MISSING_C_DOCSTRINGS,
770 "Signature information for builtins requires docstrings")
771 def test_getfullargspec_builtin_methods(self):
772 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
773 args_e=['self', 'obj'], formatted='(self, obj)')
774
775 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
776 args_e=['self', 'obj'], formatted='(self, obj)')
777
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500778 self.assertFullArgSpecEquals(
779 os.stat,
780 args_e=['path'],
781 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
782 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
783 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
784
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200785 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500786 @unittest.skipIf(MISSING_C_DOCSTRINGS,
787 "Signature information for builtins requires docstrings")
788 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200789 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500790 builtin = _testcapi.docstring_with_signature_with_defaults
791 spec = inspect.getfullargspec(builtin)
792 self.assertEqual(spec.defaults[0], 'avocado')
793
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200794 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500795 @unittest.skipIf(MISSING_C_DOCSTRINGS,
796 "Signature information for builtins requires docstrings")
797 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200798 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500799 builtin = _testcapi.docstring_no_signature
800 with self.assertRaises(TypeError):
801 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000802
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500803 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000804 class A(object):
805 def m(self):
806 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500807 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000808
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000809 def test_classify_newstyle(self):
810 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000811
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000812 def s(): pass
813 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000814
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000815 def c(cls): pass
816 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000817
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000818 def getp(self): pass
819 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000820
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000821 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000822
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000823 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000824
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000825 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000826
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100827 dd = _BrokenDataDescriptor()
828 md = _BrokenMethodDescriptor()
829
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000830 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500831
832 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
833 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
834
Benjamin Peterson577473f2010-01-19 00:09:57 +0000835 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
836 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
837 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000838 self.assertIn(('m', 'method', A), attrs,
839 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000840 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
841 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100842 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
843 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000844
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000845 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000846
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000847 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000848
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000849 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000850 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
851 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
852 self.assertIn(('p', 'property', A), attrs, 'missing property')
853 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
854 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
855 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100856 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
857 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000858
859
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000860 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000861
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000862 def m(self): pass
863 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000864
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000865 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000866 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
867 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
868 self.assertIn(('p', 'property', A), attrs, 'missing property')
869 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
870 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
871 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100872 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
873 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000874
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000875 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000876
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000877 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000878
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000879 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000880 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
881 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
882 self.assertIn(('p', 'property', A), attrs, 'missing property')
883 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
884 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
885 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100886 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
887 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
888
889 def test_classify_builtin_types(self):
890 # Simple sanity check that all built-in types can have their
891 # attributes classified.
892 for name in dir(__builtins__):
893 builtin = getattr(__builtins__, name)
894 if isinstance(builtin, type):
895 inspect.classify_class_attrs(builtin)
896
Ethan Furman63c141c2013-10-18 00:27:39 -0700897 def test_classify_DynamicClassAttribute(self):
898 class Meta(type):
899 def __getattr__(self, name):
900 if name == 'ham':
901 return 'spam'
902 return super().__getattr__(name)
903 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700904 @types.DynamicClassAttribute
905 def ham(self):
906 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700907 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
908 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700909 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700910 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
911
Yury Selivanovbf341fb2015-05-21 15:41:57 -0400912 def test_classify_overrides_bool(self):
913 class NoBool(object):
914 def __eq__(self, other):
915 return NoBool()
916
917 def __bool__(self):
918 raise NotImplementedError(
919 "This object does not specify a boolean value")
920
921 class HasNB(object):
922 dd = NoBool()
923
924 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
925 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
926
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700927 def test_classify_metaclass_class_attribute(self):
928 class Meta(type):
929 fish = 'slap'
930 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200931 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700932 class Class(metaclass=Meta):
933 pass
934 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
935 self.assertIn(should_find, inspect.classify_class_attrs(Class))
936
Ethan Furman63c141c2013-10-18 00:27:39 -0700937 def test_classify_VirtualAttribute(self):
938 class Meta(type):
939 def __dir__(cls):
940 return ['__class__', '__module__', '__name__', 'BOOM']
941 def __getattr__(self, name):
942 if name =='BOOM':
943 return 42
944 return super().__getattr(name)
945 class Class(metaclass=Meta):
946 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700947 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700948 self.assertIn(should_find, inspect.classify_class_attrs(Class))
949
950 def test_classify_VirtualAttribute_multi_classes(self):
951 class Meta1(type):
952 def __dir__(cls):
953 return ['__class__', '__module__', '__name__', 'one']
954 def __getattr__(self, name):
955 if name =='one':
956 return 1
957 return super().__getattr__(name)
958 class Meta2(type):
959 def __dir__(cls):
960 return ['__class__', '__module__', '__name__', 'two']
961 def __getattr__(self, name):
962 if name =='two':
963 return 2
964 return super().__getattr__(name)
965 class Meta3(Meta1, Meta2):
966 def __dir__(cls):
967 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
968 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
969 def __getattr__(self, name):
970 if name =='three':
971 return 3
972 return super().__getattr__(name)
973 class Class1(metaclass=Meta1):
974 pass
975 class Class2(Class1, metaclass=Meta3):
976 pass
977
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700978 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
979 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
980 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700981 cca = inspect.classify_class_attrs(Class2)
982 for sf in (should_find1, should_find2, should_find3):
983 self.assertIn(sf, cca)
984
985 def test_classify_class_attrs_with_buggy_dir(self):
986 class M(type):
987 def __dir__(cls):
988 return ['__class__', '__name__', 'missing']
989 class C(metaclass=M):
990 pass
991 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
992 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700993
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100994 def test_getmembers_descriptors(self):
995 class A(object):
996 dd = _BrokenDataDescriptor()
997 md = _BrokenMethodDescriptor()
998
999 def pred_wrapper(pred):
1000 # A quick'n'dirty way to discard standard attributes of new-style
1001 # classes.
1002 class Empty(object):
1003 pass
1004 def wrapped(x):
1005 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1006 return False
1007 return pred(x)
1008 return wrapped
1009
1010 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1011 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1012
1013 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1014 [('md', A.__dict__['md'])])
1015 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1016 [('dd', A.__dict__['dd'])])
1017
1018 class B(A):
1019 pass
1020
1021 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1022 [('md', A.__dict__['md'])])
1023 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1024 [('dd', A.__dict__['dd'])])
1025
Antoine Pitrou0c603812012-01-18 17:40:18 +01001026 def test_getmembers_method(self):
1027 class B:
1028 def f(self):
1029 pass
1030
1031 self.assertIn(('f', B.f), inspect.getmembers(B))
1032 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1033 b = B()
1034 self.assertIn(('f', b.f), inspect.getmembers(b))
1035 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1036
Ethan Furmane03ea372013-09-25 07:14:41 -07001037 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001038 class M(type):
1039 def __getattr__(cls, name):
1040 if name == 'eggs':
1041 return 'scrambled'
1042 return super().__getattr__(name)
1043 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001044 @types.DynamicClassAttribute
1045 def eggs(self):
1046 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001047 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1048 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1049
1050 def test_getmembers_with_buggy_dir(self):
1051 class M(type):
1052 def __dir__(cls):
1053 return ['__class__', '__name__', 'missing']
1054 class C(metaclass=M):
1055 pass
1056 attrs = [a[0] for a in inspect.getmembers(C)]
1057 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001058
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001059
Nick Coghlan2f92e542012-06-23 19:39:55 +10001060_global_ref = object()
1061class TestGetClosureVars(unittest.TestCase):
1062
1063 def test_name_resolution(self):
1064 # Basic test of the 4 different resolution mechanisms
1065 def f(nonlocal_ref):
1066 def g(local_ref):
1067 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1068 return g
1069 _arg = object()
1070 nonlocal_vars = {"nonlocal_ref": _arg}
1071 global_vars = {"_global_ref": _global_ref}
1072 builtin_vars = {"print": print}
1073 unbound_names = {"unbound_ref"}
1074 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1075 builtin_vars, unbound_names)
1076 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1077
1078 def test_generator_closure(self):
1079 def f(nonlocal_ref):
1080 def g(local_ref):
1081 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1082 yield
1083 return g
1084 _arg = object()
1085 nonlocal_vars = {"nonlocal_ref": _arg}
1086 global_vars = {"_global_ref": _global_ref}
1087 builtin_vars = {"print": print}
1088 unbound_names = {"unbound_ref"}
1089 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1090 builtin_vars, unbound_names)
1091 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1092
1093 def test_method_closure(self):
1094 class C:
1095 def f(self, nonlocal_ref):
1096 def g(local_ref):
1097 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1098 return g
1099 _arg = object()
1100 nonlocal_vars = {"nonlocal_ref": _arg}
1101 global_vars = {"_global_ref": _global_ref}
1102 builtin_vars = {"print": print}
1103 unbound_names = {"unbound_ref"}
1104 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1105 builtin_vars, unbound_names)
1106 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1107
1108 def test_nonlocal_vars(self):
1109 # More complex tests of nonlocal resolution
1110 def _nonlocal_vars(f):
1111 return inspect.getclosurevars(f).nonlocals
1112
1113 def make_adder(x):
1114 def add(y):
1115 return x + y
1116 return add
1117
1118 def curry(func, arg1):
1119 return lambda arg2: func(arg1, arg2)
1120
1121 def less_than(a, b):
1122 return a < b
1123
1124 # The infamous Y combinator.
1125 def Y(le):
1126 def g(f):
1127 return le(lambda x: f(f)(x))
1128 Y.g_ref = g
1129 return g(g)
1130
1131 def check_y_combinator(func):
1132 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1133
1134 inc = make_adder(1)
1135 add_two = make_adder(2)
1136 greater_than_five = curry(less_than, 5)
1137
1138 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1139 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1140 self.assertEqual(_nonlocal_vars(greater_than_five),
1141 {'arg1': 5, 'func': less_than})
1142 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1143 {'x': 3})
1144 Y(check_y_combinator)
1145
1146 def test_getclosurevars_empty(self):
1147 def foo(): pass
1148 _empty = inspect.ClosureVars({}, {}, {}, set())
1149 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1150 self.assertEqual(inspect.getclosurevars(foo), _empty)
1151
1152 def test_getclosurevars_error(self):
1153 class T: pass
1154 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1155 self.assertRaises(TypeError, inspect.getclosurevars, list)
1156 self.assertRaises(TypeError, inspect.getclosurevars, {})
1157
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001158 def _private_globals(self):
1159 code = """def f(): print(path)"""
1160 ns = {}
1161 exec(code, ns)
1162 return ns["f"], ns
1163
1164 def test_builtins_fallback(self):
1165 f, ns = self._private_globals()
1166 ns.pop("__builtins__", None)
1167 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1168 self.assertEqual(inspect.getclosurevars(f), expected)
1169
1170 def test_builtins_as_dict(self):
1171 f, ns = self._private_globals()
1172 ns["__builtins__"] = {"path":1}
1173 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1174 self.assertEqual(inspect.getclosurevars(f), expected)
1175
1176 def test_builtins_as_module(self):
1177 f, ns = self._private_globals()
1178 ns["__builtins__"] = os
1179 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1180 self.assertEqual(inspect.getclosurevars(f), expected)
1181
Nick Coghlan2f92e542012-06-23 19:39:55 +10001182
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001183class TestGetcallargsFunctions(unittest.TestCase):
1184
1185 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1186 locs = dict(locs or {}, func=func)
1187 r1 = eval('func(%s)' % call_params_string, None, locs)
1188 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1189 locs)
1190 self.assertEqual(r1, r2)
1191
1192 def assertEqualException(self, func, call_param_string, locs=None):
1193 locs = dict(locs or {}, func=func)
1194 try:
1195 eval('func(%s)' % call_param_string, None, locs)
1196 except Exception as e:
1197 ex1 = e
1198 else:
1199 self.fail('Exception not raised')
1200 try:
1201 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1202 locs)
1203 except Exception as e:
1204 ex2 = e
1205 else:
1206 self.fail('Exception not raised')
1207 self.assertIs(type(ex1), type(ex2))
1208 self.assertEqual(str(ex1), str(ex2))
1209 del ex1, ex2
1210
1211 def makeCallable(self, signature):
1212 """Create a function that returns its locals()"""
1213 code = "lambda %s: locals()"
1214 return eval(code % signature)
1215
1216 def test_plain(self):
1217 f = self.makeCallable('a, b=1')
1218 self.assertEqualCallArgs(f, '2')
1219 self.assertEqualCallArgs(f, '2, 3')
1220 self.assertEqualCallArgs(f, 'a=2')
1221 self.assertEqualCallArgs(f, 'b=3, a=2')
1222 self.assertEqualCallArgs(f, '2, b=3')
1223 # expand *iterable / **mapping
1224 self.assertEqualCallArgs(f, '*(2,)')
1225 self.assertEqualCallArgs(f, '*[2]')
1226 self.assertEqualCallArgs(f, '*(2, 3)')
1227 self.assertEqualCallArgs(f, '*[2, 3]')
1228 self.assertEqualCallArgs(f, '**{"a":2}')
1229 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1230 self.assertEqualCallArgs(f, '2, **{"b":3}')
1231 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1232 # expand UserList / UserDict
1233 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1234 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1235 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1236 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1237 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1238
1239 def test_varargs(self):
1240 f = self.makeCallable('a, b=1, *c')
1241 self.assertEqualCallArgs(f, '2')
1242 self.assertEqualCallArgs(f, '2, 3')
1243 self.assertEqualCallArgs(f, '2, 3, 4')
1244 self.assertEqualCallArgs(f, '*(2,3,4)')
1245 self.assertEqualCallArgs(f, '2, *[3,4]')
1246 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1247
1248 def test_varkw(self):
1249 f = self.makeCallable('a, b=1, **c')
1250 self.assertEqualCallArgs(f, 'a=2')
1251 self.assertEqualCallArgs(f, '2, b=3, c=4')
1252 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1253 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1254 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1255 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1256 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1257 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1258 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1259
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001260 def test_varkw_only(self):
1261 # issue11256:
1262 f = self.makeCallable('**c')
1263 self.assertEqualCallArgs(f, '')
1264 self.assertEqualCallArgs(f, 'a=1')
1265 self.assertEqualCallArgs(f, 'a=1, b=2')
1266 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1267 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1268 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1269
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001270 def test_keyword_only(self):
1271 f = self.makeCallable('a=3, *, c, d=2')
1272 self.assertEqualCallArgs(f, 'c=3')
1273 self.assertEqualCallArgs(f, 'c=3, a=3')
1274 self.assertEqualCallArgs(f, 'a=2, c=4')
1275 self.assertEqualCallArgs(f, '4, c=4')
1276 self.assertEqualException(f, '')
1277 self.assertEqualException(f, '3')
1278 self.assertEqualException(f, 'a=3')
1279 self.assertEqualException(f, 'd=4')
1280
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001281 f = self.makeCallable('*, c, d=2')
1282 self.assertEqualCallArgs(f, 'c=3')
1283 self.assertEqualCallArgs(f, 'c=3, d=4')
1284 self.assertEqualCallArgs(f, 'd=4, c=3')
1285
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001286 def test_multiple_features(self):
1287 f = self.makeCallable('a, b=2, *f, **g')
1288 self.assertEqualCallArgs(f, '2, 3, 7')
1289 self.assertEqualCallArgs(f, '2, 3, x=8')
1290 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1291 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1292 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1293 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1294 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1295 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1296 '(4,[5,6])]), **collections.UserDict('
1297 'y=9, z=10)')
1298
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001299 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1300 self.assertEqualCallArgs(f, '2, 3, x=8')
1301 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1302 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1303 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1304 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1305 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1306 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1307 '(4,[5,6])]), q=0, **collections.UserDict('
1308 'y=9, z=10)')
1309
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001310 def test_errors(self):
1311 f0 = self.makeCallable('')
1312 f1 = self.makeCallable('a, b')
1313 f2 = self.makeCallable('a, b=1')
1314 # f0 takes no arguments
1315 self.assertEqualException(f0, '1')
1316 self.assertEqualException(f0, 'x=1')
1317 self.assertEqualException(f0, '1,x=1')
1318 # f1 takes exactly 2 arguments
1319 self.assertEqualException(f1, '')
1320 self.assertEqualException(f1, '1')
1321 self.assertEqualException(f1, 'a=2')
1322 self.assertEqualException(f1, 'b=3')
1323 # f2 takes at least 1 argument
1324 self.assertEqualException(f2, '')
1325 self.assertEqualException(f2, 'b=3')
1326 for f in f1, f2:
1327 # f1/f2 takes exactly/at most 2 arguments
1328 self.assertEqualException(f, '2, 3, 4')
1329 self.assertEqualException(f, '1, 2, 3, a=1')
1330 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001331 # XXX: success of this one depends on dict order
1332 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001333 # f got an unexpected keyword argument
1334 self.assertEqualException(f, 'c=2')
1335 self.assertEqualException(f, '2, c=3')
1336 self.assertEqualException(f, '2, 3, c=4')
1337 self.assertEqualException(f, '2, c=4, b=3')
1338 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1339 # f got multiple values for keyword argument
1340 self.assertEqualException(f, '1, a=2')
1341 self.assertEqualException(f, '1, **{"a":2}')
1342 self.assertEqualException(f, '1, 2, b=3')
1343 # XXX: Python inconsistency
1344 # - for functions and bound methods: unexpected keyword 'c'
1345 # - for unbound methods: multiple values for keyword 'a'
1346 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001347 # issue11256:
1348 f3 = self.makeCallable('**c')
1349 self.assertEqualException(f3, '1, 2')
1350 self.assertEqualException(f3, '1, 2, a=1, b=2')
1351 f4 = self.makeCallable('*, a, b=0')
1352 self.assertEqualException(f3, '1, 2')
1353 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001354
Yury Selivanov875df202014-03-27 18:23:03 -04001355 # issue #20816: getcallargs() fails to iterate over non-existent
1356 # kwonlydefaults and raises a wrong TypeError
1357 def f5(*, a): pass
1358 with self.assertRaisesRegex(TypeError,
1359 'missing 1 required keyword-only'):
1360 inspect.getcallargs(f5)
1361
1362
Yury Selivanovdccfa132014-03-27 18:42:52 -04001363 # issue20817:
1364 def f6(a, b, c):
1365 pass
1366 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1367 inspect.getcallargs(f6)
1368
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001369class TestGetcallargsMethods(TestGetcallargsFunctions):
1370
1371 def setUp(self):
1372 class Foo(object):
1373 pass
1374 self.cls = Foo
1375 self.inst = Foo()
1376
1377 def makeCallable(self, signature):
1378 assert 'self' not in signature
1379 mk = super(TestGetcallargsMethods, self).makeCallable
1380 self.cls.method = mk('self, ' + signature)
1381 return self.inst.method
1382
1383class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1384
1385 def makeCallable(self, signature):
1386 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1387 return self.cls.method
1388
1389 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1390 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1391 *self._getAssertEqualParams(func, call_params_string, locs))
1392
1393 def assertEqualException(self, func, call_params_string, locs=None):
1394 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1395 *self._getAssertEqualParams(func, call_params_string, locs))
1396
1397 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1398 assert 'inst' not in call_params_string
1399 locs = dict(locs or {}, inst=self.inst)
1400 return (func, 'inst,' + call_params_string, locs)
1401
Michael Foord95fc51d2010-11-20 15:07:30 +00001402
1403class TestGetattrStatic(unittest.TestCase):
1404
1405 def test_basic(self):
1406 class Thing(object):
1407 x = object()
1408
1409 thing = Thing()
1410 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1411 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1412 with self.assertRaises(AttributeError):
1413 inspect.getattr_static(thing, 'y')
1414
1415 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1416
1417 def test_inherited(self):
1418 class Thing(object):
1419 x = object()
1420 class OtherThing(Thing):
1421 pass
1422
1423 something = OtherThing()
1424 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1425
1426 def test_instance_attr(self):
1427 class Thing(object):
1428 x = 2
1429 def __init__(self, x):
1430 self.x = x
1431 thing = Thing(3)
1432 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1433 del thing.x
1434 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1435
1436 def test_property(self):
1437 class Thing(object):
1438 @property
1439 def x(self):
1440 raise AttributeError("I'm pretending not to exist")
1441 thing = Thing()
1442 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1443
Ezio Melotti75cbd732011-04-28 00:59:29 +03001444 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001445 class descriptor(object):
1446 def __get__(*_):
1447 raise AttributeError("I'm pretending not to exist")
1448 desc = descriptor()
1449 class Thing(object):
1450 x = desc
1451 thing = Thing()
1452 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1453
1454 def test_classAttribute(self):
1455 class Thing(object):
1456 x = object()
1457
1458 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1459
Ethan Furmane03ea372013-09-25 07:14:41 -07001460 def test_classVirtualAttribute(self):
1461 class Thing(object):
1462 @types.DynamicClassAttribute
1463 def x(self):
1464 return self._x
1465 _x = object()
1466
1467 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1468
Michael Foord95fc51d2010-11-20 15:07:30 +00001469 def test_inherited_classattribute(self):
1470 class Thing(object):
1471 x = object()
1472 class OtherThing(Thing):
1473 pass
1474
1475 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1476
1477 def test_slots(self):
1478 class Thing(object):
1479 y = 'bar'
1480 __slots__ = ['x']
1481 def __init__(self):
1482 self.x = 'foo'
1483 thing = Thing()
1484 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1485 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1486
1487 del thing.x
1488 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1489
1490 def test_metaclass(self):
1491 class meta(type):
1492 attr = 'foo'
1493 class Thing(object, metaclass=meta):
1494 pass
1495 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1496
1497 class sub(meta):
1498 pass
1499 class OtherThing(object, metaclass=sub):
1500 x = 3
1501 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1502
1503 class OtherOtherThing(OtherThing):
1504 pass
1505 # this test is odd, but it was added as it exposed a bug
1506 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1507
1508 def test_no_dict_no_slots(self):
1509 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1510 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1511
1512 def test_no_dict_no_slots_instance_member(self):
1513 # returns descriptor
1514 with open(__file__) as handle:
1515 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1516
1517 def test_inherited_slots(self):
1518 # returns descriptor
1519 class Thing(object):
1520 __slots__ = ['x']
1521 def __init__(self):
1522 self.x = 'foo'
1523
1524 class OtherThing(Thing):
1525 pass
1526 # it would be nice if this worked...
1527 # we get the descriptor instead of the instance attribute
1528 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1529
1530 def test_descriptor(self):
1531 class descriptor(object):
1532 def __get__(self, instance, owner):
1533 return 3
1534 class Foo(object):
1535 d = descriptor()
1536
1537 foo = Foo()
1538
1539 # for a non data descriptor we return the instance attribute
1540 foo.__dict__['d'] = 1
1541 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1542
1543 # if the descriptor is a data-desciptor we should return the
1544 # descriptor
1545 descriptor.__set__ = lambda s, i, v: None
1546 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1547
1548
1549 def test_metaclass_with_descriptor(self):
1550 class descriptor(object):
1551 def __get__(self, instance, owner):
1552 return 3
1553 class meta(type):
1554 d = descriptor()
1555 class Thing(object, metaclass=meta):
1556 pass
1557 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1558
1559
Michael Foordcc7ebb82010-11-20 16:20:16 +00001560 def test_class_as_property(self):
1561 class Base(object):
1562 foo = 3
1563
1564 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001565 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001566 @property
1567 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001568 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001569 return object
1570
Michael Foord35184ed2010-11-20 16:58:30 +00001571 instance = Something()
1572 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1573 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001574 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1575
Michael Foorde5162652010-11-20 16:40:44 +00001576 def test_mro_as_property(self):
1577 class Meta(type):
1578 @property
1579 def __mro__(self):
1580 return (object,)
1581
1582 class Base(object):
1583 foo = 3
1584
1585 class Something(Base, metaclass=Meta):
1586 pass
1587
1588 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1589 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1590
Michael Foorddcebe0f2011-03-15 19:20:44 -04001591 def test_dict_as_property(self):
1592 test = self
1593 test.called = False
1594
1595 class Foo(dict):
1596 a = 3
1597 @property
1598 def __dict__(self):
1599 test.called = True
1600 return {}
1601
1602 foo = Foo()
1603 foo.a = 4
1604 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1605 self.assertFalse(test.called)
1606
1607 def test_custom_object_dict(self):
1608 test = self
1609 test.called = False
1610
1611 class Custom(dict):
1612 def get(self, key, default=None):
1613 test.called = True
1614 super().get(key, default)
1615
1616 class Foo(object):
1617 a = 3
1618 foo = Foo()
1619 foo.__dict__ = Custom()
1620 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1621 self.assertFalse(test.called)
1622
1623 def test_metaclass_dict_as_property(self):
1624 class Meta(type):
1625 @property
1626 def __dict__(self):
1627 self.executed = True
1628
1629 class Thing(metaclass=Meta):
1630 executed = False
1631
1632 def __init__(self):
1633 self.spam = 42
1634
1635 instance = Thing()
1636 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1637 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001638
Michael Foorda51623b2011-12-18 22:01:40 +00001639 def test_module(self):
1640 sentinel = object()
1641 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1642 sentinel)
1643
Michael Foord3ba95f82011-12-22 01:13:37 +00001644 def test_metaclass_with_metaclass_with_dict_as_property(self):
1645 class MetaMeta(type):
1646 @property
1647 def __dict__(self):
1648 self.executed = True
1649 return dict(spam=42)
1650
1651 class Meta(type, metaclass=MetaMeta):
1652 executed = False
1653
1654 class Thing(metaclass=Meta):
1655 pass
1656
1657 with self.assertRaises(AttributeError):
1658 inspect.getattr_static(Thing, "spam")
1659 self.assertFalse(Thing.executed)
1660
Nick Coghlane0f04652010-11-21 03:44:04 +00001661class TestGetGeneratorState(unittest.TestCase):
1662
1663 def setUp(self):
1664 def number_generator():
1665 for number in range(5):
1666 yield number
1667 self.generator = number_generator()
1668
1669 def _generatorstate(self):
1670 return inspect.getgeneratorstate(self.generator)
1671
1672 def test_created(self):
1673 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1674
1675 def test_suspended(self):
1676 next(self.generator)
1677 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1678
1679 def test_closed_after_exhaustion(self):
1680 for i in self.generator:
1681 pass
1682 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1683
1684 def test_closed_after_immediate_exception(self):
1685 with self.assertRaises(RuntimeError):
1686 self.generator.throw(RuntimeError)
1687 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1688
1689 def test_running(self):
1690 # As mentioned on issue #10220, checking for the RUNNING state only
1691 # makes sense inside the generator itself.
1692 # The following generator checks for this by using the closure's
1693 # reference to self and the generator state checking helper method
1694 def running_check_generator():
1695 for number in range(5):
1696 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1697 yield number
1698 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1699 self.generator = running_check_generator()
1700 # Running up to the first yield
1701 next(self.generator)
1702 # Running after the first yield
1703 next(self.generator)
1704
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001705 def test_easy_debugging(self):
1706 # repr() and str() of a generator state should contain the state name
1707 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1708 for name in names:
1709 state = getattr(inspect, name)
1710 self.assertIn(name, repr(state))
1711 self.assertIn(name, str(state))
1712
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001713 def test_getgeneratorlocals(self):
1714 def each(lst, a=None):
1715 b=(1, 2, 3)
1716 for v in lst:
1717 if v == 3:
1718 c = 12
1719 yield v
1720
1721 numbers = each([1, 2, 3])
1722 self.assertEqual(inspect.getgeneratorlocals(numbers),
1723 {'a': None, 'lst': [1, 2, 3]})
1724 next(numbers)
1725 self.assertEqual(inspect.getgeneratorlocals(numbers),
1726 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1727 'b': (1, 2, 3)})
1728 next(numbers)
1729 self.assertEqual(inspect.getgeneratorlocals(numbers),
1730 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1731 'b': (1, 2, 3)})
1732 next(numbers)
1733 self.assertEqual(inspect.getgeneratorlocals(numbers),
1734 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1735 'b': (1, 2, 3), 'c': 12})
1736 try:
1737 next(numbers)
1738 except StopIteration:
1739 pass
1740 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1741
1742 def test_getgeneratorlocals_empty(self):
1743 def yield_one():
1744 yield 1
1745 one = yield_one()
1746 self.assertEqual(inspect.getgeneratorlocals(one), {})
1747 try:
1748 next(one)
1749 except StopIteration:
1750 pass
1751 self.assertEqual(inspect.getgeneratorlocals(one), {})
1752
1753 def test_getgeneratorlocals_error(self):
1754 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1755 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1756 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1757 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1758
Nick Coghlane0f04652010-11-21 03:44:04 +00001759
Yury Selivanov5376ba92015-06-22 12:19:30 -04001760class TestGetCoroutineState(unittest.TestCase):
1761
1762 def setUp(self):
1763 @types.coroutine
1764 def number_coroutine():
1765 for number in range(5):
1766 yield number
1767 async def coroutine():
1768 await number_coroutine()
1769 self.coroutine = coroutine()
1770
1771 def tearDown(self):
1772 self.coroutine.close()
1773
1774 def _coroutinestate(self):
1775 return inspect.getcoroutinestate(self.coroutine)
1776
1777 def test_created(self):
1778 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1779
1780 def test_suspended(self):
1781 self.coroutine.send(None)
1782 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1783
1784 def test_closed_after_exhaustion(self):
1785 while True:
1786 try:
1787 self.coroutine.send(None)
1788 except StopIteration:
1789 break
1790
1791 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1792
1793 def test_closed_after_immediate_exception(self):
1794 with self.assertRaises(RuntimeError):
1795 self.coroutine.throw(RuntimeError)
1796 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1797
1798 def test_easy_debugging(self):
1799 # repr() and str() of a coroutine state should contain the state name
1800 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1801 for name in names:
1802 state = getattr(inspect, name)
1803 self.assertIn(name, repr(state))
1804 self.assertIn(name, str(state))
1805
1806 def test_getcoroutinelocals(self):
1807 @types.coroutine
1808 def gencoro():
1809 yield
1810
1811 gencoro = gencoro()
1812 async def func(a=None):
1813 b = 'spam'
1814 await gencoro
1815
1816 coro = func()
1817 self.assertEqual(inspect.getcoroutinelocals(coro),
1818 {'a': None, 'gencoro': gencoro})
1819 coro.send(None)
1820 self.assertEqual(inspect.getcoroutinelocals(coro),
1821 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
1822
1823
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001824class MySignature(inspect.Signature):
1825 # Top-level to make it picklable;
1826 # used in test_signature_object_pickle
1827 pass
1828
1829class MyParameter(inspect.Parameter):
1830 # Top-level to make it picklable;
1831 # used in test_signature_object_pickle
1832 pass
1833
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001834
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001835
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001836class TestSignatureObject(unittest.TestCase):
1837 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04001838 def signature(func, **kw):
1839 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001840 return (tuple((param.name,
1841 (... if param.default is param.empty else param.default),
1842 (... if param.annotation is param.empty
1843 else param.annotation),
1844 str(param.kind).lower())
1845 for param in sig.parameters.values()),
1846 (... if sig.return_annotation is sig.empty
1847 else sig.return_annotation))
1848
1849 def test_signature_object(self):
1850 S = inspect.Signature
1851 P = inspect.Parameter
1852
1853 self.assertEqual(str(S()), '()')
1854
Yury Selivanov07a9e452014-01-29 10:58:16 -05001855 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001856 pass
1857 sig = inspect.signature(test)
1858 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001859 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001860 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001861 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001862 args = sig.parameters['args']
1863 ko = sig.parameters['ko']
1864 kwargs = sig.parameters['kwargs']
1865
1866 S((po, pk, args, ko, kwargs))
1867
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001868 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001869 S((pk, po, args, ko, kwargs))
1870
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001871 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001872 S((po, args, pk, ko, kwargs))
1873
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001874 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001875 S((args, po, pk, ko, kwargs))
1876
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001877 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001878 S((po, pk, args, kwargs, ko))
1879
1880 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001881 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001882 S((po, pk, args, kwargs2, ko))
1883
Yury Selivanov07a9e452014-01-29 10:58:16 -05001884 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1885 S((pod, po))
1886
1887 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1888 S((po, pkd, pk))
1889
1890 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1891 S((pkd, pk))
1892
Yury Selivanov374375d2014-03-27 12:41:53 -04001893 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04001894 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04001895
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001896 def test_signature_object_pickle(self):
1897 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1898 foo_partial = functools.partial(foo, a=1)
1899
1900 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001901
1902 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1903 with self.subTest(pickle_ver=ver, subclass=False):
1904 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1905 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001906
1907 # Test that basic sub-classing works
1908 sig = inspect.signature(foo)
1909 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1910 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1911 mysig = MySignature().replace(parameters=myparams.values(),
1912 return_annotation=sig.return_annotation)
1913 self.assertTrue(isinstance(mysig, MySignature))
1914 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1915
1916 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1917 with self.subTest(pickle_ver=ver, subclass=True):
1918 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1919 self.assertEqual(mysig, sig_pickled)
1920 self.assertTrue(isinstance(sig_pickled, MySignature))
1921 self.assertTrue(isinstance(sig_pickled.parameters['z'],
1922 MyParameter))
1923
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001924 def test_signature_immutability(self):
1925 def test(a):
1926 pass
1927 sig = inspect.signature(test)
1928
1929 with self.assertRaises(AttributeError):
1930 sig.foo = 'bar'
1931
1932 with self.assertRaises(TypeError):
1933 sig.parameters['a'] = None
1934
1935 def test_signature_on_noarg(self):
1936 def test():
1937 pass
1938 self.assertEqual(self.signature(test), ((), ...))
1939
1940 def test_signature_on_wargs(self):
1941 def test(a, b:'foo') -> 123:
1942 pass
1943 self.assertEqual(self.signature(test),
1944 ((('a', ..., ..., "positional_or_keyword"),
1945 ('b', ..., 'foo', "positional_or_keyword")),
1946 123))
1947
1948 def test_signature_on_wkwonly(self):
1949 def test(*, a:float, b:str) -> int:
1950 pass
1951 self.assertEqual(self.signature(test),
1952 ((('a', ..., float, "keyword_only"),
1953 ('b', ..., str, "keyword_only")),
1954 int))
1955
1956 def test_signature_on_complex_args(self):
1957 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1958 pass
1959 self.assertEqual(self.signature(test),
1960 ((('a', ..., ..., "positional_or_keyword"),
1961 ('b', 10, 'foo', "positional_or_keyword"),
1962 ('args', ..., 'bar', "var_positional"),
1963 ('spam', ..., 'baz', "keyword_only"),
1964 ('ham', 123, ..., "keyword_only"),
1965 ('kwargs', ..., int, "var_keyword")),
1966 ...))
1967
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001968 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001969 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1970 "Signature information for builtins requires docstrings")
1971 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001972 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001973
Larry Hastings5c661892014-01-24 06:17:25 -08001974 def test_unbound_method(o):
1975 """Use this to test unbound methods (things that should have a self)"""
1976 signature = inspect.signature(o)
1977 self.assertTrue(isinstance(signature, inspect.Signature))
1978 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1979 return signature
1980
1981 def test_callable(o):
1982 """Use this to test bound methods or normal callables (things that don't expect self)"""
1983 signature = inspect.signature(o)
1984 self.assertTrue(isinstance(signature, inspect.Signature))
1985 if signature.parameters:
1986 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1987 return signature
1988
1989 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001990 def p(name): return signature.parameters[name].default
1991 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001992 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001993 self.assertEqual(p('d'), 3.14)
1994 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001995 self.assertEqual(p('n'), None)
1996 self.assertEqual(p('t'), True)
1997 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001998 self.assertEqual(p('local'), 3)
1999 self.assertEqual(p('sys'), sys.maxsize)
2000 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002001
Larry Hastings5c661892014-01-24 06:17:25 -08002002 test_callable(object)
2003
2004 # normal method
2005 # (PyMethodDescr_Type, "method_descriptor")
2006 test_unbound_method(_pickle.Pickler.dump)
2007 d = _pickle.Pickler(io.StringIO())
2008 test_callable(d.dump)
2009
2010 # static method
2011 test_callable(str.maketrans)
2012 test_callable('abc'.maketrans)
2013
2014 # class method
2015 test_callable(dict.fromkeys)
2016 test_callable({}.fromkeys)
2017
2018 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2019 test_unbound_method(type.__call__)
2020 test_unbound_method(int.__add__)
2021 test_callable((3).__add__)
2022
2023 # _PyMethodWrapper_Type
2024 # support for 'method-wrapper'
2025 test_callable(min.__call__)
2026
Larry Hastings2623c8c2014-02-08 22:15:29 -08002027 # This doesn't work now.
2028 # (We don't have a valid signature for "type" in 3.4)
2029 with self.assertRaisesRegex(ValueError, "no signature found"):
2030 class ThisWorksNow:
2031 __call__ = type
2032 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002033
Yury Selivanov056e2652014-03-02 12:25:27 -05002034 # Regression test for issue #20786
2035 test_unbound_method(dict.__delitem__)
2036 test_unbound_method(property.__delete__)
2037
Zachary Ware8ef887c2015-04-13 18:22:35 -05002038 # Regression test for issue #20586
2039 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2040
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002041 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002042 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2043 "Signature information for builtins requires docstrings")
2044 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002045 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002046 func = _testcapi.docstring_with_signature_with_defaults
2047
2048 def decorator(func):
2049 @functools.wraps(func)
2050 def wrapper(*args, **kwargs) -> int:
2051 return func(*args, **kwargs)
2052 return wrapper
2053
2054 decorated_func = decorator(func)
2055
2056 self.assertEqual(inspect.signature(func),
2057 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002058
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002059 def wrapper_like(*args, **kwargs) -> int: pass
2060 self.assertEqual(inspect.signature(decorated_func,
2061 follow_wrapped=False),
2062 inspect.signature(wrapper_like))
2063
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002064 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002065 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002066 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002067 with self.assertRaisesRegex(ValueError,
2068 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002069 inspect.signature(_testcapi.docstring_no_signature)
2070
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002071 with self.assertRaisesRegex(ValueError,
2072 'no signature found for builtin'):
2073 inspect.signature(str)
2074
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002075 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002076 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002077 inspect.signature(42)
2078
Yury Selivanov63da7c72014-01-31 14:48:37 -05002079 def test_signature_from_functionlike_object(self):
2080 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2081 pass
2082
2083 class funclike:
2084 # Has to be callable, and have correct
2085 # __code__, __annotations__, __defaults__, __name__,
2086 # and __kwdefaults__ attributes
2087
2088 def __init__(self, func):
2089 self.__name__ = func.__name__
2090 self.__code__ = func.__code__
2091 self.__annotations__ = func.__annotations__
2092 self.__defaults__ = func.__defaults__
2093 self.__kwdefaults__ = func.__kwdefaults__
2094 self.func = func
2095
2096 def __call__(self, *args, **kwargs):
2097 return self.func(*args, **kwargs)
2098
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002099 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002100
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002101 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002102 self.assertEqual(sig_funclike, sig_func)
2103
2104 sig_funclike = inspect.signature(funclike(func))
2105 self.assertEqual(sig_funclike, sig_func)
2106
2107 # If object is not a duck type of function, then
2108 # signature will try to get a signature for its '__call__'
2109 # method
2110 fl = funclike(func)
2111 del fl.__defaults__
2112 self.assertEqual(self.signature(fl),
2113 ((('args', ..., ..., "var_positional"),
2114 ('kwargs', ..., ..., "var_keyword")),
2115 ...))
2116
Yury Selivanova773de02014-02-21 18:30:53 -05002117 # Test with cython-like builtins:
2118 _orig_isdesc = inspect.ismethoddescriptor
2119 def _isdesc(obj):
2120 if hasattr(obj, '_builtinmock'):
2121 return True
2122 return _orig_isdesc(obj)
2123
2124 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2125 builtin_func = funclike(func)
2126 # Make sure that our mock setup is working
2127 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2128 builtin_func._builtinmock = True
2129 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2130 self.assertEqual(inspect.signature(builtin_func), sig_func)
2131
Yury Selivanov63da7c72014-01-31 14:48:37 -05002132 def test_signature_functionlike_class(self):
2133 # We only want to duck type function-like objects,
2134 # not classes.
2135
2136 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2137 pass
2138
2139 class funclike:
2140 def __init__(self, marker):
2141 pass
2142
2143 __name__ = func.__name__
2144 __code__ = func.__code__
2145 __annotations__ = func.__annotations__
2146 __defaults__ = func.__defaults__
2147 __kwdefaults__ = func.__kwdefaults__
2148
Yury Selivanov63da7c72014-01-31 14:48:37 -05002149 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2150
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002151 def test_signature_on_method(self):
2152 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002153 def __init__(*args):
2154 pass
2155 def m1(self, arg1, arg2=1) -> int:
2156 pass
2157 def m2(*args):
2158 pass
2159 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002160 pass
2161
Yury Selivanov62560fb2014-01-28 12:26:24 -05002162 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002163 ((('arg1', ..., ..., "positional_or_keyword"),
2164 ('arg2', 1, ..., "positional_or_keyword")),
2165 int))
2166
Yury Selivanov62560fb2014-01-28 12:26:24 -05002167 self.assertEqual(self.signature(Test().m2),
2168 ((('args', ..., ..., "var_positional"),),
2169 ...))
2170
2171 self.assertEqual(self.signature(Test),
2172 ((('args', ..., ..., "var_positional"),),
2173 ...))
2174
2175 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2176 self.signature(Test())
2177
Yury Selivanov46c759d2015-05-27 21:56:53 -04002178 def test_signature_wrapped_bound_method(self):
2179 # Issue 24298
2180 class Test:
2181 def m1(self, arg1, arg2=1) -> int:
2182 pass
2183 @functools.wraps(Test().m1)
2184 def m1d(*args, **kwargs):
2185 pass
2186 self.assertEqual(self.signature(m1d),
2187 ((('arg1', ..., ..., "positional_or_keyword"),
2188 ('arg2', 1, ..., "positional_or_keyword")),
2189 int))
2190
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002191 def test_signature_on_classmethod(self):
2192 class Test:
2193 @classmethod
2194 def foo(cls, arg1, *, arg2=1):
2195 pass
2196
2197 meth = Test().foo
2198 self.assertEqual(self.signature(meth),
2199 ((('arg1', ..., ..., "positional_or_keyword"),
2200 ('arg2', 1, ..., "keyword_only")),
2201 ...))
2202
2203 meth = Test.foo
2204 self.assertEqual(self.signature(meth),
2205 ((('arg1', ..., ..., "positional_or_keyword"),
2206 ('arg2', 1, ..., "keyword_only")),
2207 ...))
2208
2209 def test_signature_on_staticmethod(self):
2210 class Test:
2211 @staticmethod
2212 def foo(cls, *, arg):
2213 pass
2214
2215 meth = Test().foo
2216 self.assertEqual(self.signature(meth),
2217 ((('cls', ..., ..., "positional_or_keyword"),
2218 ('arg', ..., ..., "keyword_only")),
2219 ...))
2220
2221 meth = Test.foo
2222 self.assertEqual(self.signature(meth),
2223 ((('cls', ..., ..., "positional_or_keyword"),
2224 ('arg', ..., ..., "keyword_only")),
2225 ...))
2226
2227 def test_signature_on_partial(self):
2228 from functools import partial
2229
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002230 Parameter = inspect.Parameter
2231
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002232 def test():
2233 pass
2234
2235 self.assertEqual(self.signature(partial(test)), ((), ...))
2236
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002237 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002238 inspect.signature(partial(test, 1))
2239
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002240 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002241 inspect.signature(partial(test, a=1))
2242
2243 def test(a, b, *, c, d):
2244 pass
2245
2246 self.assertEqual(self.signature(partial(test)),
2247 ((('a', ..., ..., "positional_or_keyword"),
2248 ('b', ..., ..., "positional_or_keyword"),
2249 ('c', ..., ..., "keyword_only"),
2250 ('d', ..., ..., "keyword_only")),
2251 ...))
2252
2253 self.assertEqual(self.signature(partial(test, 1)),
2254 ((('b', ..., ..., "positional_or_keyword"),
2255 ('c', ..., ..., "keyword_only"),
2256 ('d', ..., ..., "keyword_only")),
2257 ...))
2258
2259 self.assertEqual(self.signature(partial(test, 1, c=2)),
2260 ((('b', ..., ..., "positional_or_keyword"),
2261 ('c', 2, ..., "keyword_only"),
2262 ('d', ..., ..., "keyword_only")),
2263 ...))
2264
2265 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2266 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002267 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002268 ('c', 2, ..., "keyword_only"),
2269 ('d', ..., ..., "keyword_only")),
2270 ...))
2271
2272 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002273 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002274 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002275 ('d', ..., ..., "keyword_only")),
2276 ...))
2277
2278 self.assertEqual(self.signature(partial(test, a=1)),
2279 ((('a', 1, ..., "keyword_only"),
2280 ('b', ..., ..., "keyword_only"),
2281 ('c', ..., ..., "keyword_only"),
2282 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002283 ...))
2284
2285 def test(a, *args, b, **kwargs):
2286 pass
2287
2288 self.assertEqual(self.signature(partial(test, 1)),
2289 ((('args', ..., ..., "var_positional"),
2290 ('b', ..., ..., "keyword_only"),
2291 ('kwargs', ..., ..., "var_keyword")),
2292 ...))
2293
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002294 self.assertEqual(self.signature(partial(test, a=1)),
2295 ((('a', 1, ..., "keyword_only"),
2296 ('b', ..., ..., "keyword_only"),
2297 ('kwargs', ..., ..., "var_keyword")),
2298 ...))
2299
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002300 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2301 ((('args', ..., ..., "var_positional"),
2302 ('b', ..., ..., "keyword_only"),
2303 ('kwargs', ..., ..., "var_keyword")),
2304 ...))
2305
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002306 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2307 ((('args', ..., ..., "var_positional"),
2308 ('b', ..., ..., "keyword_only"),
2309 ('kwargs', ..., ..., "var_keyword")),
2310 ...))
2311
2312 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2313 ((('args', ..., ..., "var_positional"),
2314 ('b', 0, ..., "keyword_only"),
2315 ('kwargs', ..., ..., "var_keyword")),
2316 ...))
2317
2318 self.assertEqual(self.signature(partial(test, b=0)),
2319 ((('a', ..., ..., "positional_or_keyword"),
2320 ('args', ..., ..., "var_positional"),
2321 ('b', 0, ..., "keyword_only"),
2322 ('kwargs', ..., ..., "var_keyword")),
2323 ...))
2324
2325 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2326 ((('a', ..., ..., "positional_or_keyword"),
2327 ('args', ..., ..., "var_positional"),
2328 ('b', 0, ..., "keyword_only"),
2329 ('kwargs', ..., ..., "var_keyword")),
2330 ...))
2331
2332 def test(a, b, c:int) -> 42:
2333 pass
2334
2335 sig = test.__signature__ = inspect.signature(test)
2336
2337 self.assertEqual(self.signature(partial(partial(test, 1))),
2338 ((('b', ..., ..., "positional_or_keyword"),
2339 ('c', ..., int, "positional_or_keyword")),
2340 42))
2341
2342 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2343 ((('c', ..., int, "positional_or_keyword"),),
2344 42))
2345
2346 psig = inspect.signature(partial(partial(test, 1), 2))
2347
2348 def foo(a):
2349 return a
2350 _foo = partial(partial(foo, a=10), a=20)
2351 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002352 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002353 ...))
2354 # check that we don't have any side-effects in signature(),
2355 # and the partial object is still functioning
2356 self.assertEqual(_foo(), 20)
2357
2358 def foo(a, b, c):
2359 return a, b, c
2360 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002361
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002362 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002363 ((('b', 30, ..., "keyword_only"),
2364 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002365 ...))
2366 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002367
2368 def foo(a, b, c, *, d):
2369 return a, b, c, d
2370 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2371 self.assertEqual(self.signature(_foo),
2372 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002373 ('b', 10, ..., "keyword_only"),
2374 ('c', 20, ..., "keyword_only"),
2375 ('d', 30, ..., "keyword_only"),
2376 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002377 ...))
2378 ba = inspect.signature(_foo).bind(a=200, b=11)
2379 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2380
2381 def foo(a=1, b=2, c=3):
2382 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002383 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2384
2385 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002386 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002387
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002388 ba = inspect.signature(_foo).bind(11, 12)
2389 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002390
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002391 ba = inspect.signature(_foo).bind(11, b=12)
2392 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002393
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002394 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002395 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2396
2397 _foo = partial(_foo, b=10, c=20)
2398 ba = inspect.signature(_foo).bind(12)
2399 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2400
2401
2402 def foo(a, b, c, d, **kwargs):
2403 pass
2404 sig = inspect.signature(foo)
2405 params = sig.parameters.copy()
2406 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2407 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2408 foo.__signature__ = inspect.Signature(params.values())
2409 sig = inspect.signature(foo)
2410 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2411
2412 self.assertEqual(self.signature(partial(foo, 1)),
2413 ((('b', ..., ..., 'positional_only'),
2414 ('c', ..., ..., 'positional_or_keyword'),
2415 ('d', ..., ..., 'positional_or_keyword'),
2416 ('kwargs', ..., ..., 'var_keyword')),
2417 ...))
2418
2419 self.assertEqual(self.signature(partial(foo, 1, 2)),
2420 ((('c', ..., ..., 'positional_or_keyword'),
2421 ('d', ..., ..., 'positional_or_keyword'),
2422 ('kwargs', ..., ..., 'var_keyword')),
2423 ...))
2424
2425 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2426 ((('d', ..., ..., 'positional_or_keyword'),
2427 ('kwargs', ..., ..., 'var_keyword')),
2428 ...))
2429
2430 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2431 ((('c', 3, ..., 'keyword_only'),
2432 ('d', ..., ..., 'keyword_only'),
2433 ('kwargs', ..., ..., 'var_keyword')),
2434 ...))
2435
2436 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2437 ((('b', ..., ..., 'positional_only'),
2438 ('c', 3, ..., 'keyword_only'),
2439 ('d', ..., ..., 'keyword_only'),
2440 ('kwargs', ..., ..., 'var_keyword')),
2441 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002442
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002443 def test_signature_on_partialmethod(self):
2444 from functools import partialmethod
2445
2446 class Spam:
2447 def test():
2448 pass
2449 ham = partialmethod(test)
2450
2451 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2452 inspect.signature(Spam.ham)
2453
2454 class Spam:
2455 def test(it, a, *, c) -> 'spam':
2456 pass
2457 ham = partialmethod(test, c=1)
2458
2459 self.assertEqual(self.signature(Spam.ham),
2460 ((('it', ..., ..., 'positional_or_keyword'),
2461 ('a', ..., ..., 'positional_or_keyword'),
2462 ('c', 1, ..., 'keyword_only')),
2463 'spam'))
2464
2465 self.assertEqual(self.signature(Spam().ham),
2466 ((('a', ..., ..., 'positional_or_keyword'),
2467 ('c', 1, ..., 'keyword_only')),
2468 'spam'))
2469
Yury Selivanov0486f812014-01-29 12:18:59 -05002470 def test_signature_on_fake_partialmethod(self):
2471 def foo(a): pass
2472 foo._partialmethod = 'spam'
2473 self.assertEqual(str(inspect.signature(foo)), '(a)')
2474
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002475 def test_signature_on_decorated(self):
2476 import functools
2477
2478 def decorator(func):
2479 @functools.wraps(func)
2480 def wrapper(*args, **kwargs) -> int:
2481 return func(*args, **kwargs)
2482 return wrapper
2483
2484 class Foo:
2485 @decorator
2486 def bar(self, a, b):
2487 pass
2488
2489 self.assertEqual(self.signature(Foo.bar),
2490 ((('self', ..., ..., "positional_or_keyword"),
2491 ('a', ..., ..., "positional_or_keyword"),
2492 ('b', ..., ..., "positional_or_keyword")),
2493 ...))
2494
2495 self.assertEqual(self.signature(Foo().bar),
2496 ((('a', ..., ..., "positional_or_keyword"),
2497 ('b', ..., ..., "positional_or_keyword")),
2498 ...))
2499
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002500 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2501 ((('args', ..., ..., "var_positional"),
2502 ('kwargs', ..., ..., "var_keyword")),
2503 ...)) # functools.wraps will copy __annotations__
2504 # from "func" to "wrapper", hence no
2505 # return_annotation
2506
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002507 # Test that we handle method wrappers correctly
2508 def decorator(func):
2509 @functools.wraps(func)
2510 def wrapper(*args, **kwargs) -> int:
2511 return func(42, *args, **kwargs)
2512 sig = inspect.signature(func)
2513 new_params = tuple(sig.parameters.values())[1:]
2514 wrapper.__signature__ = sig.replace(parameters=new_params)
2515 return wrapper
2516
2517 class Foo:
2518 @decorator
2519 def __call__(self, a, b):
2520 pass
2521
2522 self.assertEqual(self.signature(Foo.__call__),
2523 ((('a', ..., ..., "positional_or_keyword"),
2524 ('b', ..., ..., "positional_or_keyword")),
2525 ...))
2526
2527 self.assertEqual(self.signature(Foo().__call__),
2528 ((('b', ..., ..., "positional_or_keyword"),),
2529 ...))
2530
Nick Coghlane8c45d62013-07-28 20:00:01 +10002531 # Test we handle __signature__ partway down the wrapper stack
2532 def wrapped_foo_call():
2533 pass
2534 wrapped_foo_call.__wrapped__ = Foo.__call__
2535
2536 self.assertEqual(self.signature(wrapped_foo_call),
2537 ((('a', ..., ..., "positional_or_keyword"),
2538 ('b', ..., ..., "positional_or_keyword")),
2539 ...))
2540
2541
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002542 def test_signature_on_class(self):
2543 class C:
2544 def __init__(self, a):
2545 pass
2546
2547 self.assertEqual(self.signature(C),
2548 ((('a', ..., ..., "positional_or_keyword"),),
2549 ...))
2550
2551 class CM(type):
2552 def __call__(cls, a):
2553 pass
2554 class C(metaclass=CM):
2555 def __init__(self, b):
2556 pass
2557
2558 self.assertEqual(self.signature(C),
2559 ((('a', ..., ..., "positional_or_keyword"),),
2560 ...))
2561
2562 class CM(type):
2563 def __new__(mcls, name, bases, dct, *, foo=1):
2564 return super().__new__(mcls, name, bases, dct)
2565 class C(metaclass=CM):
2566 def __init__(self, b):
2567 pass
2568
2569 self.assertEqual(self.signature(C),
2570 ((('b', ..., ..., "positional_or_keyword"),),
2571 ...))
2572
2573 self.assertEqual(self.signature(CM),
2574 ((('name', ..., ..., "positional_or_keyword"),
2575 ('bases', ..., ..., "positional_or_keyword"),
2576 ('dct', ..., ..., "positional_or_keyword"),
2577 ('foo', 1, ..., "keyword_only")),
2578 ...))
2579
2580 class CMM(type):
2581 def __new__(mcls, name, bases, dct, *, foo=1):
2582 return super().__new__(mcls, name, bases, dct)
2583 def __call__(cls, nm, bs, dt):
2584 return type(nm, bs, dt)
2585 class CM(type, metaclass=CMM):
2586 def __new__(mcls, name, bases, dct, *, bar=2):
2587 return super().__new__(mcls, name, bases, dct)
2588 class C(metaclass=CM):
2589 def __init__(self, b):
2590 pass
2591
2592 self.assertEqual(self.signature(CMM),
2593 ((('name', ..., ..., "positional_or_keyword"),
2594 ('bases', ..., ..., "positional_or_keyword"),
2595 ('dct', ..., ..., "positional_or_keyword"),
2596 ('foo', 1, ..., "keyword_only")),
2597 ...))
2598
2599 self.assertEqual(self.signature(CM),
2600 ((('nm', ..., ..., "positional_or_keyword"),
2601 ('bs', ..., ..., "positional_or_keyword"),
2602 ('dt', ..., ..., "positional_or_keyword")),
2603 ...))
2604
2605 self.assertEqual(self.signature(C),
2606 ((('b', ..., ..., "positional_or_keyword"),),
2607 ...))
2608
2609 class CM(type):
2610 def __init__(cls, name, bases, dct, *, bar=2):
2611 return super().__init__(name, bases, dct)
2612 class C(metaclass=CM):
2613 def __init__(self, b):
2614 pass
2615
2616 self.assertEqual(self.signature(CM),
2617 ((('name', ..., ..., "positional_or_keyword"),
2618 ('bases', ..., ..., "positional_or_keyword"),
2619 ('dct', ..., ..., "positional_or_keyword"),
2620 ('bar', 2, ..., "keyword_only")),
2621 ...))
2622
Yury Selivanov145dff82014-02-01 13:49:29 -05002623 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2624 "Signature information for builtins requires docstrings")
2625 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002626 # Test classes without user-defined __init__ or __new__
2627 class C: pass
2628 self.assertEqual(str(inspect.signature(C)), '()')
2629 class D(C): pass
2630 self.assertEqual(str(inspect.signature(D)), '()')
2631
2632 # Test meta-classes without user-defined __init__ or __new__
2633 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002634 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002635 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2636 self.assertEqual(inspect.signature(C), None)
2637 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2638 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002639
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002640 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2641 "Signature information for builtins requires docstrings")
2642 def test_signature_on_builtin_class(self):
2643 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2644 '(file, protocol=None, fix_imports=True)')
2645
2646 class P(_pickle.Pickler): pass
2647 class EmptyTrait: pass
2648 class P2(EmptyTrait, P): pass
2649 self.assertEqual(str(inspect.signature(P)),
2650 '(file, protocol=None, fix_imports=True)')
2651 self.assertEqual(str(inspect.signature(P2)),
2652 '(file, protocol=None, fix_imports=True)')
2653
2654 class P3(P2):
2655 def __init__(self, spam):
2656 pass
2657 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2658
2659 class MetaP(type):
2660 def __call__(cls, foo, bar):
2661 pass
2662 class P4(P2, metaclass=MetaP):
2663 pass
2664 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2665
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002666 def test_signature_on_callable_objects(self):
2667 class Foo:
2668 def __call__(self, a):
2669 pass
2670
2671 self.assertEqual(self.signature(Foo()),
2672 ((('a', ..., ..., "positional_or_keyword"),),
2673 ...))
2674
2675 class Spam:
2676 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002677 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002678 inspect.signature(Spam())
2679
2680 class Bar(Spam, Foo):
2681 pass
2682
2683 self.assertEqual(self.signature(Bar()),
2684 ((('a', ..., ..., "positional_or_keyword"),),
2685 ...))
2686
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002687 class Wrapped:
2688 pass
2689 Wrapped.__wrapped__ = lambda a: None
2690 self.assertEqual(self.signature(Wrapped),
2691 ((('a', ..., ..., "positional_or_keyword"),),
2692 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002693 # wrapper loop:
2694 Wrapped.__wrapped__ = Wrapped
2695 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2696 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002697
2698 def test_signature_on_lambdas(self):
2699 self.assertEqual(self.signature((lambda a=10: a)),
2700 ((('a', 10, ..., "positional_or_keyword"),),
2701 ...))
2702
2703 def test_signature_equality(self):
2704 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002705 self.assertFalse(inspect.signature(foo) == 42)
2706 self.assertTrue(inspect.signature(foo) != 42)
2707 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2708 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002709
2710 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002711 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2712 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002713 self.assertEqual(
2714 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002715
2716 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002717 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2718 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002719 self.assertNotEqual(
2720 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002721
2722 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002723 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2724 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002725 self.assertNotEqual(
2726 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002727
2728 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002729 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2730 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002731 self.assertNotEqual(
2732 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002733
2734 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002735 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2736 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002737 self.assertNotEqual(
2738 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002739
2740 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002741 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2742 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002743 self.assertNotEqual(
2744 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002745 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002746 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
2747 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002748 self.assertNotEqual(
2749 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002750
2751 def foo(*, a, b, c): pass
2752 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002753 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2754 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002755 self.assertEqual(
2756 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002757
2758 def foo(*, a=1, b, c): pass
2759 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002760 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2761 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002762 self.assertEqual(
2763 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002764
2765 def foo(pos, *, a=1, b, c): pass
2766 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002767 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2768 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002769 self.assertEqual(
2770 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002771
2772 def foo(pos, *, a, b, c): pass
2773 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002774 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2775 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002776 self.assertNotEqual(
2777 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002778
2779 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2780 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002781 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2782 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002783 self.assertEqual(
2784 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002785
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002786 def test_signature_hashable(self):
2787 S = inspect.Signature
2788 P = inspect.Parameter
2789
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002790 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002791 foo_sig = inspect.signature(foo)
2792
2793 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2794
2795 self.assertEqual(hash(foo_sig), hash(manual_sig))
2796 self.assertNotEqual(hash(foo_sig),
2797 hash(manual_sig.replace(return_annotation='spam')))
2798
2799 def bar(a) -> 1: pass
2800 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2801
2802 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002803 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002804 hash(inspect.signature(foo))
2805
2806 def foo(a) -> {}: pass
2807 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2808 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002809
2810 def test_signature_str(self):
2811 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2812 pass
2813 self.assertEqual(str(inspect.signature(foo)),
2814 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2815
2816 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2817 pass
2818 self.assertEqual(str(inspect.signature(foo)),
2819 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2820
2821 def foo():
2822 pass
2823 self.assertEqual(str(inspect.signature(foo)), '()')
2824
2825 def test_signature_str_positional_only(self):
2826 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002827 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002828
2829 def test(a_po, *, b, **kwargs):
2830 return a_po, kwargs
2831
2832 sig = inspect.signature(test)
2833 new_params = list(sig.parameters.values())
2834 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2835 test.__signature__ = sig.replace(parameters=new_params)
2836
2837 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002838 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002839
Yury Selivanov2393dca2014-01-27 15:07:58 -05002840 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2841 '(foo, /)')
2842
2843 self.assertEqual(str(S(parameters=[
2844 P('foo', P.POSITIONAL_ONLY),
2845 P('bar', P.VAR_KEYWORD)])),
2846 '(foo, /, **bar)')
2847
2848 self.assertEqual(str(S(parameters=[
2849 P('foo', P.POSITIONAL_ONLY),
2850 P('bar', P.VAR_POSITIONAL)])),
2851 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002852
2853 def test_signature_replace_anno(self):
2854 def test() -> 42:
2855 pass
2856
2857 sig = inspect.signature(test)
2858 sig = sig.replace(return_annotation=None)
2859 self.assertIs(sig.return_annotation, None)
2860 sig = sig.replace(return_annotation=sig.empty)
2861 self.assertIs(sig.return_annotation, sig.empty)
2862 sig = sig.replace(return_annotation=42)
2863 self.assertEqual(sig.return_annotation, 42)
2864 self.assertEqual(sig, inspect.signature(test))
2865
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002866 def test_signature_on_mangled_parameters(self):
2867 class Spam:
2868 def foo(self, __p1:1=2, *, __p2:2=3):
2869 pass
2870 class Ham(Spam):
2871 pass
2872
2873 self.assertEqual(self.signature(Spam.foo),
2874 ((('self', ..., ..., "positional_or_keyword"),
2875 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2876 ('_Spam__p2', 3, 2, "keyword_only")),
2877 ...))
2878
2879 self.assertEqual(self.signature(Spam.foo),
2880 self.signature(Ham.foo))
2881
Yury Selivanovda396452014-03-27 12:09:24 -04002882 def test_signature_from_callable_python_obj(self):
2883 class MySignature(inspect.Signature): pass
2884 def foo(a, *, b:1): pass
2885 foo_sig = MySignature.from_callable(foo)
2886 self.assertTrue(isinstance(foo_sig, MySignature))
2887
2888 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2889 "Signature information for builtins requires docstrings")
2890 def test_signature_from_callable_builtin_obj(self):
2891 class MySignature(inspect.Signature): pass
2892 sig = MySignature.from_callable(_pickle.Pickler)
2893 self.assertTrue(isinstance(sig, MySignature))
2894
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002895
2896class TestParameterObject(unittest.TestCase):
2897 def test_signature_parameter_kinds(self):
2898 P = inspect.Parameter
2899 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2900 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2901
2902 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2903 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2904
2905 def test_signature_parameter_object(self):
2906 p = inspect.Parameter('foo', default=10,
2907 kind=inspect.Parameter.POSITIONAL_ONLY)
2908 self.assertEqual(p.name, 'foo')
2909 self.assertEqual(p.default, 10)
2910 self.assertIs(p.annotation, p.empty)
2911 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2912
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002913 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002914 inspect.Parameter('foo', default=10, kind='123')
2915
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002916 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002917 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2918
Yury Selivanov2393dca2014-01-27 15:07:58 -05002919 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002920 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2921
Yury Selivanov2393dca2014-01-27 15:07:58 -05002922 with self.assertRaisesRegex(ValueError,
2923 'is not a valid parameter name'):
2924 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2925
Nick Coghlanb4b966e2016-06-04 14:40:03 -07002926 with self.assertRaisesRegex(ValueError,
2927 'is not a valid parameter name'):
2928 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
2929
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002930 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002931 inspect.Parameter('a', default=42,
2932 kind=inspect.Parameter.VAR_KEYWORD)
2933
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002934 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002935 inspect.Parameter('a', default=42,
2936 kind=inspect.Parameter.VAR_POSITIONAL)
2937
2938 p = inspect.Parameter('a', default=42,
2939 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002940 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002941 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2942
2943 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002944 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002945
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002946 def test_signature_parameter_hashable(self):
2947 P = inspect.Parameter
2948 foo = P('foo', kind=P.POSITIONAL_ONLY)
2949 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
2950 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
2951 default=42)))
2952 self.assertNotEqual(hash(foo),
2953 hash(foo.replace(kind=P.VAR_POSITIONAL)))
2954
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002955 def test_signature_parameter_equality(self):
2956 P = inspect.Parameter
2957 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2958
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002959 self.assertTrue(p == p)
2960 self.assertFalse(p != p)
2961 self.assertFalse(p == 42)
2962 self.assertTrue(p != 42)
2963 self.assertTrue(p == EqualsToAll())
2964 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002965
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002966 self.assertTrue(p == P('foo', default=42,
2967 kind=inspect.Parameter.KEYWORD_ONLY))
2968 self.assertFalse(p != P('foo', default=42,
2969 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002970
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002971 def test_signature_parameter_replace(self):
2972 p = inspect.Parameter('foo', default=42,
2973 kind=inspect.Parameter.KEYWORD_ONLY)
2974
2975 self.assertIsNot(p, p.replace())
2976 self.assertEqual(p, p.replace())
2977
2978 p2 = p.replace(annotation=1)
2979 self.assertEqual(p2.annotation, 1)
2980 p2 = p2.replace(annotation=p2.empty)
2981 self.assertEqual(p, p2)
2982
2983 p2 = p2.replace(name='bar')
2984 self.assertEqual(p2.name, 'bar')
2985 self.assertNotEqual(p2, p)
2986
Yury Selivanov2393dca2014-01-27 15:07:58 -05002987 with self.assertRaisesRegex(ValueError,
2988 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002989 p2 = p2.replace(name=p2.empty)
2990
2991 p2 = p2.replace(name='foo', default=None)
2992 self.assertIs(p2.default, None)
2993 self.assertNotEqual(p2, p)
2994
2995 p2 = p2.replace(name='foo', default=p2.empty)
2996 self.assertIs(p2.default, p2.empty)
2997
2998
2999 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3000 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3001 self.assertNotEqual(p2, p)
3002
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003003 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003004 p2 = p2.replace(kind=p2.empty)
3005
3006 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3007 self.assertEqual(p2, p)
3008
3009 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003010 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3011 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003012
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003013 @cpython_only
3014 def test_signature_parameter_implicit(self):
3015 with self.assertRaisesRegex(ValueError,
3016 'implicit arguments must be passed in as'):
3017 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3018
3019 param = inspect.Parameter(
3020 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3021 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3022 self.assertEqual(param.name, 'implicit0')
3023
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003024 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003025 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003026
3027 with self.assertRaises(AttributeError):
3028 p.foo = 'bar'
3029
3030 with self.assertRaises(AttributeError):
3031 p.kind = 123
3032
3033
3034class TestSignatureBind(unittest.TestCase):
3035 @staticmethod
3036 def call(func, *args, **kwargs):
3037 sig = inspect.signature(func)
3038 ba = sig.bind(*args, **kwargs)
3039 return func(*ba.args, **ba.kwargs)
3040
3041 def test_signature_bind_empty(self):
3042 def test():
3043 return 42
3044
3045 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003046 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003047 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003048 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003049 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003050 with self.assertRaisesRegex(
3051 TypeError, "got an unexpected keyword argument 'spam'"):
3052
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003053 self.call(test, spam=1)
3054
3055 def test_signature_bind_var(self):
3056 def test(*args, **kwargs):
3057 return args, kwargs
3058
3059 self.assertEqual(self.call(test), ((), {}))
3060 self.assertEqual(self.call(test, 1), ((1,), {}))
3061 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3062 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3063 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3064 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3065 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3066 ((1, 2), {'foo': 'bar'}))
3067
3068 def test_signature_bind_just_args(self):
3069 def test(a, b, c):
3070 return a, b, c
3071
3072 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3073
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003074 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003075 self.call(test, 1, 2, 3, 4)
3076
Yury Selivanov86872752015-05-19 00:27:49 -04003077 with self.assertRaisesRegex(TypeError,
3078 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003079 self.call(test, 1)
3080
Yury Selivanov86872752015-05-19 00:27:49 -04003081 with self.assertRaisesRegex(TypeError,
3082 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003083 self.call(test)
3084
3085 def test(a, b, c=10):
3086 return a, b, c
3087 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3088 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3089
3090 def test(a=1, b=2, c=3):
3091 return a, b, c
3092 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3093 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3094 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3095
3096 def test_signature_bind_varargs_order(self):
3097 def test(*args):
3098 return args
3099
3100 self.assertEqual(self.call(test), ())
3101 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3102
3103 def test_signature_bind_args_and_varargs(self):
3104 def test(a, b, c=3, *args):
3105 return a, b, c, args
3106
3107 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3108 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3109 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3110 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3111
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003112 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003113 "multiple values for argument 'c'"):
3114 self.call(test, 1, 2, 3, c=4)
3115
3116 def test_signature_bind_just_kwargs(self):
3117 def test(**kwargs):
3118 return kwargs
3119
3120 self.assertEqual(self.call(test), {})
3121 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3122 {'foo': 'bar', 'spam': 'ham'})
3123
3124 def test_signature_bind_args_and_kwargs(self):
3125 def test(a, b, c=3, **kwargs):
3126 return a, b, c, kwargs
3127
3128 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3129 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3130 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3131 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3132 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3133 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3134 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3135 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3136 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3137 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3138 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3139 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3140 (1, 2, 4, {'foo': 'bar'}))
3141 self.assertEqual(self.call(test, c=5, a=4, b=3),
3142 (4, 3, 5, {}))
3143
3144 def test_signature_bind_kwonly(self):
3145 def test(*, foo):
3146 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003147 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003148 'too many positional arguments'):
3149 self.call(test, 1)
3150 self.assertEqual(self.call(test, foo=1), 1)
3151
3152 def test(a, *, foo=1, bar):
3153 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003154 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003155 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003156 self.call(test, 1)
3157
3158 def test(foo, *, bar):
3159 return foo, bar
3160 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3161 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3162
Yury Selivanov86872752015-05-19 00:27:49 -04003163 with self.assertRaisesRegex(
3164 TypeError, "got an unexpected keyword argument 'spam'"):
3165
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003166 self.call(test, bar=2, foo=1, spam=10)
3167
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003168 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003169 'too many positional arguments'):
3170 self.call(test, 1, 2)
3171
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003172 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003173 'too many positional arguments'):
3174 self.call(test, 1, 2, bar=2)
3175
Yury Selivanov86872752015-05-19 00:27:49 -04003176 with self.assertRaisesRegex(
3177 TypeError, "got an unexpected keyword argument 'spam'"):
3178
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003179 self.call(test, 1, bar=2, spam='ham')
3180
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003181 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003182 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003183 self.call(test, 1)
3184
3185 def test(foo, *, bar, **bin):
3186 return foo, bar, bin
3187 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3188 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3189 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3190 (1, 2, {'spam': 'ham'}))
3191 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3192 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003193 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003194 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003195 self.call(test, spam='ham', bar=2)
3196 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3197 (1, 2, {'bin': 1, 'spam': 10}))
3198
3199 def test_signature_bind_arguments(self):
3200 def test(a, *args, b, z=100, **kwargs):
3201 pass
3202 sig = inspect.signature(test)
3203 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3204 # we won't have 'z' argument in the bound arguments object, as we didn't
3205 # pass it to the 'bind'
3206 self.assertEqual(tuple(ba.arguments.items()),
3207 (('a', 10), ('args', (20,)), ('b', 30),
3208 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3209 self.assertEqual(ba.kwargs,
3210 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3211 self.assertEqual(ba.args, (10, 20))
3212
3213 def test_signature_bind_positional_only(self):
3214 P = inspect.Parameter
3215
3216 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3217 return a_po, b_po, c_po, foo, bar, kwargs
3218
3219 sig = inspect.signature(test)
3220 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3221 for name in ('a_po', 'b_po', 'c_po'):
3222 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3223 new_sig = sig.replace(parameters=new_params.values())
3224 test.__signature__ = new_sig
3225
3226 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3227 (1, 2, 4, 5, 6, {}))
3228
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003229 self.assertEqual(self.call(test, 1, 2),
3230 (1, 2, 3, 42, 50, {}))
3231
3232 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3233 (1, 2, 3, 4, 5, {}))
3234
3235 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3236 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3237
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003238 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003239 self.call(test, 1, 2, c_po=4)
3240
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003241 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003242 self.call(test, a_po=1, b_po=2)
3243
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003244 def test_signature_bind_with_self_arg(self):
3245 # Issue #17071: one of the parameters is named "self
3246 def test(a, self, b):
3247 pass
3248 sig = inspect.signature(test)
3249 ba = sig.bind(1, 2, 3)
3250 self.assertEqual(ba.args, (1, 2, 3))
3251 ba = sig.bind(1, self=2, b=3)
3252 self.assertEqual(ba.args, (1, 2, 3))
3253
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003254 def test_signature_bind_vararg_name(self):
3255 def test(a, *args):
3256 return a, args
3257 sig = inspect.signature(test)
3258
Yury Selivanov86872752015-05-19 00:27:49 -04003259 with self.assertRaisesRegex(
3260 TypeError, "got an unexpected keyword argument 'args'"):
3261
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003262 sig.bind(a=0, args=1)
3263
3264 def test(*args, **kwargs):
3265 return args, kwargs
3266 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3267
3268 sig = inspect.signature(test)
3269 ba = sig.bind(args=1)
3270 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3271
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003272 @cpython_only
3273 def test_signature_bind_implicit_arg(self):
3274 # Issue #19611: getcallargs should work with set comprehensions
3275 def make_set():
3276 return {z * z for z in range(5)}
3277 setcomp_code = make_set.__code__.co_consts[1]
3278 setcomp_func = types.FunctionType(setcomp_code, {})
3279
3280 iterator = iter(range(5))
3281 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3282
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003283
3284class TestBoundArguments(unittest.TestCase):
3285 def test_signature_bound_arguments_unhashable(self):
3286 def foo(a): pass
3287 ba = inspect.signature(foo).bind(1)
3288
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003289 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003290 hash(ba)
3291
3292 def test_signature_bound_arguments_equality(self):
3293 def foo(a): pass
3294 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003295 self.assertTrue(ba == ba)
3296 self.assertFalse(ba != ba)
3297 self.assertTrue(ba == EqualsToAll())
3298 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003299
3300 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003301 self.assertTrue(ba == ba2)
3302 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003303
3304 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003305 self.assertFalse(ba == ba3)
3306 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003307 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003308 self.assertTrue(ba == ba3)
3309 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003310
3311 def bar(b): pass
3312 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003313 self.assertFalse(ba == ba4)
3314 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003315
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003316 def foo(*, a, b): pass
3317 sig = inspect.signature(foo)
3318 ba1 = sig.bind(a=1, b=2)
3319 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003320 self.assertTrue(ba1 == ba2)
3321 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003322
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003323 def test_signature_bound_arguments_pickle(self):
3324 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3325 sig = inspect.signature(foo)
3326 ba = sig.bind(20, 30, z={})
3327
3328 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3329 with self.subTest(pickle_ver=ver):
3330 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3331 self.assertEqual(ba, ba_pickled)
3332
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003333 def test_signature_bound_arguments_repr(self):
3334 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3335 sig = inspect.signature(foo)
3336 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003337 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003338
Yury Selivanovb907a512015-05-16 13:45:09 -04003339 def test_signature_bound_arguments_apply_defaults(self):
3340 def foo(a, b=1, *args, c:1={}, **kw): pass
3341 sig = inspect.signature(foo)
3342
3343 ba = sig.bind(20)
3344 ba.apply_defaults()
3345 self.assertEqual(
3346 list(ba.arguments.items()),
3347 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3348
3349 # Make sure that we preserve the order:
3350 # i.e. 'c' should be *before* 'kw'.
3351 ba = sig.bind(10, 20, 30, d=1)
3352 ba.apply_defaults()
3353 self.assertEqual(
3354 list(ba.arguments.items()),
3355 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3356
3357 # Make sure that BoundArguments produced by bind_partial()
3358 # are supported.
3359 def foo(a, b): pass
3360 sig = inspect.signature(foo)
3361 ba = sig.bind_partial(20)
3362 ba.apply_defaults()
3363 self.assertEqual(
3364 list(ba.arguments.items()),
3365 [('a', 20)])
3366
3367 # Test no args
3368 def foo(): pass
3369 sig = inspect.signature(foo)
3370 ba = sig.bind()
3371 ba.apply_defaults()
3372 self.assertEqual(list(ba.arguments.items()), [])
3373
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003374 # Make sure a no-args binding still acquires proper defaults.
3375 def foo(a='spam'): pass
3376 sig = inspect.signature(foo)
3377 ba = sig.bind()
3378 ba.apply_defaults()
3379 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3380
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003381
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003382class TestSignaturePrivateHelpers(unittest.TestCase):
3383 def test_signature_get_bound_param(self):
3384 getter = inspect._signature_get_bound_param
3385
3386 self.assertEqual(getter('($self)'), 'self')
3387 self.assertEqual(getter('($self, obj)'), 'self')
3388 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3389
Larry Hastings2623c8c2014-02-08 22:15:29 -08003390 def _strip_non_python_syntax(self, input,
3391 clean_signature, self_parameter, last_positional_only):
3392 computed_clean_signature, \
3393 computed_self_parameter, \
3394 computed_last_positional_only = \
3395 inspect._signature_strip_non_python_syntax(input)
3396 self.assertEqual(computed_clean_signature, clean_signature)
3397 self.assertEqual(computed_self_parameter, self_parameter)
3398 self.assertEqual(computed_last_positional_only, last_positional_only)
3399
3400 def test_signature_strip_non_python_syntax(self):
3401 self._strip_non_python_syntax(
3402 "($module, /, path, mode, *, dir_fd=None, " +
3403 "effective_ids=False,\n follow_symlinks=True)",
3404 "(module, path, mode, *, dir_fd=None, " +
3405 "effective_ids=False, follow_symlinks=True)",
3406 0,
3407 0)
3408
3409 self._strip_non_python_syntax(
3410 "($module, word, salt, /)",
3411 "(module, word, salt)",
3412 0,
3413 2)
3414
3415 self._strip_non_python_syntax(
3416 "(x, y=None, z=None, /)",
3417 "(x, y=None, z=None)",
3418 None,
3419 2)
3420
3421 self._strip_non_python_syntax(
3422 "(x, y=None, z=None)",
3423 "(x, y=None, z=None)",
3424 None,
3425 None)
3426
3427 self._strip_non_python_syntax(
3428 "(x,\n y=None,\n z = None )",
3429 "(x, y=None, z=None)",
3430 None,
3431 None)
3432
3433 self._strip_non_python_syntax(
3434 "",
3435 "",
3436 None,
3437 None)
3438
3439 self._strip_non_python_syntax(
3440 None,
3441 None,
3442 None,
3443 None)
3444
Nick Coghlan9c680b02015-04-13 12:54:54 -04003445class TestSignatureDefinitions(unittest.TestCase):
3446 # This test case provides a home for checking that particular APIs
3447 # have signatures available for introspection
3448
3449 @cpython_only
3450 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3451 "Signature information for builtins requires docstrings")
3452 def test_builtins_have_signatures(self):
3453 # This checks all builtin callables in CPython have signatures
3454 # A few have signatures Signature can't yet handle, so we skip those
3455 # since they will have to wait until PEP 457 adds the required
3456 # introspection support to the inspect module
3457 # Some others also haven't been converted yet for various other
3458 # reasons, so we also skip those for the time being, but design
3459 # the test to fail in order to indicate when it needs to be
3460 # updated.
3461 no_signature = set()
3462 # These need PEP 457 groups
3463 needs_groups = {"range", "slice", "dir", "getattr",
3464 "next", "iter", "vars"}
3465 no_signature |= needs_groups
3466 # These need PEP 457 groups or a signature change to accept None
3467 needs_semantic_update = {"round"}
3468 no_signature |= needs_semantic_update
3469 # These need *args support in Argument Clinic
3470 needs_varargs = {"min", "max", "print", "__build_class__"}
3471 no_signature |= needs_varargs
3472 # These simply weren't covered in the initial AC conversion
3473 # for builtin callables
3474 not_converted_yet = {"open", "__import__"}
3475 no_signature |= not_converted_yet
3476 # These builtin types are expected to provide introspection info
3477 types_with_signatures = set()
3478 # Check the signatures we expect to be there
3479 ns = vars(builtins)
3480 for name, obj in sorted(ns.items()):
3481 if not callable(obj):
3482 continue
3483 # The builtin types haven't been converted to AC yet
3484 if isinstance(obj, type) and (name not in types_with_signatures):
3485 # Note that this also skips all the exception types
3486 no_signature.add(name)
3487 if (name in no_signature):
3488 # Not yet converted
3489 continue
3490 with self.subTest(builtin=name):
3491 self.assertIsNotNone(inspect.signature(obj))
3492 # Check callables that haven't been converted don't claim a signature
3493 # This ensures this test will start failing as more signatures are
3494 # added, so the affected items can be moved into the scope of the
3495 # regression test above
3496 for name in no_signature:
3497 with self.subTest(builtin=name):
3498 self.assertIsNone(obj.__text_signature__)
3499
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003500
Nick Coghlane8c45d62013-07-28 20:00:01 +10003501class TestUnwrap(unittest.TestCase):
3502
3503 def test_unwrap_one(self):
3504 def func(a, b):
3505 return a + b
3506 wrapper = functools.lru_cache(maxsize=20)(func)
3507 self.assertIs(inspect.unwrap(wrapper), func)
3508
3509 def test_unwrap_several(self):
3510 def func(a, b):
3511 return a + b
3512 wrapper = func
3513 for __ in range(10):
3514 @functools.wraps(wrapper)
3515 def wrapper():
3516 pass
3517 self.assertIsNot(wrapper.__wrapped__, func)
3518 self.assertIs(inspect.unwrap(wrapper), func)
3519
3520 def test_stop(self):
3521 def func1(a, b):
3522 return a + b
3523 @functools.wraps(func1)
3524 def func2():
3525 pass
3526 @functools.wraps(func2)
3527 def wrapper():
3528 pass
3529 func2.stop_here = 1
3530 unwrapped = inspect.unwrap(wrapper,
3531 stop=(lambda f: hasattr(f, "stop_here")))
3532 self.assertIs(unwrapped, func2)
3533
3534 def test_cycle(self):
3535 def func1(): pass
3536 func1.__wrapped__ = func1
3537 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3538 inspect.unwrap(func1)
3539
3540 def func2(): pass
3541 func2.__wrapped__ = func1
3542 func1.__wrapped__ = func2
3543 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3544 inspect.unwrap(func1)
3545 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3546 inspect.unwrap(func2)
3547
3548 def test_unhashable(self):
3549 def func(): pass
3550 func.__wrapped__ = None
3551 class C:
3552 __hash__ = None
3553 __wrapped__ = func
3554 self.assertIsNone(inspect.unwrap(C()))
3555
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003556class TestMain(unittest.TestCase):
3557 def test_only_source(self):
3558 module = importlib.import_module('unittest')
3559 rc, out, err = assert_python_ok('-m', 'inspect',
3560 'unittest')
3561 lines = out.decode().splitlines()
3562 # ignore the final newline
3563 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3564 self.assertEqual(err, b'')
3565
Yury Selivanov42407ab2014-06-23 10:23:50 -07003566 def test_custom_getattr(self):
3567 def foo():
3568 pass
3569 foo.__signature__ = 42
3570 with self.assertRaises(TypeError):
3571 inspect.signature(foo)
3572
Brett Cannon634a8fc2013-10-02 10:25:42 -04003573 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003574 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003575 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003576 rc, out, err = assert_python_ok('-m', 'inspect',
3577 'concurrent.futures:ThreadPoolExecutor')
3578 lines = out.decode().splitlines()
3579 # ignore the final newline
3580 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003581 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003582 self.assertEqual(err, b'')
3583
3584 def test_builtins(self):
3585 module = importlib.import_module('unittest')
3586 _, out, err = assert_python_failure('-m', 'inspect',
3587 'sys')
3588 lines = err.decode().splitlines()
3589 self.assertEqual(lines, ["Can't get info for builtin modules."])
3590
3591 def test_details(self):
3592 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003593 args = support.optim_args_from_interpreter_flags()
3594 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003595 'unittest', '--details')
3596 output = out.decode()
3597 # Just a quick sanity check on the output
3598 self.assertIn(module.__name__, output)
3599 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003600 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003601 self.assertEqual(err, b'')
3602
3603
Yury Selivanovef1e7502014-12-08 16:05:34 -05003604class TestReload(unittest.TestCase):
3605
3606 src_before = textwrap.dedent("""\
3607def foo():
3608 print("Bla")
3609 """)
3610
3611 src_after = textwrap.dedent("""\
3612def foo():
3613 print("Oh no!")
3614 """)
3615
3616 def assertInspectEqual(self, path, source):
3617 inspected_src = inspect.getsource(source)
3618 with open(path) as src:
3619 self.assertEqual(
3620 src.read().splitlines(True),
3621 inspected_src.splitlines(True)
3622 )
3623
3624 def test_getsource_reload(self):
3625 # see issue 1218234
3626 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3627 module = importlib.import_module(name)
3628 self.assertInspectEqual(path, module)
3629 with open(path, 'w') as src:
3630 src.write(self.src_after)
3631 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003632
Nick Coghlane8c45d62013-07-28 20:00:01 +10003633
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003634def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003635 run_unittest(
3636 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3637 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3638 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003639 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003640 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003641 TestBoundArguments, TestSignaturePrivateHelpers,
3642 TestSignatureDefinitions,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003643 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
3644 TestGetCoroutineState
Michael Foord95fc51d2010-11-20 15:07:30 +00003645 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003646
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003647if __name__ == "__main__":
3648 test_main()