blob: 97634e591cabe38b3caba5e0babebc465e7a76c2 [file] [log] [blame]
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001import builtins
Guido van Rossum813b0e52007-05-21 18:11:34 +00002import collections
Larry Hastings5c661892014-01-24 06:17:25 -08003import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10004import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10005import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08006import inspect
7import io
8import linecache
9import os
Christian Heimesa3538eb2007-11-06 11:44:48 +000010from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080011import _pickle
Yury Selivanova5d63dd2014-03-27 11:31:43 -040012import pickle
Larry Hastings5c661892014-01-24 06:17:25 -080013import re
14import shutil
15import sys
16import types
Yury Selivanovef1e7502014-12-08 16:05:34 -050017import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080018import unicodedata
19import unittest
Yury Selivanova773de02014-02-21 18:30:53 -050020import unittest.mock
Yury Selivanov75445082015-05-11 22:57:16 -040021import warnings
Larry Hastings5c661892014-01-24 06:17:25 -080022
Brett Cannon634a8fc2013-10-02 10:25:42 -040023try:
24 from concurrent.futures import ThreadPoolExecutor
25except ImportError:
26 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000027
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020028from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Nick Coghlanf9e227e2014-08-17 14:01:19 +100029from test.support import MISSING_C_DOCSTRINGS, cpython_only
Berker Peksagce643912015-05-06 06:33:17 +030030from test.support.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000031from test import inspect_fodder as mod
32from test import inspect_fodder2 as mod2
Victor Stinner9def2842016-01-18 12:15:08 +010033from test import support
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000034
Yury Selivanovef1e7502014-12-08 16:05:34 -050035from test.test_import import _ready_to_import
36
R. David Murray74b89242009-05-13 17:33:03 +000037
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000038# Functions tested in this suite:
39# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000040# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
41# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
Berker Peksagfa3922c2015-07-31 04:11:29 +030042# getclasstree, getargvalues, formatargspec, formatargvalues,
Christian Heimes7131fd92008-02-19 14:21:46 +000043# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000044
Nick Coghlanf088e5e2008-12-14 11:50:48 +000045# NOTE: There are some additional tests relating to interaction with
46# zipimport in the test_zipimport_support test module.
47
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000048modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000049if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000050 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000051
Christian Heimesa3538eb2007-11-06 11:44:48 +000052# Normalize file names: on Windows, the case of file names of compiled
53# modules depends on the path used to start the python executable.
54modfile = normcase(modfile)
55
56def revise(filename, *args):
57 return (normcase(filename),) + args
58
Georg Brandl1a3284e2007-12-02 09:40:06 +000059import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000060
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000061git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000062
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000063class IsTestBase(unittest.TestCase):
64 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
65 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000066 inspect.ismodule, inspect.istraceback,
Yury Selivanov75445082015-05-11 22:57:16 -040067 inspect.isgenerator, inspect.isgeneratorfunction,
Yury Selivanoveb636452016-09-08 22:01:51 -070068 inspect.iscoroutine, inspect.iscoroutinefunction,
69 inspect.isasyncgen, inspect.isasyncgenfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000070
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000071 def istest(self, predicate, exp):
72 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000073 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000074
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000075 for other in self.predicates - set([predicate]):
Yury Selivanov75445082015-05-11 22:57:16 -040076 if (predicate == inspect.isgeneratorfunction or \
Yury Selivanoveb636452016-09-08 22:01:51 -070077 predicate == inspect.isasyncgenfunction or \
Yury Selivanov75445082015-05-11 22:57:16 -040078 predicate == inspect.iscoroutinefunction) and \
Christian Heimes7131fd92008-02-19 14:21:46 +000079 other == inspect.isfunction:
80 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000081 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000082
Christian Heimes7131fd92008-02-19 14:21:46 +000083def generator_function_example(self):
84 for i in range(2):
85 yield i
86
Yury Selivanoveb636452016-09-08 22:01:51 -070087async def async_generator_function_example(self):
88 async for i in range(2):
89 yield i
90
Yury Selivanov75445082015-05-11 22:57:16 -040091async def coroutine_function_example(self):
92 return 'spam'
93
94@types.coroutine
95def gen_coroutine_function_example(self):
96 yield
97 return 'spam'
98
Serhiy Storchaka3018cc42015-07-18 23:19:05 +030099class EqualsToAll:
100 def __eq__(self, other):
101 return True
Yury Selivanova5d63dd2014-03-27 11:31:43 -0400102
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000103class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +0000104
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000105 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200106 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000107 self.istest(inspect.isbuiltin, 'sys.exit')
108 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +0000109 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200110 try:
111 1/0
112 except:
113 tb = sys.exc_info()[2]
114 self.istest(inspect.isframe, 'tb.tb_frame')
115 self.istest(inspect.istraceback, 'tb')
116 if hasattr(types, 'GetSetDescriptorType'):
117 self.istest(inspect.isgetsetdescriptor,
118 'type(tb.tb_frame).f_locals')
119 else:
120 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
121 finally:
122 # Clear traceback and all the frames and local variables hanging to it.
123 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000124 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000125 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000126 self.istest(inspect.ismethod, 'git.argue')
127 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000128 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000129 self.istest(inspect.isgenerator, '(x for x in range(2))')
130 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanoveb636452016-09-08 22:01:51 -0700131 self.istest(inspect.isasyncgen,
132 'async_generator_function_example(1)')
133 self.istest(inspect.isasyncgenfunction,
134 'async_generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400135
136 with warnings.catch_warnings():
137 warnings.simplefilter("ignore")
138 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
139 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
140
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000141 if hasattr(types, 'MemberDescriptorType'):
142 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
143 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000144 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000145
Yury Selivanov75445082015-05-11 22:57:16 -0400146 def test_iscoroutine(self):
147 gen_coro = gen_coroutine_function_example(1)
148 coro = coroutine_function_example(1)
149
Yury Selivanov5376ba92015-06-22 12:19:30 -0400150 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400151 inspect.iscoroutinefunction(gen_coroutine_function_example))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400152 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400153
154 self.assertTrue(
155 inspect.isgeneratorfunction(gen_coroutine_function_example))
156 self.assertTrue(inspect.isgenerator(gen_coro))
157
158 self.assertTrue(
159 inspect.iscoroutinefunction(coroutine_function_example))
160 self.assertTrue(inspect.iscoroutine(coro))
161
162 self.assertFalse(
163 inspect.isgeneratorfunction(coroutine_function_example))
164 self.assertFalse(inspect.isgenerator(coro))
165
166 coro.close(); gen_coro.close() # silence warnings
167
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400168 def test_isawaitable(self):
169 def gen(): yield
170 self.assertFalse(inspect.isawaitable(gen()))
171
172 coro = coroutine_function_example(1)
173 gen_coro = gen_coroutine_function_example(1)
174
175 self.assertTrue(inspect.isawaitable(coro))
176 self.assertTrue(inspect.isawaitable(gen_coro))
177
178 class Future:
179 def __await__():
180 pass
181 self.assertTrue(inspect.isawaitable(Future()))
182 self.assertFalse(inspect.isawaitable(Future))
183
184 class NotFuture: pass
185 not_fut = NotFuture()
186 not_fut.__await__ = lambda: None
187 self.assertFalse(inspect.isawaitable(not_fut))
188
189 coro.close(); gen_coro.close() # silence warnings
190
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000191 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000192 self.assertTrue(inspect.isroutine(mod.spam))
193 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000194
Benjamin Petersonc4656002009-01-17 22:41:18 +0000195 def test_isclass(self):
196 self.istest(inspect.isclass, 'mod.StupidGit')
197 self.assertTrue(inspect.isclass(list))
198
199 class CustomGetattr(object):
200 def __getattr__(self, attr):
201 return None
202 self.assertFalse(inspect.isclass(CustomGetattr()))
203
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000204 def test_get_slot_members(self):
205 class C(object):
206 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000207 x = C()
208 x.a = 42
209 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000210 self.assertIn('a', members)
211 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000212
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000213 def test_isabstract(self):
214 from abc import ABCMeta, abstractmethod
215
216 class AbstractClassExample(metaclass=ABCMeta):
217
218 @abstractmethod
219 def foo(self):
220 pass
221
222 class ClassExample(AbstractClassExample):
223 def foo(self):
224 pass
225
226 a = ClassExample()
227
228 # Test general behaviour.
229 self.assertTrue(inspect.isabstract(AbstractClassExample))
230 self.assertFalse(inspect.isabstract(ClassExample))
231 self.assertFalse(inspect.isabstract(a))
232 self.assertFalse(inspect.isabstract(int))
233 self.assertFalse(inspect.isabstract(5))
234
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000235
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000236class TestInterpreterStack(IsTestBase):
237 def __init__(self, *args, **kwargs):
238 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000239
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000240 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000241
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000242 def test_abuse_done(self):
243 self.istest(inspect.istraceback, 'git.ex[2]')
244 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000245
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000246 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000247 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000248 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000249 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000250 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000251 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000252 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000253 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000254 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000255 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400256 # Test named tuple fields
257 record = mod.st[0]
258 self.assertIs(record.frame, mod.fr)
259 self.assertEqual(record.lineno, 16)
260 self.assertEqual(record.filename, mod.__file__)
261 self.assertEqual(record.function, 'eggs')
262 self.assertIn('inspect.stack()', record.code_context[0])
263 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000264
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000265 def test_trace(self):
266 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000267 self.assertEqual(revise(*git.tr[0][1:]),
268 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
269 self.assertEqual(revise(*git.tr[1][1:]),
270 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
271 self.assertEqual(revise(*git.tr[2][1:]),
272 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000273
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000274 def test_frame(self):
275 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
276 self.assertEqual(args, ['x', 'y'])
277 self.assertEqual(varargs, None)
278 self.assertEqual(varkw, None)
279 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
280 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
281 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000282
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000283 def test_previous_frame(self):
284 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000285 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000286 self.assertEqual(varargs, 'g')
287 self.assertEqual(varkw, 'h')
288 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000289 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000290
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000291class GetSourceBase(unittest.TestCase):
292 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000293 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000294
Yury Selivanov6738b112015-05-16 10:10:21 -0400295 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000296 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000297 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000298
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000299 def sourcerange(self, top, bottom):
300 lines = self.source.split("\n")
301 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000302
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000303 def assertSourceEqual(self, obj, top, bottom):
304 self.assertEqual(inspect.getsource(obj),
305 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000306
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000307class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000308 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000309
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000310 def test_getclasses(self):
311 classes = inspect.getmembers(mod, inspect.isclass)
312 self.assertEqual(classes,
313 [('FesteringGob', mod.FesteringGob),
314 ('MalodorousPervert', mod.MalodorousPervert),
315 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300316 ('StupidGit', mod.StupidGit),
317 ('Tit', mod.MalodorousPervert),
318 ])
319 tree = inspect.getclasstree([cls[1] for cls in classes])
320 self.assertEqual(tree,
321 [(object, ()),
322 [(mod.ParrotDroppings, (object,)),
323 [(mod.FesteringGob, (mod.MalodorousPervert,
324 mod.ParrotDroppings))
325 ],
326 (mod.StupidGit, (object,)),
327 [(mod.MalodorousPervert, (mod.StupidGit,)),
328 [(mod.FesteringGob, (mod.MalodorousPervert,
329 mod.ParrotDroppings))
330 ]
331 ]
332 ]
333 ])
334 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000335 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000336 [(object, ()),
337 [(mod.ParrotDroppings, (object,)),
338 (mod.StupidGit, (object,)),
339 [(mod.MalodorousPervert, (mod.StupidGit,)),
340 [(mod.FesteringGob, (mod.MalodorousPervert,
341 mod.ParrotDroppings))
342 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000343 ]
344 ]
345 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000346
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000347 def test_getfunctions(self):
348 functions = inspect.getmembers(mod, inspect.isfunction)
349 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300350 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000351 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000352
R. David Murray378c0cf2010-02-24 01:46:21 +0000353 @unittest.skipIf(sys.flags.optimize >= 2,
354 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000355 def test_getdoc(self):
356 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
357 self.assertEqual(inspect.getdoc(mod.StupidGit),
358 'A longer,\n\nindented\n\ndocstring.')
359 self.assertEqual(inspect.getdoc(git.abuse),
360 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000361
Serhiy Storchaka5cf2b7252015-04-03 22:38:53 +0300362 @unittest.skipIf(sys.flags.optimize >= 2,
363 "Docstrings are omitted with -O2 and above")
364 def test_getdoc_inherited(self):
365 self.assertEqual(inspect.getdoc(mod.FesteringGob),
366 'A longer,\n\nindented\n\ndocstring.')
367 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
368 'Another\n\ndocstring\n\ncontaining\n\ntabs')
369 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
370 'Another\n\ndocstring\n\ncontaining\n\ntabs')
371 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
372 'The automatic gainsaying.')
373
374 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
375 def test_finddoc(self):
376 finddoc = inspect._finddoc
377 self.assertEqual(finddoc(int), int.__doc__)
378 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
379 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
380 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
381 self.assertEqual(finddoc(int.real), int.real.__doc__)
382
Georg Brandl0c77a822008-06-10 16:37:50 +0000383 def test_cleandoc(self):
384 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
385 'An\nindented\ndocstring.')
386
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000387 def test_getcomments(self):
388 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
389 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000390
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000391 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000392 # Check actual module
393 self.assertEqual(inspect.getmodule(mod), mod)
394 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000395 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000396 # Check a method (no __module__ attribute, falls back to filename)
397 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
398 # Do it again (check the caching isn't broken)
399 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
400 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000401 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000402 # Check filename override
403 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000404
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000405 def test_getsource(self):
406 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200407 self.assertSourceEqual(mod.StupidGit, 21, 51)
408 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000409
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000410 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000411 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
412 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000413 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100414 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000415 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000416 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200417 try:
418 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
419 finally:
420 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000421
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000422 def test_getfile(self):
423 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000424
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500425 def test_getfile_class_without_module(self):
426 class CM(type):
427 @property
428 def __module__(cls):
429 raise AttributeError
430 class C(metaclass=CM):
431 pass
432 with self.assertRaises(TypeError):
433 inspect.getfile(C)
434
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000435 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000436 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000437 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000438 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000439 m.__file__ = "<string>" # hopefully not a real filename...
440 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000441 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000442 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000443 del sys.modules[name]
444 inspect.getmodule(compile('a=10','','single'))
445
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500446 def test_proceed_with_fake_filename(self):
447 '''doctest monkeypatches linecache to enable inspection'''
448 fn, source = '<test>', 'def x(): pass\n'
449 getlines = linecache.getlines
450 def monkey(filename, module_globals=None):
451 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300452 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500453 else:
454 return getlines(filename, module_globals)
455 linecache.getlines = monkey
456 try:
457 ns = {}
458 exec(compile(source, fn, 'single'), ns)
459 inspect.getsource(ns["x"])
460 finally:
461 linecache.getlines = getlines
462
Antoine Pitroua8723a02015-04-15 00:41:29 +0200463 def test_getsource_on_code_object(self):
464 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
465
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000466class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000467 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000468
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000469 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000470 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000471
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000472 def test_replacing_decorator(self):
473 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000474
Yury Selivanov081bbf62014-09-26 17:34:54 -0400475 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200476 self.assertSourceEqual(mod2.real, 130, 132)
477
478 def test_decorator_with_lambda(self):
479 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400480
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000481class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000482 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000483 def test_oneline_lambda(self):
484 # Test inspect.getsource with a one-line lambda function.
485 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000486
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000487 def test_threeline_lambda(self):
488 # Test inspect.getsource with a three-line lambda function,
489 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000490 self.assertSourceEqual(mod2.tll, 28, 30)
491
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000492 def test_twoline_indented_lambda(self):
493 # Test inspect.getsource with a two-line lambda function,
494 # where the second line _is_ indented.
495 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000496
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000497 def test_onelinefunc(self):
498 # Test inspect.getsource with a regular one-line function.
499 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000500
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000501 def test_manyargs(self):
502 # Test inspect.getsource with a regular function where
503 # the arguments are on two lines and _not_ indented and
504 # the body on the second line with the last arguments.
505 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000506
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000507 def test_twolinefunc(self):
508 # Test inspect.getsource with a regular function where
509 # the body is on two lines, following the argument list and
510 # continued on the next line by a \\.
511 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000512
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000513 def test_lambda_in_list(self):
514 # Test inspect.getsource with a one-line lambda function
515 # defined in a list, indented.
516 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000517
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000518 def test_anonymous(self):
519 # Test inspect.getsource with a lambda function defined
520 # as argument to another function.
521 self.assertSourceEqual(mod2.anonymous, 55, 55)
522
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000523class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000524 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000525
526 def test_with_comment(self):
527 self.assertSourceEqual(mod2.with_comment, 58, 59)
528
529 def test_multiline_sig(self):
530 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
531
Armin Rigodd5c0232005-09-25 11:45:45 +0000532 def test_nested_class(self):
533 self.assertSourceEqual(mod2.func69().func71, 71, 72)
534
535 def test_one_liner_followed_by_non_name(self):
536 self.assertSourceEqual(mod2.func77, 77, 77)
537
538 def test_one_liner_dedent_non_name(self):
539 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
540
541 def test_with_comment_instead_of_docstring(self):
542 self.assertSourceEqual(mod2.func88, 88, 90)
543
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000544 def test_method_in_dynamic_class(self):
545 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
546
R David Murray32562d72014-10-03 11:15:38 -0400547 # This should not skip for CPython, but might on a repackaged python where
548 # unicodedata is not an external module, or on pypy.
549 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
550 unicodedata.__file__.endswith('.py'),
551 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000552 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200553 self.assertRaises(OSError, inspect.getsource, unicodedata)
554 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000555
R. David Murraya1b37402010-06-17 02:04:29 +0000556 def test_findsource_code_in_linecache(self):
557 lines = ["x=1"]
558 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200559 self.assertRaises(OSError, inspect.findsource, co)
560 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000561 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200562 try:
563 self.assertEqual(inspect.findsource(co), (lines,0))
564 self.assertEqual(inspect.getsource(co), lines[0])
565 finally:
566 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000567
Ezio Melotti1b145922013-03-30 05:17:24 +0200568 def test_findsource_without_filename(self):
569 for fname in ['', '<string>']:
570 co = compile('x=1', fname, "exec")
571 self.assertRaises(IOError, inspect.findsource, co)
572 self.assertRaises(IOError, inspect.getsource, co)
573
Antoine Pitroua8723a02015-04-15 00:41:29 +0200574 def test_getsource_on_method(self):
575 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
576
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300577 def test_nested_func(self):
578 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
579
580
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000581class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400582 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000583 self.tempdir = TESTFN + '_dir'
584 os.mkdir(self.tempdir)
585 with open(os.path.join(self.tempdir,
586 'inspect_fodder3%spy' % os.extsep), 'w') as f:
587 f.write("class X:\n pass # No EOL")
588 with DirsOnSysPath(self.tempdir):
589 import inspect_fodder3 as mod3
590 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400591 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000592
593 def tearDown(self):
594 shutil.rmtree(self.tempdir)
595
596 def test_class(self):
597 self.assertSourceEqual(self.fodderModule.X, 1, 2)
598
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100599
600class _BrokenDataDescriptor(object):
601 """
602 A broken data descriptor. See bug #1785.
603 """
604 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700605 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100606
607 def __set__(*args):
608 raise RuntimeError
609
610 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700611 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100612
613
614class _BrokenMethodDescriptor(object):
615 """
616 A broken method descriptor. See bug #1785.
617 """
618 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700619 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100620
621 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700622 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100623
624
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000625# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000626def attrs_wo_objs(cls):
627 return [t[:3] for t in inspect.classify_class_attrs(cls)]
628
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100629
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000630class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000631 def test_newstyle_mro(self):
632 # The same w/ new-class MRO.
633 class A(object): pass
634 class B(A): pass
635 class C(A): pass
636 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000637
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000638 expected = (D, B, C, A, object)
639 got = inspect.getmro(D)
640 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000641
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500642 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
643 varkw_e=None, defaults_e=None, formatted=None):
644 with self.assertWarns(DeprecationWarning):
645 args, varargs, varkw, defaults = inspect.getargspec(routine)
646 self.assertEqual(args, args_e)
647 self.assertEqual(varargs, varargs_e)
648 self.assertEqual(varkw, varkw_e)
649 self.assertEqual(defaults, defaults_e)
650 if formatted is not None:
651 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
652 formatted)
653
Christian Heimes3795b532007-11-08 13:48:53 +0000654 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
655 varkw_e=None, defaults_e=None,
656 kwonlyargs_e=[], kwonlydefaults_e=None,
657 ann_e={}, formatted=None):
658 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
659 inspect.getfullargspec(routine)
660 self.assertEqual(args, args_e)
661 self.assertEqual(varargs, varargs_e)
662 self.assertEqual(varkw, varkw_e)
663 self.assertEqual(defaults, defaults_e)
664 self.assertEqual(kwonlyargs, kwonlyargs_e)
665 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
666 self.assertEqual(ann, ann_e)
667 if formatted is not None:
668 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
669 kwonlyargs, kwonlydefaults, ann),
670 formatted)
671
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500672 def test_getargspec(self):
673 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
674
675 self.assertArgSpecEquals(mod.spam,
676 ['a', 'b', 'c', 'd', 'e', 'f'],
677 'g', 'h', (3, 4, 5),
678 '(a, b, c, d=3, e=4, f=5, *g, **h)')
679
680 self.assertRaises(ValueError, self.assertArgSpecEquals,
681 mod2.keyworded, [])
682
683 self.assertRaises(ValueError, self.assertArgSpecEquals,
684 mod2.annotated, [])
685 self.assertRaises(ValueError, self.assertArgSpecEquals,
686 mod2.keyword_only_arg, [])
687
688
Christian Heimes3795b532007-11-08 13:48:53 +0000689 def test_getfullargspec(self):
690 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
691 kwonlyargs_e=['arg2'],
692 kwonlydefaults_e={'arg2':1},
693 formatted='(*arg1, arg2=1)')
694
695 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000696 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000697 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000698 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
699 kwonlyargs_e=['arg'],
700 formatted='(*, arg)')
701
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500702 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500703 # Issue 20684: low level introspection API must ignore __wrapped__
704 @functools.wraps(mod.spam)
705 def ham(x, y):
706 pass
707 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500708 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500709 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
710 self.assertFullArgSpecEquals(functools.partial(ham),
711 ['x', 'y'], formatted='(x, y)')
712 # Other variants
713 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500714 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
715 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500716 class C:
717 @functools.wraps(mod.spam)
718 def ham(self, x, y):
719 pass
720 pham = functools.partialmethod(ham)
721 @functools.wraps(mod.spam)
722 def __call__(self, x, y):
723 pass
724 check_method(C())
725 check_method(C.ham)
726 check_method(C().ham)
727 check_method(C.pham)
728 check_method(C().pham)
729
730 class C_new:
731 @functools.wraps(mod.spam)
732 def __new__(self, x, y):
733 pass
734 check_method(C_new)
735
736 class C_init:
737 @functools.wraps(mod.spam)
738 def __init__(self, x, y):
739 pass
740 check_method(C_init)
741
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500742 def test_getfullargspec_signature_attr(self):
743 def test():
744 pass
745 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
746 test.__signature__ = inspect.Signature(parameters=(spam_param,))
747
748 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
749
Yury Selivanov4cb93912014-01-29 11:54:12 -0500750 def test_getfullargspec_signature_annos(self):
751 def test(a:'spam') -> 'ham': pass
752 spec = inspect.getfullargspec(test)
753 self.assertEqual(test.__annotations__, spec.annotations)
754
755 def test(): pass
756 spec = inspect.getfullargspec(test)
757 self.assertEqual(test.__annotations__, spec.annotations)
758
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500759 @unittest.skipIf(MISSING_C_DOCSTRINGS,
760 "Signature information for builtins requires docstrings")
761 def test_getfullargspec_builtin_methods(self):
762 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
763 args_e=['self', 'obj'], formatted='(self, obj)')
764
765 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
766 args_e=['self', 'obj'], formatted='(self, obj)')
767
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500768 self.assertFullArgSpecEquals(
769 os.stat,
770 args_e=['path'],
771 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
772 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
773 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
774
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200775 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500776 @unittest.skipIf(MISSING_C_DOCSTRINGS,
777 "Signature information for builtins requires docstrings")
778 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200779 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500780 builtin = _testcapi.docstring_with_signature_with_defaults
781 spec = inspect.getfullargspec(builtin)
782 self.assertEqual(spec.defaults[0], 'avocado')
783
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200784 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500785 @unittest.skipIf(MISSING_C_DOCSTRINGS,
786 "Signature information for builtins requires docstrings")
787 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200788 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500789 builtin = _testcapi.docstring_no_signature
790 with self.assertRaises(TypeError):
791 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000792
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500793 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000794 class A(object):
795 def m(self):
796 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500797 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000798
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000799 def test_classify_newstyle(self):
800 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000801
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000802 def s(): pass
803 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000804
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000805 def c(cls): pass
806 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000807
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000808 def getp(self): pass
809 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000810
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000811 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000812
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000813 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000814
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000815 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000816
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100817 dd = _BrokenDataDescriptor()
818 md = _BrokenMethodDescriptor()
819
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000820 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500821
822 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
823 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
824
Benjamin Peterson577473f2010-01-19 00:09:57 +0000825 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
826 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
827 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000828 self.assertIn(('m', 'method', A), attrs,
829 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000830 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
831 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100832 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
833 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000834
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000835 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000836
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000837 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000838
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000839 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000840 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
841 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
842 self.assertIn(('p', 'property', A), attrs, 'missing property')
843 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
844 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
845 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100846 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
847 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000848
849
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000850 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000851
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000852 def m(self): pass
853 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000854
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000855 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000856 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
857 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
858 self.assertIn(('p', 'property', A), attrs, 'missing property')
859 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
860 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
861 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100862 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
863 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000864
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000865 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000866
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000867 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000868
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000869 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000870 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
871 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
872 self.assertIn(('p', 'property', A), attrs, 'missing property')
873 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
874 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
875 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100876 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
877 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
878
879 def test_classify_builtin_types(self):
880 # Simple sanity check that all built-in types can have their
881 # attributes classified.
882 for name in dir(__builtins__):
883 builtin = getattr(__builtins__, name)
884 if isinstance(builtin, type):
885 inspect.classify_class_attrs(builtin)
886
Ethan Furman63c141c2013-10-18 00:27:39 -0700887 def test_classify_DynamicClassAttribute(self):
888 class Meta(type):
889 def __getattr__(self, name):
890 if name == 'ham':
891 return 'spam'
892 return super().__getattr__(name)
893 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700894 @types.DynamicClassAttribute
895 def ham(self):
896 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700897 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
898 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700899 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700900 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
901
Yury Selivanovbf341fb2015-05-21 15:41:57 -0400902 def test_classify_overrides_bool(self):
903 class NoBool(object):
904 def __eq__(self, other):
905 return NoBool()
906
907 def __bool__(self):
908 raise NotImplementedError(
909 "This object does not specify a boolean value")
910
911 class HasNB(object):
912 dd = NoBool()
913
914 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
915 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
916
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700917 def test_classify_metaclass_class_attribute(self):
918 class Meta(type):
919 fish = 'slap'
920 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200921 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700922 class Class(metaclass=Meta):
923 pass
924 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
925 self.assertIn(should_find, inspect.classify_class_attrs(Class))
926
Ethan Furman63c141c2013-10-18 00:27:39 -0700927 def test_classify_VirtualAttribute(self):
928 class Meta(type):
929 def __dir__(cls):
930 return ['__class__', '__module__', '__name__', 'BOOM']
931 def __getattr__(self, name):
932 if name =='BOOM':
933 return 42
934 return super().__getattr(name)
935 class Class(metaclass=Meta):
936 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700937 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700938 self.assertIn(should_find, inspect.classify_class_attrs(Class))
939
940 def test_classify_VirtualAttribute_multi_classes(self):
941 class Meta1(type):
942 def __dir__(cls):
943 return ['__class__', '__module__', '__name__', 'one']
944 def __getattr__(self, name):
945 if name =='one':
946 return 1
947 return super().__getattr__(name)
948 class Meta2(type):
949 def __dir__(cls):
950 return ['__class__', '__module__', '__name__', 'two']
951 def __getattr__(self, name):
952 if name =='two':
953 return 2
954 return super().__getattr__(name)
955 class Meta3(Meta1, Meta2):
956 def __dir__(cls):
957 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
958 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
959 def __getattr__(self, name):
960 if name =='three':
961 return 3
962 return super().__getattr__(name)
963 class Class1(metaclass=Meta1):
964 pass
965 class Class2(Class1, metaclass=Meta3):
966 pass
967
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700968 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
969 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
970 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700971 cca = inspect.classify_class_attrs(Class2)
972 for sf in (should_find1, should_find2, should_find3):
973 self.assertIn(sf, cca)
974
975 def test_classify_class_attrs_with_buggy_dir(self):
976 class M(type):
977 def __dir__(cls):
978 return ['__class__', '__name__', 'missing']
979 class C(metaclass=M):
980 pass
981 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
982 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700983
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100984 def test_getmembers_descriptors(self):
985 class A(object):
986 dd = _BrokenDataDescriptor()
987 md = _BrokenMethodDescriptor()
988
989 def pred_wrapper(pred):
990 # A quick'n'dirty way to discard standard attributes of new-style
991 # classes.
992 class Empty(object):
993 pass
994 def wrapped(x):
995 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
996 return False
997 return pred(x)
998 return wrapped
999
1000 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1001 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1002
1003 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1004 [('md', A.__dict__['md'])])
1005 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1006 [('dd', A.__dict__['dd'])])
1007
1008 class B(A):
1009 pass
1010
1011 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1012 [('md', A.__dict__['md'])])
1013 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1014 [('dd', A.__dict__['dd'])])
1015
Antoine Pitrou0c603812012-01-18 17:40:18 +01001016 def test_getmembers_method(self):
1017 class B:
1018 def f(self):
1019 pass
1020
1021 self.assertIn(('f', B.f), inspect.getmembers(B))
1022 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1023 b = B()
1024 self.assertIn(('f', b.f), inspect.getmembers(b))
1025 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1026
Ethan Furmane03ea372013-09-25 07:14:41 -07001027 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001028 class M(type):
1029 def __getattr__(cls, name):
1030 if name == 'eggs':
1031 return 'scrambled'
1032 return super().__getattr__(name)
1033 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001034 @types.DynamicClassAttribute
1035 def eggs(self):
1036 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001037 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1038 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1039
1040 def test_getmembers_with_buggy_dir(self):
1041 class M(type):
1042 def __dir__(cls):
1043 return ['__class__', '__name__', 'missing']
1044 class C(metaclass=M):
1045 pass
1046 attrs = [a[0] for a in inspect.getmembers(C)]
1047 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001048
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001049
Nick Coghlan2f92e542012-06-23 19:39:55 +10001050_global_ref = object()
1051class TestGetClosureVars(unittest.TestCase):
1052
1053 def test_name_resolution(self):
1054 # Basic test of the 4 different resolution mechanisms
1055 def f(nonlocal_ref):
1056 def g(local_ref):
1057 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1058 return g
1059 _arg = object()
1060 nonlocal_vars = {"nonlocal_ref": _arg}
1061 global_vars = {"_global_ref": _global_ref}
1062 builtin_vars = {"print": print}
1063 unbound_names = {"unbound_ref"}
1064 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1065 builtin_vars, unbound_names)
1066 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1067
1068 def test_generator_closure(self):
1069 def f(nonlocal_ref):
1070 def g(local_ref):
1071 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1072 yield
1073 return g
1074 _arg = object()
1075 nonlocal_vars = {"nonlocal_ref": _arg}
1076 global_vars = {"_global_ref": _global_ref}
1077 builtin_vars = {"print": print}
1078 unbound_names = {"unbound_ref"}
1079 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1080 builtin_vars, unbound_names)
1081 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1082
1083 def test_method_closure(self):
1084 class C:
1085 def f(self, nonlocal_ref):
1086 def g(local_ref):
1087 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1088 return g
1089 _arg = object()
1090 nonlocal_vars = {"nonlocal_ref": _arg}
1091 global_vars = {"_global_ref": _global_ref}
1092 builtin_vars = {"print": print}
1093 unbound_names = {"unbound_ref"}
1094 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1095 builtin_vars, unbound_names)
1096 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1097
1098 def test_nonlocal_vars(self):
1099 # More complex tests of nonlocal resolution
1100 def _nonlocal_vars(f):
1101 return inspect.getclosurevars(f).nonlocals
1102
1103 def make_adder(x):
1104 def add(y):
1105 return x + y
1106 return add
1107
1108 def curry(func, arg1):
1109 return lambda arg2: func(arg1, arg2)
1110
1111 def less_than(a, b):
1112 return a < b
1113
1114 # The infamous Y combinator.
1115 def Y(le):
1116 def g(f):
1117 return le(lambda x: f(f)(x))
1118 Y.g_ref = g
1119 return g(g)
1120
1121 def check_y_combinator(func):
1122 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1123
1124 inc = make_adder(1)
1125 add_two = make_adder(2)
1126 greater_than_five = curry(less_than, 5)
1127
1128 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1129 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1130 self.assertEqual(_nonlocal_vars(greater_than_five),
1131 {'arg1': 5, 'func': less_than})
1132 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1133 {'x': 3})
1134 Y(check_y_combinator)
1135
1136 def test_getclosurevars_empty(self):
1137 def foo(): pass
1138 _empty = inspect.ClosureVars({}, {}, {}, set())
1139 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1140 self.assertEqual(inspect.getclosurevars(foo), _empty)
1141
1142 def test_getclosurevars_error(self):
1143 class T: pass
1144 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1145 self.assertRaises(TypeError, inspect.getclosurevars, list)
1146 self.assertRaises(TypeError, inspect.getclosurevars, {})
1147
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001148 def _private_globals(self):
1149 code = """def f(): print(path)"""
1150 ns = {}
1151 exec(code, ns)
1152 return ns["f"], ns
1153
1154 def test_builtins_fallback(self):
1155 f, ns = self._private_globals()
1156 ns.pop("__builtins__", None)
1157 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1158 self.assertEqual(inspect.getclosurevars(f), expected)
1159
1160 def test_builtins_as_dict(self):
1161 f, ns = self._private_globals()
1162 ns["__builtins__"] = {"path":1}
1163 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1164 self.assertEqual(inspect.getclosurevars(f), expected)
1165
1166 def test_builtins_as_module(self):
1167 f, ns = self._private_globals()
1168 ns["__builtins__"] = os
1169 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1170 self.assertEqual(inspect.getclosurevars(f), expected)
1171
Nick Coghlan2f92e542012-06-23 19:39:55 +10001172
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001173class TestGetcallargsFunctions(unittest.TestCase):
1174
1175 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1176 locs = dict(locs or {}, func=func)
1177 r1 = eval('func(%s)' % call_params_string, None, locs)
1178 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1179 locs)
1180 self.assertEqual(r1, r2)
1181
1182 def assertEqualException(self, func, call_param_string, locs=None):
1183 locs = dict(locs or {}, func=func)
1184 try:
1185 eval('func(%s)' % call_param_string, None, locs)
1186 except Exception as e:
1187 ex1 = e
1188 else:
1189 self.fail('Exception not raised')
1190 try:
1191 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1192 locs)
1193 except Exception as e:
1194 ex2 = e
1195 else:
1196 self.fail('Exception not raised')
1197 self.assertIs(type(ex1), type(ex2))
1198 self.assertEqual(str(ex1), str(ex2))
1199 del ex1, ex2
1200
1201 def makeCallable(self, signature):
1202 """Create a function that returns its locals()"""
1203 code = "lambda %s: locals()"
1204 return eval(code % signature)
1205
1206 def test_plain(self):
1207 f = self.makeCallable('a, b=1')
1208 self.assertEqualCallArgs(f, '2')
1209 self.assertEqualCallArgs(f, '2, 3')
1210 self.assertEqualCallArgs(f, 'a=2')
1211 self.assertEqualCallArgs(f, 'b=3, a=2')
1212 self.assertEqualCallArgs(f, '2, b=3')
1213 # expand *iterable / **mapping
1214 self.assertEqualCallArgs(f, '*(2,)')
1215 self.assertEqualCallArgs(f, '*[2]')
1216 self.assertEqualCallArgs(f, '*(2, 3)')
1217 self.assertEqualCallArgs(f, '*[2, 3]')
1218 self.assertEqualCallArgs(f, '**{"a":2}')
1219 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1220 self.assertEqualCallArgs(f, '2, **{"b":3}')
1221 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1222 # expand UserList / UserDict
1223 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1224 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1225 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1226 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1227 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1228
1229 def test_varargs(self):
1230 f = self.makeCallable('a, b=1, *c')
1231 self.assertEqualCallArgs(f, '2')
1232 self.assertEqualCallArgs(f, '2, 3')
1233 self.assertEqualCallArgs(f, '2, 3, 4')
1234 self.assertEqualCallArgs(f, '*(2,3,4)')
1235 self.assertEqualCallArgs(f, '2, *[3,4]')
1236 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1237
1238 def test_varkw(self):
1239 f = self.makeCallable('a, b=1, **c')
1240 self.assertEqualCallArgs(f, 'a=2')
1241 self.assertEqualCallArgs(f, '2, b=3, c=4')
1242 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1243 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1244 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1245 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1246 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1247 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1248 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1249
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001250 def test_varkw_only(self):
1251 # issue11256:
1252 f = self.makeCallable('**c')
1253 self.assertEqualCallArgs(f, '')
1254 self.assertEqualCallArgs(f, 'a=1')
1255 self.assertEqualCallArgs(f, 'a=1, b=2')
1256 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1257 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1258 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1259
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001260 def test_keyword_only(self):
1261 f = self.makeCallable('a=3, *, c, d=2')
1262 self.assertEqualCallArgs(f, 'c=3')
1263 self.assertEqualCallArgs(f, 'c=3, a=3')
1264 self.assertEqualCallArgs(f, 'a=2, c=4')
1265 self.assertEqualCallArgs(f, '4, c=4')
1266 self.assertEqualException(f, '')
1267 self.assertEqualException(f, '3')
1268 self.assertEqualException(f, 'a=3')
1269 self.assertEqualException(f, 'd=4')
1270
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001271 f = self.makeCallable('*, c, d=2')
1272 self.assertEqualCallArgs(f, 'c=3')
1273 self.assertEqualCallArgs(f, 'c=3, d=4')
1274 self.assertEqualCallArgs(f, 'd=4, c=3')
1275
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001276 def test_multiple_features(self):
1277 f = self.makeCallable('a, b=2, *f, **g')
1278 self.assertEqualCallArgs(f, '2, 3, 7')
1279 self.assertEqualCallArgs(f, '2, 3, x=8')
1280 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1281 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1282 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1283 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1284 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1285 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1286 '(4,[5,6])]), **collections.UserDict('
1287 'y=9, z=10)')
1288
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001289 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1290 self.assertEqualCallArgs(f, '2, 3, x=8')
1291 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1292 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1293 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1294 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1295 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1296 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1297 '(4,[5,6])]), q=0, **collections.UserDict('
1298 'y=9, z=10)')
1299
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001300 def test_errors(self):
1301 f0 = self.makeCallable('')
1302 f1 = self.makeCallable('a, b')
1303 f2 = self.makeCallable('a, b=1')
1304 # f0 takes no arguments
1305 self.assertEqualException(f0, '1')
1306 self.assertEqualException(f0, 'x=1')
1307 self.assertEqualException(f0, '1,x=1')
1308 # f1 takes exactly 2 arguments
1309 self.assertEqualException(f1, '')
1310 self.assertEqualException(f1, '1')
1311 self.assertEqualException(f1, 'a=2')
1312 self.assertEqualException(f1, 'b=3')
1313 # f2 takes at least 1 argument
1314 self.assertEqualException(f2, '')
1315 self.assertEqualException(f2, 'b=3')
1316 for f in f1, f2:
1317 # f1/f2 takes exactly/at most 2 arguments
1318 self.assertEqualException(f, '2, 3, 4')
1319 self.assertEqualException(f, '1, 2, 3, a=1')
1320 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001321 # XXX: success of this one depends on dict order
1322 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001323 # f got an unexpected keyword argument
1324 self.assertEqualException(f, 'c=2')
1325 self.assertEqualException(f, '2, c=3')
1326 self.assertEqualException(f, '2, 3, c=4')
1327 self.assertEqualException(f, '2, c=4, b=3')
1328 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1329 # f got multiple values for keyword argument
1330 self.assertEqualException(f, '1, a=2')
1331 self.assertEqualException(f, '1, **{"a":2}')
1332 self.assertEqualException(f, '1, 2, b=3')
1333 # XXX: Python inconsistency
1334 # - for functions and bound methods: unexpected keyword 'c'
1335 # - for unbound methods: multiple values for keyword 'a'
1336 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001337 # issue11256:
1338 f3 = self.makeCallable('**c')
1339 self.assertEqualException(f3, '1, 2')
1340 self.assertEqualException(f3, '1, 2, a=1, b=2')
1341 f4 = self.makeCallable('*, a, b=0')
1342 self.assertEqualException(f3, '1, 2')
1343 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001344
Yury Selivanov875df202014-03-27 18:23:03 -04001345 # issue #20816: getcallargs() fails to iterate over non-existent
1346 # kwonlydefaults and raises a wrong TypeError
1347 def f5(*, a): pass
1348 with self.assertRaisesRegex(TypeError,
1349 'missing 1 required keyword-only'):
1350 inspect.getcallargs(f5)
1351
1352
Yury Selivanovdccfa132014-03-27 18:42:52 -04001353 # issue20817:
1354 def f6(a, b, c):
1355 pass
1356 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1357 inspect.getcallargs(f6)
1358
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001359class TestGetcallargsMethods(TestGetcallargsFunctions):
1360
1361 def setUp(self):
1362 class Foo(object):
1363 pass
1364 self.cls = Foo
1365 self.inst = Foo()
1366
1367 def makeCallable(self, signature):
1368 assert 'self' not in signature
1369 mk = super(TestGetcallargsMethods, self).makeCallable
1370 self.cls.method = mk('self, ' + signature)
1371 return self.inst.method
1372
1373class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1374
1375 def makeCallable(self, signature):
1376 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1377 return self.cls.method
1378
1379 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1380 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1381 *self._getAssertEqualParams(func, call_params_string, locs))
1382
1383 def assertEqualException(self, func, call_params_string, locs=None):
1384 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1385 *self._getAssertEqualParams(func, call_params_string, locs))
1386
1387 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1388 assert 'inst' not in call_params_string
1389 locs = dict(locs or {}, inst=self.inst)
1390 return (func, 'inst,' + call_params_string, locs)
1391
Michael Foord95fc51d2010-11-20 15:07:30 +00001392
1393class TestGetattrStatic(unittest.TestCase):
1394
1395 def test_basic(self):
1396 class Thing(object):
1397 x = object()
1398
1399 thing = Thing()
1400 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1401 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1402 with self.assertRaises(AttributeError):
1403 inspect.getattr_static(thing, 'y')
1404
1405 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1406
1407 def test_inherited(self):
1408 class Thing(object):
1409 x = object()
1410 class OtherThing(Thing):
1411 pass
1412
1413 something = OtherThing()
1414 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1415
1416 def test_instance_attr(self):
1417 class Thing(object):
1418 x = 2
1419 def __init__(self, x):
1420 self.x = x
1421 thing = Thing(3)
1422 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1423 del thing.x
1424 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1425
1426 def test_property(self):
1427 class Thing(object):
1428 @property
1429 def x(self):
1430 raise AttributeError("I'm pretending not to exist")
1431 thing = Thing()
1432 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1433
Ezio Melotti75cbd732011-04-28 00:59:29 +03001434 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001435 class descriptor(object):
1436 def __get__(*_):
1437 raise AttributeError("I'm pretending not to exist")
1438 desc = descriptor()
1439 class Thing(object):
1440 x = desc
1441 thing = Thing()
1442 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1443
1444 def test_classAttribute(self):
1445 class Thing(object):
1446 x = object()
1447
1448 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1449
Ethan Furmane03ea372013-09-25 07:14:41 -07001450 def test_classVirtualAttribute(self):
1451 class Thing(object):
1452 @types.DynamicClassAttribute
1453 def x(self):
1454 return self._x
1455 _x = object()
1456
1457 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1458
Michael Foord95fc51d2010-11-20 15:07:30 +00001459 def test_inherited_classattribute(self):
1460 class Thing(object):
1461 x = object()
1462 class OtherThing(Thing):
1463 pass
1464
1465 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1466
1467 def test_slots(self):
1468 class Thing(object):
1469 y = 'bar'
1470 __slots__ = ['x']
1471 def __init__(self):
1472 self.x = 'foo'
1473 thing = Thing()
1474 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1475 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1476
1477 del thing.x
1478 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1479
1480 def test_metaclass(self):
1481 class meta(type):
1482 attr = 'foo'
1483 class Thing(object, metaclass=meta):
1484 pass
1485 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1486
1487 class sub(meta):
1488 pass
1489 class OtherThing(object, metaclass=sub):
1490 x = 3
1491 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1492
1493 class OtherOtherThing(OtherThing):
1494 pass
1495 # this test is odd, but it was added as it exposed a bug
1496 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1497
1498 def test_no_dict_no_slots(self):
1499 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1500 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1501
1502 def test_no_dict_no_slots_instance_member(self):
1503 # returns descriptor
1504 with open(__file__) as handle:
1505 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1506
1507 def test_inherited_slots(self):
1508 # returns descriptor
1509 class Thing(object):
1510 __slots__ = ['x']
1511 def __init__(self):
1512 self.x = 'foo'
1513
1514 class OtherThing(Thing):
1515 pass
1516 # it would be nice if this worked...
1517 # we get the descriptor instead of the instance attribute
1518 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1519
1520 def test_descriptor(self):
1521 class descriptor(object):
1522 def __get__(self, instance, owner):
1523 return 3
1524 class Foo(object):
1525 d = descriptor()
1526
1527 foo = Foo()
1528
1529 # for a non data descriptor we return the instance attribute
1530 foo.__dict__['d'] = 1
1531 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1532
1533 # if the descriptor is a data-desciptor we should return the
1534 # descriptor
1535 descriptor.__set__ = lambda s, i, v: None
1536 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1537
1538
1539 def test_metaclass_with_descriptor(self):
1540 class descriptor(object):
1541 def __get__(self, instance, owner):
1542 return 3
1543 class meta(type):
1544 d = descriptor()
1545 class Thing(object, metaclass=meta):
1546 pass
1547 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1548
1549
Michael Foordcc7ebb82010-11-20 16:20:16 +00001550 def test_class_as_property(self):
1551 class Base(object):
1552 foo = 3
1553
1554 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001555 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001556 @property
1557 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001558 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001559 return object
1560
Michael Foord35184ed2010-11-20 16:58:30 +00001561 instance = Something()
1562 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1563 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001564 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1565
Michael Foorde5162652010-11-20 16:40:44 +00001566 def test_mro_as_property(self):
1567 class Meta(type):
1568 @property
1569 def __mro__(self):
1570 return (object,)
1571
1572 class Base(object):
1573 foo = 3
1574
1575 class Something(Base, metaclass=Meta):
1576 pass
1577
1578 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1579 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1580
Michael Foorddcebe0f2011-03-15 19:20:44 -04001581 def test_dict_as_property(self):
1582 test = self
1583 test.called = False
1584
1585 class Foo(dict):
1586 a = 3
1587 @property
1588 def __dict__(self):
1589 test.called = True
1590 return {}
1591
1592 foo = Foo()
1593 foo.a = 4
1594 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1595 self.assertFalse(test.called)
1596
1597 def test_custom_object_dict(self):
1598 test = self
1599 test.called = False
1600
1601 class Custom(dict):
1602 def get(self, key, default=None):
1603 test.called = True
1604 super().get(key, default)
1605
1606 class Foo(object):
1607 a = 3
1608 foo = Foo()
1609 foo.__dict__ = Custom()
1610 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1611 self.assertFalse(test.called)
1612
1613 def test_metaclass_dict_as_property(self):
1614 class Meta(type):
1615 @property
1616 def __dict__(self):
1617 self.executed = True
1618
1619 class Thing(metaclass=Meta):
1620 executed = False
1621
1622 def __init__(self):
1623 self.spam = 42
1624
1625 instance = Thing()
1626 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1627 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001628
Michael Foorda51623b2011-12-18 22:01:40 +00001629 def test_module(self):
1630 sentinel = object()
1631 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1632 sentinel)
1633
Michael Foord3ba95f82011-12-22 01:13:37 +00001634 def test_metaclass_with_metaclass_with_dict_as_property(self):
1635 class MetaMeta(type):
1636 @property
1637 def __dict__(self):
1638 self.executed = True
1639 return dict(spam=42)
1640
1641 class Meta(type, metaclass=MetaMeta):
1642 executed = False
1643
1644 class Thing(metaclass=Meta):
1645 pass
1646
1647 with self.assertRaises(AttributeError):
1648 inspect.getattr_static(Thing, "spam")
1649 self.assertFalse(Thing.executed)
1650
Nick Coghlane0f04652010-11-21 03:44:04 +00001651class TestGetGeneratorState(unittest.TestCase):
1652
1653 def setUp(self):
1654 def number_generator():
1655 for number in range(5):
1656 yield number
1657 self.generator = number_generator()
1658
1659 def _generatorstate(self):
1660 return inspect.getgeneratorstate(self.generator)
1661
1662 def test_created(self):
1663 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1664
1665 def test_suspended(self):
1666 next(self.generator)
1667 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1668
1669 def test_closed_after_exhaustion(self):
1670 for i in self.generator:
1671 pass
1672 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1673
1674 def test_closed_after_immediate_exception(self):
1675 with self.assertRaises(RuntimeError):
1676 self.generator.throw(RuntimeError)
1677 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1678
1679 def test_running(self):
1680 # As mentioned on issue #10220, checking for the RUNNING state only
1681 # makes sense inside the generator itself.
1682 # The following generator checks for this by using the closure's
1683 # reference to self and the generator state checking helper method
1684 def running_check_generator():
1685 for number in range(5):
1686 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1687 yield number
1688 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1689 self.generator = running_check_generator()
1690 # Running up to the first yield
1691 next(self.generator)
1692 # Running after the first yield
1693 next(self.generator)
1694
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001695 def test_easy_debugging(self):
1696 # repr() and str() of a generator state should contain the state name
1697 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1698 for name in names:
1699 state = getattr(inspect, name)
1700 self.assertIn(name, repr(state))
1701 self.assertIn(name, str(state))
1702
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001703 def test_getgeneratorlocals(self):
1704 def each(lst, a=None):
1705 b=(1, 2, 3)
1706 for v in lst:
1707 if v == 3:
1708 c = 12
1709 yield v
1710
1711 numbers = each([1, 2, 3])
1712 self.assertEqual(inspect.getgeneratorlocals(numbers),
1713 {'a': None, 'lst': [1, 2, 3]})
1714 next(numbers)
1715 self.assertEqual(inspect.getgeneratorlocals(numbers),
1716 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1717 'b': (1, 2, 3)})
1718 next(numbers)
1719 self.assertEqual(inspect.getgeneratorlocals(numbers),
1720 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1721 'b': (1, 2, 3)})
1722 next(numbers)
1723 self.assertEqual(inspect.getgeneratorlocals(numbers),
1724 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1725 'b': (1, 2, 3), 'c': 12})
1726 try:
1727 next(numbers)
1728 except StopIteration:
1729 pass
1730 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1731
1732 def test_getgeneratorlocals_empty(self):
1733 def yield_one():
1734 yield 1
1735 one = yield_one()
1736 self.assertEqual(inspect.getgeneratorlocals(one), {})
1737 try:
1738 next(one)
1739 except StopIteration:
1740 pass
1741 self.assertEqual(inspect.getgeneratorlocals(one), {})
1742
1743 def test_getgeneratorlocals_error(self):
1744 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1745 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1746 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1747 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1748
Nick Coghlane0f04652010-11-21 03:44:04 +00001749
Yury Selivanov5376ba92015-06-22 12:19:30 -04001750class TestGetCoroutineState(unittest.TestCase):
1751
1752 def setUp(self):
1753 @types.coroutine
1754 def number_coroutine():
1755 for number in range(5):
1756 yield number
1757 async def coroutine():
1758 await number_coroutine()
1759 self.coroutine = coroutine()
1760
1761 def tearDown(self):
1762 self.coroutine.close()
1763
1764 def _coroutinestate(self):
1765 return inspect.getcoroutinestate(self.coroutine)
1766
1767 def test_created(self):
1768 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1769
1770 def test_suspended(self):
1771 self.coroutine.send(None)
1772 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1773
1774 def test_closed_after_exhaustion(self):
1775 while True:
1776 try:
1777 self.coroutine.send(None)
1778 except StopIteration:
1779 break
1780
1781 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1782
1783 def test_closed_after_immediate_exception(self):
1784 with self.assertRaises(RuntimeError):
1785 self.coroutine.throw(RuntimeError)
1786 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1787
1788 def test_easy_debugging(self):
1789 # repr() and str() of a coroutine state should contain the state name
1790 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1791 for name in names:
1792 state = getattr(inspect, name)
1793 self.assertIn(name, repr(state))
1794 self.assertIn(name, str(state))
1795
1796 def test_getcoroutinelocals(self):
1797 @types.coroutine
1798 def gencoro():
1799 yield
1800
1801 gencoro = gencoro()
1802 async def func(a=None):
1803 b = 'spam'
1804 await gencoro
1805
1806 coro = func()
1807 self.assertEqual(inspect.getcoroutinelocals(coro),
1808 {'a': None, 'gencoro': gencoro})
1809 coro.send(None)
1810 self.assertEqual(inspect.getcoroutinelocals(coro),
1811 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
1812
1813
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001814class MySignature(inspect.Signature):
1815 # Top-level to make it picklable;
1816 # used in test_signature_object_pickle
1817 pass
1818
1819class MyParameter(inspect.Parameter):
1820 # Top-level to make it picklable;
1821 # used in test_signature_object_pickle
1822 pass
1823
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001824
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001825
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001826class TestSignatureObject(unittest.TestCase):
1827 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04001828 def signature(func, **kw):
1829 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001830 return (tuple((param.name,
1831 (... if param.default is param.empty else param.default),
1832 (... if param.annotation is param.empty
1833 else param.annotation),
1834 str(param.kind).lower())
1835 for param in sig.parameters.values()),
1836 (... if sig.return_annotation is sig.empty
1837 else sig.return_annotation))
1838
1839 def test_signature_object(self):
1840 S = inspect.Signature
1841 P = inspect.Parameter
1842
1843 self.assertEqual(str(S()), '()')
1844
Yury Selivanov07a9e452014-01-29 10:58:16 -05001845 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001846 pass
1847 sig = inspect.signature(test)
1848 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001849 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001850 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001851 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001852 args = sig.parameters['args']
1853 ko = sig.parameters['ko']
1854 kwargs = sig.parameters['kwargs']
1855
1856 S((po, pk, args, ko, kwargs))
1857
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001858 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001859 S((pk, po, args, ko, kwargs))
1860
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001861 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001862 S((po, args, pk, ko, kwargs))
1863
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001864 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001865 S((args, po, pk, ko, kwargs))
1866
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001867 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001868 S((po, pk, args, kwargs, ko))
1869
1870 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001871 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001872 S((po, pk, args, kwargs2, ko))
1873
Yury Selivanov07a9e452014-01-29 10:58:16 -05001874 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1875 S((pod, po))
1876
1877 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1878 S((po, pkd, pk))
1879
1880 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1881 S((pkd, pk))
1882
Yury Selivanov374375d2014-03-27 12:41:53 -04001883 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04001884 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04001885
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001886 def test_signature_object_pickle(self):
1887 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1888 foo_partial = functools.partial(foo, a=1)
1889
1890 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001891
1892 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1893 with self.subTest(pickle_ver=ver, subclass=False):
1894 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1895 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001896
1897 # Test that basic sub-classing works
1898 sig = inspect.signature(foo)
1899 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1900 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1901 mysig = MySignature().replace(parameters=myparams.values(),
1902 return_annotation=sig.return_annotation)
1903 self.assertTrue(isinstance(mysig, MySignature))
1904 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1905
1906 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1907 with self.subTest(pickle_ver=ver, subclass=True):
1908 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1909 self.assertEqual(mysig, sig_pickled)
1910 self.assertTrue(isinstance(sig_pickled, MySignature))
1911 self.assertTrue(isinstance(sig_pickled.parameters['z'],
1912 MyParameter))
1913
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001914 def test_signature_immutability(self):
1915 def test(a):
1916 pass
1917 sig = inspect.signature(test)
1918
1919 with self.assertRaises(AttributeError):
1920 sig.foo = 'bar'
1921
1922 with self.assertRaises(TypeError):
1923 sig.parameters['a'] = None
1924
1925 def test_signature_on_noarg(self):
1926 def test():
1927 pass
1928 self.assertEqual(self.signature(test), ((), ...))
1929
1930 def test_signature_on_wargs(self):
1931 def test(a, b:'foo') -> 123:
1932 pass
1933 self.assertEqual(self.signature(test),
1934 ((('a', ..., ..., "positional_or_keyword"),
1935 ('b', ..., 'foo', "positional_or_keyword")),
1936 123))
1937
1938 def test_signature_on_wkwonly(self):
1939 def test(*, a:float, b:str) -> int:
1940 pass
1941 self.assertEqual(self.signature(test),
1942 ((('a', ..., float, "keyword_only"),
1943 ('b', ..., str, "keyword_only")),
1944 int))
1945
1946 def test_signature_on_complex_args(self):
1947 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1948 pass
1949 self.assertEqual(self.signature(test),
1950 ((('a', ..., ..., "positional_or_keyword"),
1951 ('b', 10, 'foo', "positional_or_keyword"),
1952 ('args', ..., 'bar', "var_positional"),
1953 ('spam', ..., 'baz', "keyword_only"),
1954 ('ham', 123, ..., "keyword_only"),
1955 ('kwargs', ..., int, "var_keyword")),
1956 ...))
1957
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001958 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001959 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1960 "Signature information for builtins requires docstrings")
1961 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001962 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001963
Larry Hastings5c661892014-01-24 06:17:25 -08001964 def test_unbound_method(o):
1965 """Use this to test unbound methods (things that should have a self)"""
1966 signature = inspect.signature(o)
1967 self.assertTrue(isinstance(signature, inspect.Signature))
1968 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1969 return signature
1970
1971 def test_callable(o):
1972 """Use this to test bound methods or normal callables (things that don't expect self)"""
1973 signature = inspect.signature(o)
1974 self.assertTrue(isinstance(signature, inspect.Signature))
1975 if signature.parameters:
1976 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1977 return signature
1978
1979 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001980 def p(name): return signature.parameters[name].default
1981 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001982 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001983 self.assertEqual(p('d'), 3.14)
1984 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001985 self.assertEqual(p('n'), None)
1986 self.assertEqual(p('t'), True)
1987 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001988 self.assertEqual(p('local'), 3)
1989 self.assertEqual(p('sys'), sys.maxsize)
1990 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001991
Larry Hastings5c661892014-01-24 06:17:25 -08001992 test_callable(object)
1993
1994 # normal method
1995 # (PyMethodDescr_Type, "method_descriptor")
1996 test_unbound_method(_pickle.Pickler.dump)
1997 d = _pickle.Pickler(io.StringIO())
1998 test_callable(d.dump)
1999
2000 # static method
2001 test_callable(str.maketrans)
2002 test_callable('abc'.maketrans)
2003
2004 # class method
2005 test_callable(dict.fromkeys)
2006 test_callable({}.fromkeys)
2007
2008 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2009 test_unbound_method(type.__call__)
2010 test_unbound_method(int.__add__)
2011 test_callable((3).__add__)
2012
2013 # _PyMethodWrapper_Type
2014 # support for 'method-wrapper'
2015 test_callable(min.__call__)
2016
Larry Hastings2623c8c2014-02-08 22:15:29 -08002017 # This doesn't work now.
2018 # (We don't have a valid signature for "type" in 3.4)
2019 with self.assertRaisesRegex(ValueError, "no signature found"):
2020 class ThisWorksNow:
2021 __call__ = type
2022 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002023
Yury Selivanov056e2652014-03-02 12:25:27 -05002024 # Regression test for issue #20786
2025 test_unbound_method(dict.__delitem__)
2026 test_unbound_method(property.__delete__)
2027
Zachary Ware8ef887c2015-04-13 18:22:35 -05002028 # Regression test for issue #20586
2029 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2030
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002031 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002032 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2033 "Signature information for builtins requires docstrings")
2034 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002035 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002036 func = _testcapi.docstring_with_signature_with_defaults
2037
2038 def decorator(func):
2039 @functools.wraps(func)
2040 def wrapper(*args, **kwargs) -> int:
2041 return func(*args, **kwargs)
2042 return wrapper
2043
2044 decorated_func = decorator(func)
2045
2046 self.assertEqual(inspect.signature(func),
2047 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002048
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002049 def wrapper_like(*args, **kwargs) -> int: pass
2050 self.assertEqual(inspect.signature(decorated_func,
2051 follow_wrapped=False),
2052 inspect.signature(wrapper_like))
2053
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002054 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002055 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002056 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002057 with self.assertRaisesRegex(ValueError,
2058 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002059 inspect.signature(_testcapi.docstring_no_signature)
2060
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002061 with self.assertRaisesRegex(ValueError,
2062 'no signature found for builtin'):
2063 inspect.signature(str)
2064
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002065 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002066 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002067 inspect.signature(42)
2068
Yury Selivanov63da7c72014-01-31 14:48:37 -05002069 def test_signature_from_functionlike_object(self):
2070 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2071 pass
2072
2073 class funclike:
2074 # Has to be callable, and have correct
2075 # __code__, __annotations__, __defaults__, __name__,
2076 # and __kwdefaults__ attributes
2077
2078 def __init__(self, func):
2079 self.__name__ = func.__name__
2080 self.__code__ = func.__code__
2081 self.__annotations__ = func.__annotations__
2082 self.__defaults__ = func.__defaults__
2083 self.__kwdefaults__ = func.__kwdefaults__
2084 self.func = func
2085
2086 def __call__(self, *args, **kwargs):
2087 return self.func(*args, **kwargs)
2088
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002089 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002090
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002091 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002092 self.assertEqual(sig_funclike, sig_func)
2093
2094 sig_funclike = inspect.signature(funclike(func))
2095 self.assertEqual(sig_funclike, sig_func)
2096
2097 # If object is not a duck type of function, then
2098 # signature will try to get a signature for its '__call__'
2099 # method
2100 fl = funclike(func)
2101 del fl.__defaults__
2102 self.assertEqual(self.signature(fl),
2103 ((('args', ..., ..., "var_positional"),
2104 ('kwargs', ..., ..., "var_keyword")),
2105 ...))
2106
Yury Selivanova773de02014-02-21 18:30:53 -05002107 # Test with cython-like builtins:
2108 _orig_isdesc = inspect.ismethoddescriptor
2109 def _isdesc(obj):
2110 if hasattr(obj, '_builtinmock'):
2111 return True
2112 return _orig_isdesc(obj)
2113
2114 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2115 builtin_func = funclike(func)
2116 # Make sure that our mock setup is working
2117 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2118 builtin_func._builtinmock = True
2119 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2120 self.assertEqual(inspect.signature(builtin_func), sig_func)
2121
Yury Selivanov63da7c72014-01-31 14:48:37 -05002122 def test_signature_functionlike_class(self):
2123 # We only want to duck type function-like objects,
2124 # not classes.
2125
2126 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2127 pass
2128
2129 class funclike:
2130 def __init__(self, marker):
2131 pass
2132
2133 __name__ = func.__name__
2134 __code__ = func.__code__
2135 __annotations__ = func.__annotations__
2136 __defaults__ = func.__defaults__
2137 __kwdefaults__ = func.__kwdefaults__
2138
Yury Selivanov63da7c72014-01-31 14:48:37 -05002139 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2140
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002141 def test_signature_on_method(self):
2142 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002143 def __init__(*args):
2144 pass
2145 def m1(self, arg1, arg2=1) -> int:
2146 pass
2147 def m2(*args):
2148 pass
2149 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002150 pass
2151
Yury Selivanov62560fb2014-01-28 12:26:24 -05002152 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002153 ((('arg1', ..., ..., "positional_or_keyword"),
2154 ('arg2', 1, ..., "positional_or_keyword")),
2155 int))
2156
Yury Selivanov62560fb2014-01-28 12:26:24 -05002157 self.assertEqual(self.signature(Test().m2),
2158 ((('args', ..., ..., "var_positional"),),
2159 ...))
2160
2161 self.assertEqual(self.signature(Test),
2162 ((('args', ..., ..., "var_positional"),),
2163 ...))
2164
2165 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2166 self.signature(Test())
2167
Yury Selivanov46c759d2015-05-27 21:56:53 -04002168 def test_signature_wrapped_bound_method(self):
2169 # Issue 24298
2170 class Test:
2171 def m1(self, arg1, arg2=1) -> int:
2172 pass
2173 @functools.wraps(Test().m1)
2174 def m1d(*args, **kwargs):
2175 pass
2176 self.assertEqual(self.signature(m1d),
2177 ((('arg1', ..., ..., "positional_or_keyword"),
2178 ('arg2', 1, ..., "positional_or_keyword")),
2179 int))
2180
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002181 def test_signature_on_classmethod(self):
2182 class Test:
2183 @classmethod
2184 def foo(cls, arg1, *, arg2=1):
2185 pass
2186
2187 meth = Test().foo
2188 self.assertEqual(self.signature(meth),
2189 ((('arg1', ..., ..., "positional_or_keyword"),
2190 ('arg2', 1, ..., "keyword_only")),
2191 ...))
2192
2193 meth = Test.foo
2194 self.assertEqual(self.signature(meth),
2195 ((('arg1', ..., ..., "positional_or_keyword"),
2196 ('arg2', 1, ..., "keyword_only")),
2197 ...))
2198
2199 def test_signature_on_staticmethod(self):
2200 class Test:
2201 @staticmethod
2202 def foo(cls, *, arg):
2203 pass
2204
2205 meth = Test().foo
2206 self.assertEqual(self.signature(meth),
2207 ((('cls', ..., ..., "positional_or_keyword"),
2208 ('arg', ..., ..., "keyword_only")),
2209 ...))
2210
2211 meth = Test.foo
2212 self.assertEqual(self.signature(meth),
2213 ((('cls', ..., ..., "positional_or_keyword"),
2214 ('arg', ..., ..., "keyword_only")),
2215 ...))
2216
2217 def test_signature_on_partial(self):
2218 from functools import partial
2219
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002220 Parameter = inspect.Parameter
2221
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002222 def test():
2223 pass
2224
2225 self.assertEqual(self.signature(partial(test)), ((), ...))
2226
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002227 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002228 inspect.signature(partial(test, 1))
2229
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002230 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002231 inspect.signature(partial(test, a=1))
2232
2233 def test(a, b, *, c, d):
2234 pass
2235
2236 self.assertEqual(self.signature(partial(test)),
2237 ((('a', ..., ..., "positional_or_keyword"),
2238 ('b', ..., ..., "positional_or_keyword"),
2239 ('c', ..., ..., "keyword_only"),
2240 ('d', ..., ..., "keyword_only")),
2241 ...))
2242
2243 self.assertEqual(self.signature(partial(test, 1)),
2244 ((('b', ..., ..., "positional_or_keyword"),
2245 ('c', ..., ..., "keyword_only"),
2246 ('d', ..., ..., "keyword_only")),
2247 ...))
2248
2249 self.assertEqual(self.signature(partial(test, 1, c=2)),
2250 ((('b', ..., ..., "positional_or_keyword"),
2251 ('c', 2, ..., "keyword_only"),
2252 ('d', ..., ..., "keyword_only")),
2253 ...))
2254
2255 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2256 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002257 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002258 ('c', 2, ..., "keyword_only"),
2259 ('d', ..., ..., "keyword_only")),
2260 ...))
2261
2262 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002263 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002264 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002265 ('d', ..., ..., "keyword_only")),
2266 ...))
2267
2268 self.assertEqual(self.signature(partial(test, a=1)),
2269 ((('a', 1, ..., "keyword_only"),
2270 ('b', ..., ..., "keyword_only"),
2271 ('c', ..., ..., "keyword_only"),
2272 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002273 ...))
2274
2275 def test(a, *args, b, **kwargs):
2276 pass
2277
2278 self.assertEqual(self.signature(partial(test, 1)),
2279 ((('args', ..., ..., "var_positional"),
2280 ('b', ..., ..., "keyword_only"),
2281 ('kwargs', ..., ..., "var_keyword")),
2282 ...))
2283
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002284 self.assertEqual(self.signature(partial(test, a=1)),
2285 ((('a', 1, ..., "keyword_only"),
2286 ('b', ..., ..., "keyword_only"),
2287 ('kwargs', ..., ..., "var_keyword")),
2288 ...))
2289
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002290 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2291 ((('args', ..., ..., "var_positional"),
2292 ('b', ..., ..., "keyword_only"),
2293 ('kwargs', ..., ..., "var_keyword")),
2294 ...))
2295
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002296 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2297 ((('args', ..., ..., "var_positional"),
2298 ('b', ..., ..., "keyword_only"),
2299 ('kwargs', ..., ..., "var_keyword")),
2300 ...))
2301
2302 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2303 ((('args', ..., ..., "var_positional"),
2304 ('b', 0, ..., "keyword_only"),
2305 ('kwargs', ..., ..., "var_keyword")),
2306 ...))
2307
2308 self.assertEqual(self.signature(partial(test, b=0)),
2309 ((('a', ..., ..., "positional_or_keyword"),
2310 ('args', ..., ..., "var_positional"),
2311 ('b', 0, ..., "keyword_only"),
2312 ('kwargs', ..., ..., "var_keyword")),
2313 ...))
2314
2315 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2316 ((('a', ..., ..., "positional_or_keyword"),
2317 ('args', ..., ..., "var_positional"),
2318 ('b', 0, ..., "keyword_only"),
2319 ('kwargs', ..., ..., "var_keyword")),
2320 ...))
2321
2322 def test(a, b, c:int) -> 42:
2323 pass
2324
2325 sig = test.__signature__ = inspect.signature(test)
2326
2327 self.assertEqual(self.signature(partial(partial(test, 1))),
2328 ((('b', ..., ..., "positional_or_keyword"),
2329 ('c', ..., int, "positional_or_keyword")),
2330 42))
2331
2332 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2333 ((('c', ..., int, "positional_or_keyword"),),
2334 42))
2335
2336 psig = inspect.signature(partial(partial(test, 1), 2))
2337
2338 def foo(a):
2339 return a
2340 _foo = partial(partial(foo, a=10), a=20)
2341 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002342 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002343 ...))
2344 # check that we don't have any side-effects in signature(),
2345 # and the partial object is still functioning
2346 self.assertEqual(_foo(), 20)
2347
2348 def foo(a, b, c):
2349 return a, b, c
2350 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002351
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002352 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002353 ((('b', 30, ..., "keyword_only"),
2354 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002355 ...))
2356 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002357
2358 def foo(a, b, c, *, d):
2359 return a, b, c, d
2360 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2361 self.assertEqual(self.signature(_foo),
2362 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002363 ('b', 10, ..., "keyword_only"),
2364 ('c', 20, ..., "keyword_only"),
2365 ('d', 30, ..., "keyword_only"),
2366 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002367 ...))
2368 ba = inspect.signature(_foo).bind(a=200, b=11)
2369 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2370
2371 def foo(a=1, b=2, c=3):
2372 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002373 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2374
2375 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002376 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002377
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002378 ba = inspect.signature(_foo).bind(11, 12)
2379 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002380
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002381 ba = inspect.signature(_foo).bind(11, b=12)
2382 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002383
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002384 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002385 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2386
2387 _foo = partial(_foo, b=10, c=20)
2388 ba = inspect.signature(_foo).bind(12)
2389 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2390
2391
2392 def foo(a, b, c, d, **kwargs):
2393 pass
2394 sig = inspect.signature(foo)
2395 params = sig.parameters.copy()
2396 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2397 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2398 foo.__signature__ = inspect.Signature(params.values())
2399 sig = inspect.signature(foo)
2400 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2401
2402 self.assertEqual(self.signature(partial(foo, 1)),
2403 ((('b', ..., ..., 'positional_only'),
2404 ('c', ..., ..., 'positional_or_keyword'),
2405 ('d', ..., ..., 'positional_or_keyword'),
2406 ('kwargs', ..., ..., 'var_keyword')),
2407 ...))
2408
2409 self.assertEqual(self.signature(partial(foo, 1, 2)),
2410 ((('c', ..., ..., 'positional_or_keyword'),
2411 ('d', ..., ..., 'positional_or_keyword'),
2412 ('kwargs', ..., ..., 'var_keyword')),
2413 ...))
2414
2415 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2416 ((('d', ..., ..., 'positional_or_keyword'),
2417 ('kwargs', ..., ..., 'var_keyword')),
2418 ...))
2419
2420 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2421 ((('c', 3, ..., 'keyword_only'),
2422 ('d', ..., ..., 'keyword_only'),
2423 ('kwargs', ..., ..., 'var_keyword')),
2424 ...))
2425
2426 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2427 ((('b', ..., ..., 'positional_only'),
2428 ('c', 3, ..., 'keyword_only'),
2429 ('d', ..., ..., 'keyword_only'),
2430 ('kwargs', ..., ..., 'var_keyword')),
2431 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002432
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002433 def test_signature_on_partialmethod(self):
2434 from functools import partialmethod
2435
2436 class Spam:
2437 def test():
2438 pass
2439 ham = partialmethod(test)
2440
2441 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2442 inspect.signature(Spam.ham)
2443
2444 class Spam:
2445 def test(it, a, *, c) -> 'spam':
2446 pass
2447 ham = partialmethod(test, c=1)
2448
2449 self.assertEqual(self.signature(Spam.ham),
2450 ((('it', ..., ..., 'positional_or_keyword'),
2451 ('a', ..., ..., 'positional_or_keyword'),
2452 ('c', 1, ..., 'keyword_only')),
2453 'spam'))
2454
2455 self.assertEqual(self.signature(Spam().ham),
2456 ((('a', ..., ..., 'positional_or_keyword'),
2457 ('c', 1, ..., 'keyword_only')),
2458 'spam'))
2459
Yury Selivanov0486f812014-01-29 12:18:59 -05002460 def test_signature_on_fake_partialmethod(self):
2461 def foo(a): pass
2462 foo._partialmethod = 'spam'
2463 self.assertEqual(str(inspect.signature(foo)), '(a)')
2464
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002465 def test_signature_on_decorated(self):
2466 import functools
2467
2468 def decorator(func):
2469 @functools.wraps(func)
2470 def wrapper(*args, **kwargs) -> int:
2471 return func(*args, **kwargs)
2472 return wrapper
2473
2474 class Foo:
2475 @decorator
2476 def bar(self, a, b):
2477 pass
2478
2479 self.assertEqual(self.signature(Foo.bar),
2480 ((('self', ..., ..., "positional_or_keyword"),
2481 ('a', ..., ..., "positional_or_keyword"),
2482 ('b', ..., ..., "positional_or_keyword")),
2483 ...))
2484
2485 self.assertEqual(self.signature(Foo().bar),
2486 ((('a', ..., ..., "positional_or_keyword"),
2487 ('b', ..., ..., "positional_or_keyword")),
2488 ...))
2489
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002490 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2491 ((('args', ..., ..., "var_positional"),
2492 ('kwargs', ..., ..., "var_keyword")),
2493 ...)) # functools.wraps will copy __annotations__
2494 # from "func" to "wrapper", hence no
2495 # return_annotation
2496
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002497 # Test that we handle method wrappers correctly
2498 def decorator(func):
2499 @functools.wraps(func)
2500 def wrapper(*args, **kwargs) -> int:
2501 return func(42, *args, **kwargs)
2502 sig = inspect.signature(func)
2503 new_params = tuple(sig.parameters.values())[1:]
2504 wrapper.__signature__ = sig.replace(parameters=new_params)
2505 return wrapper
2506
2507 class Foo:
2508 @decorator
2509 def __call__(self, a, b):
2510 pass
2511
2512 self.assertEqual(self.signature(Foo.__call__),
2513 ((('a', ..., ..., "positional_or_keyword"),
2514 ('b', ..., ..., "positional_or_keyword")),
2515 ...))
2516
2517 self.assertEqual(self.signature(Foo().__call__),
2518 ((('b', ..., ..., "positional_or_keyword"),),
2519 ...))
2520
Nick Coghlane8c45d62013-07-28 20:00:01 +10002521 # Test we handle __signature__ partway down the wrapper stack
2522 def wrapped_foo_call():
2523 pass
2524 wrapped_foo_call.__wrapped__ = Foo.__call__
2525
2526 self.assertEqual(self.signature(wrapped_foo_call),
2527 ((('a', ..., ..., "positional_or_keyword"),
2528 ('b', ..., ..., "positional_or_keyword")),
2529 ...))
2530
2531
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002532 def test_signature_on_class(self):
2533 class C:
2534 def __init__(self, a):
2535 pass
2536
2537 self.assertEqual(self.signature(C),
2538 ((('a', ..., ..., "positional_or_keyword"),),
2539 ...))
2540
2541 class CM(type):
2542 def __call__(cls, a):
2543 pass
2544 class C(metaclass=CM):
2545 def __init__(self, b):
2546 pass
2547
2548 self.assertEqual(self.signature(C),
2549 ((('a', ..., ..., "positional_or_keyword"),),
2550 ...))
2551
2552 class CM(type):
2553 def __new__(mcls, name, bases, dct, *, foo=1):
2554 return super().__new__(mcls, name, bases, dct)
2555 class C(metaclass=CM):
2556 def __init__(self, b):
2557 pass
2558
2559 self.assertEqual(self.signature(C),
2560 ((('b', ..., ..., "positional_or_keyword"),),
2561 ...))
2562
2563 self.assertEqual(self.signature(CM),
2564 ((('name', ..., ..., "positional_or_keyword"),
2565 ('bases', ..., ..., "positional_or_keyword"),
2566 ('dct', ..., ..., "positional_or_keyword"),
2567 ('foo', 1, ..., "keyword_only")),
2568 ...))
2569
2570 class CMM(type):
2571 def __new__(mcls, name, bases, dct, *, foo=1):
2572 return super().__new__(mcls, name, bases, dct)
2573 def __call__(cls, nm, bs, dt):
2574 return type(nm, bs, dt)
2575 class CM(type, metaclass=CMM):
2576 def __new__(mcls, name, bases, dct, *, bar=2):
2577 return super().__new__(mcls, name, bases, dct)
2578 class C(metaclass=CM):
2579 def __init__(self, b):
2580 pass
2581
2582 self.assertEqual(self.signature(CMM),
2583 ((('name', ..., ..., "positional_or_keyword"),
2584 ('bases', ..., ..., "positional_or_keyword"),
2585 ('dct', ..., ..., "positional_or_keyword"),
2586 ('foo', 1, ..., "keyword_only")),
2587 ...))
2588
2589 self.assertEqual(self.signature(CM),
2590 ((('nm', ..., ..., "positional_or_keyword"),
2591 ('bs', ..., ..., "positional_or_keyword"),
2592 ('dt', ..., ..., "positional_or_keyword")),
2593 ...))
2594
2595 self.assertEqual(self.signature(C),
2596 ((('b', ..., ..., "positional_or_keyword"),),
2597 ...))
2598
2599 class CM(type):
2600 def __init__(cls, name, bases, dct, *, bar=2):
2601 return super().__init__(name, bases, dct)
2602 class C(metaclass=CM):
2603 def __init__(self, b):
2604 pass
2605
2606 self.assertEqual(self.signature(CM),
2607 ((('name', ..., ..., "positional_or_keyword"),
2608 ('bases', ..., ..., "positional_or_keyword"),
2609 ('dct', ..., ..., "positional_or_keyword"),
2610 ('bar', 2, ..., "keyword_only")),
2611 ...))
2612
Yury Selivanov145dff82014-02-01 13:49:29 -05002613 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2614 "Signature information for builtins requires docstrings")
2615 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002616 # Test classes without user-defined __init__ or __new__
2617 class C: pass
2618 self.assertEqual(str(inspect.signature(C)), '()')
2619 class D(C): pass
2620 self.assertEqual(str(inspect.signature(D)), '()')
2621
2622 # Test meta-classes without user-defined __init__ or __new__
2623 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002624 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002625 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2626 self.assertEqual(inspect.signature(C), None)
2627 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2628 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002629
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002630 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2631 "Signature information for builtins requires docstrings")
2632 def test_signature_on_builtin_class(self):
2633 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2634 '(file, protocol=None, fix_imports=True)')
2635
2636 class P(_pickle.Pickler): pass
2637 class EmptyTrait: pass
2638 class P2(EmptyTrait, P): pass
2639 self.assertEqual(str(inspect.signature(P)),
2640 '(file, protocol=None, fix_imports=True)')
2641 self.assertEqual(str(inspect.signature(P2)),
2642 '(file, protocol=None, fix_imports=True)')
2643
2644 class P3(P2):
2645 def __init__(self, spam):
2646 pass
2647 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2648
2649 class MetaP(type):
2650 def __call__(cls, foo, bar):
2651 pass
2652 class P4(P2, metaclass=MetaP):
2653 pass
2654 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2655
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002656 def test_signature_on_callable_objects(self):
2657 class Foo:
2658 def __call__(self, a):
2659 pass
2660
2661 self.assertEqual(self.signature(Foo()),
2662 ((('a', ..., ..., "positional_or_keyword"),),
2663 ...))
2664
2665 class Spam:
2666 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002667 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002668 inspect.signature(Spam())
2669
2670 class Bar(Spam, Foo):
2671 pass
2672
2673 self.assertEqual(self.signature(Bar()),
2674 ((('a', ..., ..., "positional_or_keyword"),),
2675 ...))
2676
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002677 class Wrapped:
2678 pass
2679 Wrapped.__wrapped__ = lambda a: None
2680 self.assertEqual(self.signature(Wrapped),
2681 ((('a', ..., ..., "positional_or_keyword"),),
2682 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002683 # wrapper loop:
2684 Wrapped.__wrapped__ = Wrapped
2685 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2686 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002687
2688 def test_signature_on_lambdas(self):
2689 self.assertEqual(self.signature((lambda a=10: a)),
2690 ((('a', 10, ..., "positional_or_keyword"),),
2691 ...))
2692
2693 def test_signature_equality(self):
2694 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002695 self.assertFalse(inspect.signature(foo) == 42)
2696 self.assertTrue(inspect.signature(foo) != 42)
2697 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2698 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002699
2700 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002701 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2702 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002703 self.assertEqual(
2704 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002705
2706 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002707 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2708 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002709 self.assertNotEqual(
2710 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002711
2712 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002713 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2714 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002715 self.assertNotEqual(
2716 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002717
2718 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002719 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2720 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002721 self.assertNotEqual(
2722 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002723
2724 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002725 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2726 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002727 self.assertNotEqual(
2728 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002729
2730 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002731 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2732 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002733 self.assertNotEqual(
2734 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002735 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002736 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
2737 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002738 self.assertNotEqual(
2739 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002740
2741 def foo(*, a, b, c): pass
2742 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002743 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2744 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002745 self.assertEqual(
2746 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002747
2748 def foo(*, a=1, b, c): pass
2749 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002750 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2751 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002752 self.assertEqual(
2753 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002754
2755 def foo(pos, *, a=1, b, c): pass
2756 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002757 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2758 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002759 self.assertEqual(
2760 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002761
2762 def foo(pos, *, a, b, c): pass
2763 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002764 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2765 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002766 self.assertNotEqual(
2767 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002768
2769 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2770 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002771 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2772 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002773 self.assertEqual(
2774 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002775
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002776 def test_signature_hashable(self):
2777 S = inspect.Signature
2778 P = inspect.Parameter
2779
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002780 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002781 foo_sig = inspect.signature(foo)
2782
2783 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2784
2785 self.assertEqual(hash(foo_sig), hash(manual_sig))
2786 self.assertNotEqual(hash(foo_sig),
2787 hash(manual_sig.replace(return_annotation='spam')))
2788
2789 def bar(a) -> 1: pass
2790 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2791
2792 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002793 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002794 hash(inspect.signature(foo))
2795
2796 def foo(a) -> {}: pass
2797 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2798 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002799
2800 def test_signature_str(self):
2801 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2802 pass
2803 self.assertEqual(str(inspect.signature(foo)),
2804 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2805
2806 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2807 pass
2808 self.assertEqual(str(inspect.signature(foo)),
2809 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2810
2811 def foo():
2812 pass
2813 self.assertEqual(str(inspect.signature(foo)), '()')
2814
2815 def test_signature_str_positional_only(self):
2816 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002817 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002818
2819 def test(a_po, *, b, **kwargs):
2820 return a_po, kwargs
2821
2822 sig = inspect.signature(test)
2823 new_params = list(sig.parameters.values())
2824 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2825 test.__signature__ = sig.replace(parameters=new_params)
2826
2827 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002828 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002829
Yury Selivanov2393dca2014-01-27 15:07:58 -05002830 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2831 '(foo, /)')
2832
2833 self.assertEqual(str(S(parameters=[
2834 P('foo', P.POSITIONAL_ONLY),
2835 P('bar', P.VAR_KEYWORD)])),
2836 '(foo, /, **bar)')
2837
2838 self.assertEqual(str(S(parameters=[
2839 P('foo', P.POSITIONAL_ONLY),
2840 P('bar', P.VAR_POSITIONAL)])),
2841 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002842
2843 def test_signature_replace_anno(self):
2844 def test() -> 42:
2845 pass
2846
2847 sig = inspect.signature(test)
2848 sig = sig.replace(return_annotation=None)
2849 self.assertIs(sig.return_annotation, None)
2850 sig = sig.replace(return_annotation=sig.empty)
2851 self.assertIs(sig.return_annotation, sig.empty)
2852 sig = sig.replace(return_annotation=42)
2853 self.assertEqual(sig.return_annotation, 42)
2854 self.assertEqual(sig, inspect.signature(test))
2855
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002856 def test_signature_on_mangled_parameters(self):
2857 class Spam:
2858 def foo(self, __p1:1=2, *, __p2:2=3):
2859 pass
2860 class Ham(Spam):
2861 pass
2862
2863 self.assertEqual(self.signature(Spam.foo),
2864 ((('self', ..., ..., "positional_or_keyword"),
2865 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2866 ('_Spam__p2', 3, 2, "keyword_only")),
2867 ...))
2868
2869 self.assertEqual(self.signature(Spam.foo),
2870 self.signature(Ham.foo))
2871
Yury Selivanovda396452014-03-27 12:09:24 -04002872 def test_signature_from_callable_python_obj(self):
2873 class MySignature(inspect.Signature): pass
2874 def foo(a, *, b:1): pass
2875 foo_sig = MySignature.from_callable(foo)
2876 self.assertTrue(isinstance(foo_sig, MySignature))
2877
2878 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2879 "Signature information for builtins requires docstrings")
2880 def test_signature_from_callable_builtin_obj(self):
2881 class MySignature(inspect.Signature): pass
2882 sig = MySignature.from_callable(_pickle.Pickler)
2883 self.assertTrue(isinstance(sig, MySignature))
2884
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002885
2886class TestParameterObject(unittest.TestCase):
2887 def test_signature_parameter_kinds(self):
2888 P = inspect.Parameter
2889 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2890 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2891
2892 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2893 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2894
2895 def test_signature_parameter_object(self):
2896 p = inspect.Parameter('foo', default=10,
2897 kind=inspect.Parameter.POSITIONAL_ONLY)
2898 self.assertEqual(p.name, 'foo')
2899 self.assertEqual(p.default, 10)
2900 self.assertIs(p.annotation, p.empty)
2901 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2902
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002903 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002904 inspect.Parameter('foo', default=10, kind='123')
2905
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002906 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002907 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2908
Yury Selivanov2393dca2014-01-27 15:07:58 -05002909 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002910 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2911
Yury Selivanov2393dca2014-01-27 15:07:58 -05002912 with self.assertRaisesRegex(ValueError,
2913 'is not a valid parameter name'):
2914 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2915
Nick Coghlanb4b966e2016-06-04 14:40:03 -07002916 with self.assertRaisesRegex(ValueError,
2917 'is not a valid parameter name'):
2918 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
2919
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002920 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002921 inspect.Parameter('a', default=42,
2922 kind=inspect.Parameter.VAR_KEYWORD)
2923
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002924 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002925 inspect.Parameter('a', default=42,
2926 kind=inspect.Parameter.VAR_POSITIONAL)
2927
2928 p = inspect.Parameter('a', default=42,
2929 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002930 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002931 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2932
2933 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002934 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002935
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002936 def test_signature_parameter_hashable(self):
2937 P = inspect.Parameter
2938 foo = P('foo', kind=P.POSITIONAL_ONLY)
2939 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
2940 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
2941 default=42)))
2942 self.assertNotEqual(hash(foo),
2943 hash(foo.replace(kind=P.VAR_POSITIONAL)))
2944
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002945 def test_signature_parameter_equality(self):
2946 P = inspect.Parameter
2947 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2948
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002949 self.assertTrue(p == p)
2950 self.assertFalse(p != p)
2951 self.assertFalse(p == 42)
2952 self.assertTrue(p != 42)
2953 self.assertTrue(p == EqualsToAll())
2954 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002955
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002956 self.assertTrue(p == P('foo', default=42,
2957 kind=inspect.Parameter.KEYWORD_ONLY))
2958 self.assertFalse(p != P('foo', default=42,
2959 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002960
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002961 def test_signature_parameter_replace(self):
2962 p = inspect.Parameter('foo', default=42,
2963 kind=inspect.Parameter.KEYWORD_ONLY)
2964
2965 self.assertIsNot(p, p.replace())
2966 self.assertEqual(p, p.replace())
2967
2968 p2 = p.replace(annotation=1)
2969 self.assertEqual(p2.annotation, 1)
2970 p2 = p2.replace(annotation=p2.empty)
2971 self.assertEqual(p, p2)
2972
2973 p2 = p2.replace(name='bar')
2974 self.assertEqual(p2.name, 'bar')
2975 self.assertNotEqual(p2, p)
2976
Yury Selivanov2393dca2014-01-27 15:07:58 -05002977 with self.assertRaisesRegex(ValueError,
2978 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002979 p2 = p2.replace(name=p2.empty)
2980
2981 p2 = p2.replace(name='foo', default=None)
2982 self.assertIs(p2.default, None)
2983 self.assertNotEqual(p2, p)
2984
2985 p2 = p2.replace(name='foo', default=p2.empty)
2986 self.assertIs(p2.default, p2.empty)
2987
2988
2989 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2990 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2991 self.assertNotEqual(p2, p)
2992
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002993 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002994 p2 = p2.replace(kind=p2.empty)
2995
2996 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2997 self.assertEqual(p2, p)
2998
2999 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003000 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3001 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003002
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003003 @cpython_only
3004 def test_signature_parameter_implicit(self):
3005 with self.assertRaisesRegex(ValueError,
3006 'implicit arguments must be passed in as'):
3007 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3008
3009 param = inspect.Parameter(
3010 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3011 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3012 self.assertEqual(param.name, 'implicit0')
3013
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003014 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003015 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003016
3017 with self.assertRaises(AttributeError):
3018 p.foo = 'bar'
3019
3020 with self.assertRaises(AttributeError):
3021 p.kind = 123
3022
3023
3024class TestSignatureBind(unittest.TestCase):
3025 @staticmethod
3026 def call(func, *args, **kwargs):
3027 sig = inspect.signature(func)
3028 ba = sig.bind(*args, **kwargs)
3029 return func(*ba.args, **ba.kwargs)
3030
3031 def test_signature_bind_empty(self):
3032 def test():
3033 return 42
3034
3035 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003036 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003037 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003038 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003039 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003040 with self.assertRaisesRegex(
3041 TypeError, "got an unexpected keyword argument 'spam'"):
3042
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003043 self.call(test, spam=1)
3044
3045 def test_signature_bind_var(self):
3046 def test(*args, **kwargs):
3047 return args, kwargs
3048
3049 self.assertEqual(self.call(test), ((), {}))
3050 self.assertEqual(self.call(test, 1), ((1,), {}))
3051 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3052 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3053 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3054 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3055 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3056 ((1, 2), {'foo': 'bar'}))
3057
3058 def test_signature_bind_just_args(self):
3059 def test(a, b, c):
3060 return a, b, c
3061
3062 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3063
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003064 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003065 self.call(test, 1, 2, 3, 4)
3066
Yury Selivanov86872752015-05-19 00:27:49 -04003067 with self.assertRaisesRegex(TypeError,
3068 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003069 self.call(test, 1)
3070
Yury Selivanov86872752015-05-19 00:27:49 -04003071 with self.assertRaisesRegex(TypeError,
3072 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003073 self.call(test)
3074
3075 def test(a, b, c=10):
3076 return a, b, c
3077 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3078 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3079
3080 def test(a=1, b=2, c=3):
3081 return a, b, c
3082 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3083 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3084 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3085
3086 def test_signature_bind_varargs_order(self):
3087 def test(*args):
3088 return args
3089
3090 self.assertEqual(self.call(test), ())
3091 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3092
3093 def test_signature_bind_args_and_varargs(self):
3094 def test(a, b, c=3, *args):
3095 return a, b, c, args
3096
3097 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3098 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3099 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3100 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3101
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003102 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003103 "multiple values for argument 'c'"):
3104 self.call(test, 1, 2, 3, c=4)
3105
3106 def test_signature_bind_just_kwargs(self):
3107 def test(**kwargs):
3108 return kwargs
3109
3110 self.assertEqual(self.call(test), {})
3111 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3112 {'foo': 'bar', 'spam': 'ham'})
3113
3114 def test_signature_bind_args_and_kwargs(self):
3115 def test(a, b, c=3, **kwargs):
3116 return a, b, c, kwargs
3117
3118 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3119 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3120 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3121 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3122 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3123 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3124 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3125 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3126 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3127 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3128 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3129 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3130 (1, 2, 4, {'foo': 'bar'}))
3131 self.assertEqual(self.call(test, c=5, a=4, b=3),
3132 (4, 3, 5, {}))
3133
3134 def test_signature_bind_kwonly(self):
3135 def test(*, foo):
3136 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003137 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003138 'too many positional arguments'):
3139 self.call(test, 1)
3140 self.assertEqual(self.call(test, foo=1), 1)
3141
3142 def test(a, *, foo=1, bar):
3143 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003144 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003145 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003146 self.call(test, 1)
3147
3148 def test(foo, *, bar):
3149 return foo, bar
3150 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3151 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3152
Yury Selivanov86872752015-05-19 00:27:49 -04003153 with self.assertRaisesRegex(
3154 TypeError, "got an unexpected keyword argument 'spam'"):
3155
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003156 self.call(test, bar=2, foo=1, spam=10)
3157
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003158 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003159 'too many positional arguments'):
3160 self.call(test, 1, 2)
3161
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003162 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003163 'too many positional arguments'):
3164 self.call(test, 1, 2, bar=2)
3165
Yury Selivanov86872752015-05-19 00:27:49 -04003166 with self.assertRaisesRegex(
3167 TypeError, "got an unexpected keyword argument 'spam'"):
3168
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003169 self.call(test, 1, bar=2, spam='ham')
3170
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003171 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003172 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003173 self.call(test, 1)
3174
3175 def test(foo, *, bar, **bin):
3176 return foo, bar, bin
3177 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3178 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3179 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3180 (1, 2, {'spam': 'ham'}))
3181 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3182 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003183 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003184 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003185 self.call(test, spam='ham', bar=2)
3186 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3187 (1, 2, {'bin': 1, 'spam': 10}))
3188
3189 def test_signature_bind_arguments(self):
3190 def test(a, *args, b, z=100, **kwargs):
3191 pass
3192 sig = inspect.signature(test)
3193 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3194 # we won't have 'z' argument in the bound arguments object, as we didn't
3195 # pass it to the 'bind'
3196 self.assertEqual(tuple(ba.arguments.items()),
3197 (('a', 10), ('args', (20,)), ('b', 30),
3198 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3199 self.assertEqual(ba.kwargs,
3200 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3201 self.assertEqual(ba.args, (10, 20))
3202
3203 def test_signature_bind_positional_only(self):
3204 P = inspect.Parameter
3205
3206 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3207 return a_po, b_po, c_po, foo, bar, kwargs
3208
3209 sig = inspect.signature(test)
3210 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3211 for name in ('a_po', 'b_po', 'c_po'):
3212 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3213 new_sig = sig.replace(parameters=new_params.values())
3214 test.__signature__ = new_sig
3215
3216 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3217 (1, 2, 4, 5, 6, {}))
3218
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003219 self.assertEqual(self.call(test, 1, 2),
3220 (1, 2, 3, 42, 50, {}))
3221
3222 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3223 (1, 2, 3, 4, 5, {}))
3224
3225 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3226 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3227
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003228 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003229 self.call(test, 1, 2, c_po=4)
3230
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003231 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003232 self.call(test, a_po=1, b_po=2)
3233
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003234 def test_signature_bind_with_self_arg(self):
3235 # Issue #17071: one of the parameters is named "self
3236 def test(a, self, b):
3237 pass
3238 sig = inspect.signature(test)
3239 ba = sig.bind(1, 2, 3)
3240 self.assertEqual(ba.args, (1, 2, 3))
3241 ba = sig.bind(1, self=2, b=3)
3242 self.assertEqual(ba.args, (1, 2, 3))
3243
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003244 def test_signature_bind_vararg_name(self):
3245 def test(a, *args):
3246 return a, args
3247 sig = inspect.signature(test)
3248
Yury Selivanov86872752015-05-19 00:27:49 -04003249 with self.assertRaisesRegex(
3250 TypeError, "got an unexpected keyword argument 'args'"):
3251
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003252 sig.bind(a=0, args=1)
3253
3254 def test(*args, **kwargs):
3255 return args, kwargs
3256 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3257
3258 sig = inspect.signature(test)
3259 ba = sig.bind(args=1)
3260 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3261
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003262 @cpython_only
3263 def test_signature_bind_implicit_arg(self):
3264 # Issue #19611: getcallargs should work with set comprehensions
3265 def make_set():
3266 return {z * z for z in range(5)}
3267 setcomp_code = make_set.__code__.co_consts[1]
3268 setcomp_func = types.FunctionType(setcomp_code, {})
3269
3270 iterator = iter(range(5))
3271 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3272
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003273
3274class TestBoundArguments(unittest.TestCase):
3275 def test_signature_bound_arguments_unhashable(self):
3276 def foo(a): pass
3277 ba = inspect.signature(foo).bind(1)
3278
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003279 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003280 hash(ba)
3281
3282 def test_signature_bound_arguments_equality(self):
3283 def foo(a): pass
3284 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003285 self.assertTrue(ba == ba)
3286 self.assertFalse(ba != ba)
3287 self.assertTrue(ba == EqualsToAll())
3288 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003289
3290 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003291 self.assertTrue(ba == ba2)
3292 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003293
3294 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003295 self.assertFalse(ba == ba3)
3296 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003297 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003298 self.assertTrue(ba == ba3)
3299 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003300
3301 def bar(b): pass
3302 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003303 self.assertFalse(ba == ba4)
3304 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003305
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003306 def foo(*, a, b): pass
3307 sig = inspect.signature(foo)
3308 ba1 = sig.bind(a=1, b=2)
3309 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003310 self.assertTrue(ba1 == ba2)
3311 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003312
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003313 def test_signature_bound_arguments_pickle(self):
3314 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3315 sig = inspect.signature(foo)
3316 ba = sig.bind(20, 30, z={})
3317
3318 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3319 with self.subTest(pickle_ver=ver):
3320 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3321 self.assertEqual(ba, ba_pickled)
3322
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003323 def test_signature_bound_arguments_repr(self):
3324 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3325 sig = inspect.signature(foo)
3326 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003327 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003328
Yury Selivanovb907a512015-05-16 13:45:09 -04003329 def test_signature_bound_arguments_apply_defaults(self):
3330 def foo(a, b=1, *args, c:1={}, **kw): pass
3331 sig = inspect.signature(foo)
3332
3333 ba = sig.bind(20)
3334 ba.apply_defaults()
3335 self.assertEqual(
3336 list(ba.arguments.items()),
3337 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3338
3339 # Make sure that we preserve the order:
3340 # i.e. 'c' should be *before* 'kw'.
3341 ba = sig.bind(10, 20, 30, d=1)
3342 ba.apply_defaults()
3343 self.assertEqual(
3344 list(ba.arguments.items()),
3345 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3346
3347 # Make sure that BoundArguments produced by bind_partial()
3348 # are supported.
3349 def foo(a, b): pass
3350 sig = inspect.signature(foo)
3351 ba = sig.bind_partial(20)
3352 ba.apply_defaults()
3353 self.assertEqual(
3354 list(ba.arguments.items()),
3355 [('a', 20)])
3356
3357 # Test no args
3358 def foo(): pass
3359 sig = inspect.signature(foo)
3360 ba = sig.bind()
3361 ba.apply_defaults()
3362 self.assertEqual(list(ba.arguments.items()), [])
3363
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003364 # Make sure a no-args binding still acquires proper defaults.
3365 def foo(a='spam'): pass
3366 sig = inspect.signature(foo)
3367 ba = sig.bind()
3368 ba.apply_defaults()
3369 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3370
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003371
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003372class TestSignaturePrivateHelpers(unittest.TestCase):
3373 def test_signature_get_bound_param(self):
3374 getter = inspect._signature_get_bound_param
3375
3376 self.assertEqual(getter('($self)'), 'self')
3377 self.assertEqual(getter('($self, obj)'), 'self')
3378 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3379
Larry Hastings2623c8c2014-02-08 22:15:29 -08003380 def _strip_non_python_syntax(self, input,
3381 clean_signature, self_parameter, last_positional_only):
3382 computed_clean_signature, \
3383 computed_self_parameter, \
3384 computed_last_positional_only = \
3385 inspect._signature_strip_non_python_syntax(input)
3386 self.assertEqual(computed_clean_signature, clean_signature)
3387 self.assertEqual(computed_self_parameter, self_parameter)
3388 self.assertEqual(computed_last_positional_only, last_positional_only)
3389
3390 def test_signature_strip_non_python_syntax(self):
3391 self._strip_non_python_syntax(
3392 "($module, /, path, mode, *, dir_fd=None, " +
3393 "effective_ids=False,\n follow_symlinks=True)",
3394 "(module, path, mode, *, dir_fd=None, " +
3395 "effective_ids=False, follow_symlinks=True)",
3396 0,
3397 0)
3398
3399 self._strip_non_python_syntax(
3400 "($module, word, salt, /)",
3401 "(module, word, salt)",
3402 0,
3403 2)
3404
3405 self._strip_non_python_syntax(
3406 "(x, y=None, z=None, /)",
3407 "(x, y=None, z=None)",
3408 None,
3409 2)
3410
3411 self._strip_non_python_syntax(
3412 "(x, y=None, z=None)",
3413 "(x, y=None, z=None)",
3414 None,
3415 None)
3416
3417 self._strip_non_python_syntax(
3418 "(x,\n y=None,\n z = None )",
3419 "(x, y=None, z=None)",
3420 None,
3421 None)
3422
3423 self._strip_non_python_syntax(
3424 "",
3425 "",
3426 None,
3427 None)
3428
3429 self._strip_non_python_syntax(
3430 None,
3431 None,
3432 None,
3433 None)
3434
Nick Coghlan9c680b02015-04-13 12:54:54 -04003435class TestSignatureDefinitions(unittest.TestCase):
3436 # This test case provides a home for checking that particular APIs
3437 # have signatures available for introspection
3438
3439 @cpython_only
3440 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3441 "Signature information for builtins requires docstrings")
3442 def test_builtins_have_signatures(self):
3443 # This checks all builtin callables in CPython have signatures
3444 # A few have signatures Signature can't yet handle, so we skip those
3445 # since they will have to wait until PEP 457 adds the required
3446 # introspection support to the inspect module
3447 # Some others also haven't been converted yet for various other
3448 # reasons, so we also skip those for the time being, but design
3449 # the test to fail in order to indicate when it needs to be
3450 # updated.
3451 no_signature = set()
3452 # These need PEP 457 groups
3453 needs_groups = {"range", "slice", "dir", "getattr",
3454 "next", "iter", "vars"}
3455 no_signature |= needs_groups
3456 # These need PEP 457 groups or a signature change to accept None
3457 needs_semantic_update = {"round"}
3458 no_signature |= needs_semantic_update
3459 # These need *args support in Argument Clinic
3460 needs_varargs = {"min", "max", "print", "__build_class__"}
3461 no_signature |= needs_varargs
3462 # These simply weren't covered in the initial AC conversion
3463 # for builtin callables
3464 not_converted_yet = {"open", "__import__"}
3465 no_signature |= not_converted_yet
3466 # These builtin types are expected to provide introspection info
3467 types_with_signatures = set()
3468 # Check the signatures we expect to be there
3469 ns = vars(builtins)
3470 for name, obj in sorted(ns.items()):
3471 if not callable(obj):
3472 continue
3473 # The builtin types haven't been converted to AC yet
3474 if isinstance(obj, type) and (name not in types_with_signatures):
3475 # Note that this also skips all the exception types
3476 no_signature.add(name)
3477 if (name in no_signature):
3478 # Not yet converted
3479 continue
3480 with self.subTest(builtin=name):
3481 self.assertIsNotNone(inspect.signature(obj))
3482 # Check callables that haven't been converted don't claim a signature
3483 # This ensures this test will start failing as more signatures are
3484 # added, so the affected items can be moved into the scope of the
3485 # regression test above
3486 for name in no_signature:
3487 with self.subTest(builtin=name):
3488 self.assertIsNone(obj.__text_signature__)
3489
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003490
Nick Coghlane8c45d62013-07-28 20:00:01 +10003491class TestUnwrap(unittest.TestCase):
3492
3493 def test_unwrap_one(self):
3494 def func(a, b):
3495 return a + b
3496 wrapper = functools.lru_cache(maxsize=20)(func)
3497 self.assertIs(inspect.unwrap(wrapper), func)
3498
3499 def test_unwrap_several(self):
3500 def func(a, b):
3501 return a + b
3502 wrapper = func
3503 for __ in range(10):
3504 @functools.wraps(wrapper)
3505 def wrapper():
3506 pass
3507 self.assertIsNot(wrapper.__wrapped__, func)
3508 self.assertIs(inspect.unwrap(wrapper), func)
3509
3510 def test_stop(self):
3511 def func1(a, b):
3512 return a + b
3513 @functools.wraps(func1)
3514 def func2():
3515 pass
3516 @functools.wraps(func2)
3517 def wrapper():
3518 pass
3519 func2.stop_here = 1
3520 unwrapped = inspect.unwrap(wrapper,
3521 stop=(lambda f: hasattr(f, "stop_here")))
3522 self.assertIs(unwrapped, func2)
3523
3524 def test_cycle(self):
3525 def func1(): pass
3526 func1.__wrapped__ = func1
3527 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3528 inspect.unwrap(func1)
3529
3530 def func2(): pass
3531 func2.__wrapped__ = func1
3532 func1.__wrapped__ = func2
3533 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3534 inspect.unwrap(func1)
3535 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3536 inspect.unwrap(func2)
3537
3538 def test_unhashable(self):
3539 def func(): pass
3540 func.__wrapped__ = None
3541 class C:
3542 __hash__ = None
3543 __wrapped__ = func
3544 self.assertIsNone(inspect.unwrap(C()))
3545
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003546class TestMain(unittest.TestCase):
3547 def test_only_source(self):
3548 module = importlib.import_module('unittest')
3549 rc, out, err = assert_python_ok('-m', 'inspect',
3550 'unittest')
3551 lines = out.decode().splitlines()
3552 # ignore the final newline
3553 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3554 self.assertEqual(err, b'')
3555
Yury Selivanov42407ab2014-06-23 10:23:50 -07003556 def test_custom_getattr(self):
3557 def foo():
3558 pass
3559 foo.__signature__ = 42
3560 with self.assertRaises(TypeError):
3561 inspect.signature(foo)
3562
Brett Cannon634a8fc2013-10-02 10:25:42 -04003563 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003564 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003565 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003566 rc, out, err = assert_python_ok('-m', 'inspect',
3567 'concurrent.futures:ThreadPoolExecutor')
3568 lines = out.decode().splitlines()
3569 # ignore the final newline
3570 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003571 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003572 self.assertEqual(err, b'')
3573
3574 def test_builtins(self):
3575 module = importlib.import_module('unittest')
3576 _, out, err = assert_python_failure('-m', 'inspect',
3577 'sys')
3578 lines = err.decode().splitlines()
3579 self.assertEqual(lines, ["Can't get info for builtin modules."])
3580
3581 def test_details(self):
3582 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003583 args = support.optim_args_from_interpreter_flags()
3584 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003585 'unittest', '--details')
3586 output = out.decode()
3587 # Just a quick sanity check on the output
3588 self.assertIn(module.__name__, output)
3589 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003590 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003591 self.assertEqual(err, b'')
3592
3593
Yury Selivanovef1e7502014-12-08 16:05:34 -05003594class TestReload(unittest.TestCase):
3595
3596 src_before = textwrap.dedent("""\
3597def foo():
3598 print("Bla")
3599 """)
3600
3601 src_after = textwrap.dedent("""\
3602def foo():
3603 print("Oh no!")
3604 """)
3605
3606 def assertInspectEqual(self, path, source):
3607 inspected_src = inspect.getsource(source)
3608 with open(path) as src:
3609 self.assertEqual(
3610 src.read().splitlines(True),
3611 inspected_src.splitlines(True)
3612 )
3613
3614 def test_getsource_reload(self):
3615 # see issue 1218234
3616 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3617 module = importlib.import_module(name)
3618 self.assertInspectEqual(path, module)
3619 with open(path, 'w') as src:
3620 src.write(self.src_after)
3621 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003622
Nick Coghlane8c45d62013-07-28 20:00:01 +10003623
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003624def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003625 run_unittest(
3626 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3627 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3628 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003629 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003630 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003631 TestBoundArguments, TestSignaturePrivateHelpers,
3632 TestSignatureDefinitions,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003633 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
3634 TestGetCoroutineState
Michael Foord95fc51d2010-11-20 15:07:30 +00003635 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003636
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003637if __name__ == "__main__":
3638 test_main()