blob: 9d9fedc21e57959d473b0292903060510d0fdafb [file] [log] [blame]
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001import builtins
Guido van Rossum813b0e52007-05-21 18:11:34 +00002import collections
Larry Hastings5c661892014-01-24 06:17:25 -08003import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10004import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10005import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08006import inspect
7import io
8import linecache
9import os
Christian Heimesa3538eb2007-11-06 11:44:48 +000010from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080011import _pickle
Yury Selivanova5d63dd2014-03-27 11:31:43 -040012import pickle
Larry Hastings5c661892014-01-24 06:17:25 -080013import shutil
14import sys
15import types
Yury Selivanovef1e7502014-12-08 16:05:34 -050016import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080017import unicodedata
18import unittest
Yury Selivanova773de02014-02-21 18:30:53 -050019import unittest.mock
Yury Selivanov75445082015-05-11 22:57:16 -040020import warnings
Larry Hastings5c661892014-01-24 06:17:25 -080021
Brett Cannon634a8fc2013-10-02 10:25:42 -040022try:
23 from concurrent.futures import ThreadPoolExecutor
24except ImportError:
25 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000026
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020027from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Nick Coghlanf9e227e2014-08-17 14:01:19 +100028from test.support import MISSING_C_DOCSTRINGS, cpython_only
Berker Peksagce643912015-05-06 06:33:17 +030029from test.support.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000030from test import inspect_fodder as mod
31from test import inspect_fodder2 as mod2
Victor Stinner9def2842016-01-18 12:15:08 +010032from test import support
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000033
Yury Selivanovef1e7502014-12-08 16:05:34 -050034from test.test_import import _ready_to_import
35
R. David Murray74b89242009-05-13 17:33:03 +000036
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000037# Functions tested in this suite:
38# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000039# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
40# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
Berker Peksagfa3922c2015-07-31 04:11:29 +030041# getclasstree, getargvalues, formatargspec, formatargvalues,
Christian Heimes7131fd92008-02-19 14:21:46 +000042# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000043
Nick Coghlanf088e5e2008-12-14 11:50:48 +000044# NOTE: There are some additional tests relating to interaction with
45# zipimport in the test_zipimport_support test module.
46
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000047modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000048if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000049 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000050
Christian Heimesa3538eb2007-11-06 11:44:48 +000051# Normalize file names: on Windows, the case of file names of compiled
52# modules depends on the path used to start the python executable.
53modfile = normcase(modfile)
54
55def revise(filename, *args):
56 return (normcase(filename),) + args
57
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000058git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000059
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000060class IsTestBase(unittest.TestCase):
61 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
62 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000063 inspect.ismodule, inspect.istraceback,
Yury Selivanov75445082015-05-11 22:57:16 -040064 inspect.isgenerator, inspect.isgeneratorfunction,
Yury Selivanoveb636452016-09-08 22:01:51 -070065 inspect.iscoroutine, inspect.iscoroutinefunction,
66 inspect.isasyncgen, inspect.isasyncgenfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000067
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000068 def istest(self, predicate, exp):
69 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000070 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000071
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000072 for other in self.predicates - set([predicate]):
Yury Selivanov75445082015-05-11 22:57:16 -040073 if (predicate == inspect.isgeneratorfunction or \
Yury Selivanoveb636452016-09-08 22:01:51 -070074 predicate == inspect.isasyncgenfunction or \
Yury Selivanov75445082015-05-11 22:57:16 -040075 predicate == inspect.iscoroutinefunction) and \
Christian Heimes7131fd92008-02-19 14:21:46 +000076 other == inspect.isfunction:
77 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000078 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000079
Christian Heimes7131fd92008-02-19 14:21:46 +000080def generator_function_example(self):
81 for i in range(2):
82 yield i
83
Yury Selivanoveb636452016-09-08 22:01:51 -070084async def async_generator_function_example(self):
85 async for i in range(2):
86 yield i
87
Yury Selivanov75445082015-05-11 22:57:16 -040088async def coroutine_function_example(self):
89 return 'spam'
90
91@types.coroutine
92def gen_coroutine_function_example(self):
93 yield
94 return 'spam'
95
Serhiy Storchaka3018cc42015-07-18 23:19:05 +030096class EqualsToAll:
97 def __eq__(self, other):
98 return True
Yury Selivanova5d63dd2014-03-27 11:31:43 -040099
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000100class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +0000101
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000102 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200103 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000104 self.istest(inspect.isbuiltin, 'sys.exit')
105 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +0000106 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200107 try:
108 1/0
109 except:
110 tb = sys.exc_info()[2]
111 self.istest(inspect.isframe, 'tb.tb_frame')
112 self.istest(inspect.istraceback, 'tb')
113 if hasattr(types, 'GetSetDescriptorType'):
114 self.istest(inspect.isgetsetdescriptor,
115 'type(tb.tb_frame).f_locals')
116 else:
117 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
118 finally:
119 # Clear traceback and all the frames and local variables hanging to it.
120 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000121 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000122 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000123 self.istest(inspect.ismethod, 'git.argue')
124 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000125 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000126 self.istest(inspect.isgenerator, '(x for x in range(2))')
127 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanoveb636452016-09-08 22:01:51 -0700128 self.istest(inspect.isasyncgen,
129 'async_generator_function_example(1)')
130 self.istest(inspect.isasyncgenfunction,
131 'async_generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400132
133 with warnings.catch_warnings():
134 warnings.simplefilter("ignore")
135 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
136 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
137
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000138 if hasattr(types, 'MemberDescriptorType'):
139 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
140 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000141 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000142
Yury Selivanov75445082015-05-11 22:57:16 -0400143 def test_iscoroutine(self):
144 gen_coro = gen_coroutine_function_example(1)
145 coro = coroutine_function_example(1)
146
Yury Selivanov5376ba92015-06-22 12:19:30 -0400147 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400148 inspect.iscoroutinefunction(gen_coroutine_function_example))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400149 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400150
151 self.assertTrue(
152 inspect.isgeneratorfunction(gen_coroutine_function_example))
153 self.assertTrue(inspect.isgenerator(gen_coro))
154
155 self.assertTrue(
156 inspect.iscoroutinefunction(coroutine_function_example))
157 self.assertTrue(inspect.iscoroutine(coro))
158
159 self.assertFalse(
160 inspect.isgeneratorfunction(coroutine_function_example))
161 self.assertFalse(inspect.isgenerator(coro))
162
163 coro.close(); gen_coro.close() # silence warnings
164
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400165 def test_isawaitable(self):
166 def gen(): yield
167 self.assertFalse(inspect.isawaitable(gen()))
168
169 coro = coroutine_function_example(1)
170 gen_coro = gen_coroutine_function_example(1)
171
172 self.assertTrue(inspect.isawaitable(coro))
173 self.assertTrue(inspect.isawaitable(gen_coro))
174
175 class Future:
176 def __await__():
177 pass
178 self.assertTrue(inspect.isawaitable(Future()))
179 self.assertFalse(inspect.isawaitable(Future))
180
181 class NotFuture: pass
182 not_fut = NotFuture()
183 not_fut.__await__ = lambda: None
184 self.assertFalse(inspect.isawaitable(not_fut))
185
186 coro.close(); gen_coro.close() # silence warnings
187
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000188 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000189 self.assertTrue(inspect.isroutine(mod.spam))
190 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000191
Benjamin Petersonc4656002009-01-17 22:41:18 +0000192 def test_isclass(self):
193 self.istest(inspect.isclass, 'mod.StupidGit')
194 self.assertTrue(inspect.isclass(list))
195
196 class CustomGetattr(object):
197 def __getattr__(self, attr):
198 return None
199 self.assertFalse(inspect.isclass(CustomGetattr()))
200
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000201 def test_get_slot_members(self):
202 class C(object):
203 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000204 x = C()
205 x.a = 42
206 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000207 self.assertIn('a', members)
208 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000209
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000210 def test_isabstract(self):
211 from abc import ABCMeta, abstractmethod
212
213 class AbstractClassExample(metaclass=ABCMeta):
214
215 @abstractmethod
216 def foo(self):
217 pass
218
219 class ClassExample(AbstractClassExample):
220 def foo(self):
221 pass
222
223 a = ClassExample()
224
225 # Test general behaviour.
226 self.assertTrue(inspect.isabstract(AbstractClassExample))
227 self.assertFalse(inspect.isabstract(ClassExample))
228 self.assertFalse(inspect.isabstract(a))
229 self.assertFalse(inspect.isabstract(int))
230 self.assertFalse(inspect.isabstract(5))
231
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000232
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000233class TestInterpreterStack(IsTestBase):
234 def __init__(self, *args, **kwargs):
235 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000236
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000237 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000238
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000239 def test_abuse_done(self):
240 self.istest(inspect.istraceback, 'git.ex[2]')
241 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000242
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000243 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000244 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000245 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000246 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000247 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000248 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000249 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000250 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000251 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000252 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400253 # Test named tuple fields
254 record = mod.st[0]
255 self.assertIs(record.frame, mod.fr)
256 self.assertEqual(record.lineno, 16)
257 self.assertEqual(record.filename, mod.__file__)
258 self.assertEqual(record.function, 'eggs')
259 self.assertIn('inspect.stack()', record.code_context[0])
260 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000261
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000262 def test_trace(self):
263 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000264 self.assertEqual(revise(*git.tr[0][1:]),
265 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
266 self.assertEqual(revise(*git.tr[1][1:]),
267 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
268 self.assertEqual(revise(*git.tr[2][1:]),
269 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000270
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000271 def test_frame(self):
272 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
273 self.assertEqual(args, ['x', 'y'])
274 self.assertEqual(varargs, None)
275 self.assertEqual(varkw, None)
276 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
277 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
278 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000279
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000280 def test_previous_frame(self):
281 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000282 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000283 self.assertEqual(varargs, 'g')
284 self.assertEqual(varkw, 'h')
285 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000286 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000287
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000288class GetSourceBase(unittest.TestCase):
289 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000290 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000291
Yury Selivanov6738b112015-05-16 10:10:21 -0400292 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000293 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000294 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000295
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000296 def sourcerange(self, top, bottom):
297 lines = self.source.split("\n")
298 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000299
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000300 def assertSourceEqual(self, obj, top, bottom):
301 self.assertEqual(inspect.getsource(obj),
302 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000303
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000304class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000305 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000306
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000307 def test_getclasses(self):
308 classes = inspect.getmembers(mod, inspect.isclass)
309 self.assertEqual(classes,
310 [('FesteringGob', mod.FesteringGob),
311 ('MalodorousPervert', mod.MalodorousPervert),
312 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300313 ('StupidGit', mod.StupidGit),
314 ('Tit', mod.MalodorousPervert),
315 ])
316 tree = inspect.getclasstree([cls[1] for cls in classes])
317 self.assertEqual(tree,
318 [(object, ()),
319 [(mod.ParrotDroppings, (object,)),
320 [(mod.FesteringGob, (mod.MalodorousPervert,
321 mod.ParrotDroppings))
322 ],
323 (mod.StupidGit, (object,)),
324 [(mod.MalodorousPervert, (mod.StupidGit,)),
325 [(mod.FesteringGob, (mod.MalodorousPervert,
326 mod.ParrotDroppings))
327 ]
328 ]
329 ]
330 ])
331 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000332 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000333 [(object, ()),
334 [(mod.ParrotDroppings, (object,)),
335 (mod.StupidGit, (object,)),
336 [(mod.MalodorousPervert, (mod.StupidGit,)),
337 [(mod.FesteringGob, (mod.MalodorousPervert,
338 mod.ParrotDroppings))
339 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000340 ]
341 ]
342 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000343
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000344 def test_getfunctions(self):
345 functions = inspect.getmembers(mod, inspect.isfunction)
346 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300347 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000348 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000349
R. David Murray378c0cf2010-02-24 01:46:21 +0000350 @unittest.skipIf(sys.flags.optimize >= 2,
351 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000352 def test_getdoc(self):
353 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
354 self.assertEqual(inspect.getdoc(mod.StupidGit),
355 'A longer,\n\nindented\n\ndocstring.')
356 self.assertEqual(inspect.getdoc(git.abuse),
357 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000358
Serhiy Storchaka5cf2b7252015-04-03 22:38:53 +0300359 @unittest.skipIf(sys.flags.optimize >= 2,
360 "Docstrings are omitted with -O2 and above")
361 def test_getdoc_inherited(self):
362 self.assertEqual(inspect.getdoc(mod.FesteringGob),
363 'A longer,\n\nindented\n\ndocstring.')
364 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
365 'Another\n\ndocstring\n\ncontaining\n\ntabs')
366 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
367 'Another\n\ndocstring\n\ncontaining\n\ntabs')
368 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
369 'The automatic gainsaying.')
370
371 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
372 def test_finddoc(self):
373 finddoc = inspect._finddoc
374 self.assertEqual(finddoc(int), int.__doc__)
375 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
376 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
377 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
378 self.assertEqual(finddoc(int.real), int.real.__doc__)
379
Georg Brandl0c77a822008-06-10 16:37:50 +0000380 def test_cleandoc(self):
381 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
382 'An\nindented\ndocstring.')
383
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000384 def test_getcomments(self):
385 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
386 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000387
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000388 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000389 # Check actual module
390 self.assertEqual(inspect.getmodule(mod), mod)
391 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000392 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000393 # Check a method (no __module__ attribute, falls back to filename)
394 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
395 # Do it again (check the caching isn't broken)
396 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
397 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000398 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000399 # Check filename override
400 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000401
Berker Peksagff0e3b72017-01-02 06:57:43 +0300402 def test_getframeinfo_get_first_line(self):
403 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
404 self.assertEqual(frame_info.code_context[0], "# line 1\n")
405 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
406
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000407 def test_getsource(self):
408 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200409 self.assertSourceEqual(mod.StupidGit, 21, 51)
410 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000411
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000412 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000413 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
414 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000415 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100416 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000417 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000418 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200419 try:
420 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
421 finally:
422 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000423
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000424 def test_getfile(self):
425 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000426
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500427 def test_getfile_class_without_module(self):
428 class CM(type):
429 @property
430 def __module__(cls):
431 raise AttributeError
432 class C(metaclass=CM):
433 pass
434 with self.assertRaises(TypeError):
435 inspect.getfile(C)
436
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000437 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000438 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000439 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000440 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000441 m.__file__ = "<string>" # hopefully not a real filename...
442 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000443 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000444 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000445 del sys.modules[name]
446 inspect.getmodule(compile('a=10','','single'))
447
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500448 def test_proceed_with_fake_filename(self):
449 '''doctest monkeypatches linecache to enable inspection'''
450 fn, source = '<test>', 'def x(): pass\n'
451 getlines = linecache.getlines
452 def monkey(filename, module_globals=None):
453 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300454 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500455 else:
456 return getlines(filename, module_globals)
457 linecache.getlines = monkey
458 try:
459 ns = {}
460 exec(compile(source, fn, 'single'), ns)
461 inspect.getsource(ns["x"])
462 finally:
463 linecache.getlines = getlines
464
Antoine Pitroua8723a02015-04-15 00:41:29 +0200465 def test_getsource_on_code_object(self):
466 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
467
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000468class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000469 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000470
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000471 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000472 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000473
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000474 def test_replacing_decorator(self):
475 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000476
Yury Selivanov081bbf62014-09-26 17:34:54 -0400477 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200478 self.assertSourceEqual(mod2.real, 130, 132)
479
480 def test_decorator_with_lambda(self):
481 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400482
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000483class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000484 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000485 def test_oneline_lambda(self):
486 # Test inspect.getsource with a one-line lambda function.
487 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000488
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000489 def test_threeline_lambda(self):
490 # Test inspect.getsource with a three-line lambda function,
491 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000492 self.assertSourceEqual(mod2.tll, 28, 30)
493
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000494 def test_twoline_indented_lambda(self):
495 # Test inspect.getsource with a two-line lambda function,
496 # where the second line _is_ indented.
497 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000498
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000499 def test_onelinefunc(self):
500 # Test inspect.getsource with a regular one-line function.
501 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000502
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000503 def test_manyargs(self):
504 # Test inspect.getsource with a regular function where
505 # the arguments are on two lines and _not_ indented and
506 # the body on the second line with the last arguments.
507 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000508
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000509 def test_twolinefunc(self):
510 # Test inspect.getsource with a regular function where
511 # the body is on two lines, following the argument list and
512 # continued on the next line by a \\.
513 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000514
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000515 def test_lambda_in_list(self):
516 # Test inspect.getsource with a one-line lambda function
517 # defined in a list, indented.
518 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000519
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000520 def test_anonymous(self):
521 # Test inspect.getsource with a lambda function defined
522 # as argument to another function.
523 self.assertSourceEqual(mod2.anonymous, 55, 55)
524
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000525class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000526 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000527
528 def test_with_comment(self):
529 self.assertSourceEqual(mod2.with_comment, 58, 59)
530
531 def test_multiline_sig(self):
532 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
533
Armin Rigodd5c0232005-09-25 11:45:45 +0000534 def test_nested_class(self):
535 self.assertSourceEqual(mod2.func69().func71, 71, 72)
536
537 def test_one_liner_followed_by_non_name(self):
538 self.assertSourceEqual(mod2.func77, 77, 77)
539
540 def test_one_liner_dedent_non_name(self):
541 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
542
543 def test_with_comment_instead_of_docstring(self):
544 self.assertSourceEqual(mod2.func88, 88, 90)
545
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000546 def test_method_in_dynamic_class(self):
547 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
548
R David Murray32562d72014-10-03 11:15:38 -0400549 # This should not skip for CPython, but might on a repackaged python where
550 # unicodedata is not an external module, or on pypy.
551 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
552 unicodedata.__file__.endswith('.py'),
553 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000554 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200555 self.assertRaises(OSError, inspect.getsource, unicodedata)
556 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000557
R. David Murraya1b37402010-06-17 02:04:29 +0000558 def test_findsource_code_in_linecache(self):
559 lines = ["x=1"]
560 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200561 self.assertRaises(OSError, inspect.findsource, co)
562 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000563 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200564 try:
565 self.assertEqual(inspect.findsource(co), (lines,0))
566 self.assertEqual(inspect.getsource(co), lines[0])
567 finally:
568 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000569
Ezio Melotti1b145922013-03-30 05:17:24 +0200570 def test_findsource_without_filename(self):
571 for fname in ['', '<string>']:
572 co = compile('x=1', fname, "exec")
573 self.assertRaises(IOError, inspect.findsource, co)
574 self.assertRaises(IOError, inspect.getsource, co)
575
Antoine Pitroua8723a02015-04-15 00:41:29 +0200576 def test_getsource_on_method(self):
577 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
578
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300579 def test_nested_func(self):
580 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
581
582
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000583class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400584 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000585 self.tempdir = TESTFN + '_dir'
586 os.mkdir(self.tempdir)
587 with open(os.path.join(self.tempdir,
588 'inspect_fodder3%spy' % os.extsep), 'w') as f:
589 f.write("class X:\n pass # No EOL")
590 with DirsOnSysPath(self.tempdir):
591 import inspect_fodder3 as mod3
592 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400593 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000594
595 def tearDown(self):
596 shutil.rmtree(self.tempdir)
597
598 def test_class(self):
599 self.assertSourceEqual(self.fodderModule.X, 1, 2)
600
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100601
602class _BrokenDataDescriptor(object):
603 """
604 A broken data descriptor. See bug #1785.
605 """
606 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700607 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100608
609 def __set__(*args):
610 raise RuntimeError
611
612 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700613 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100614
615
616class _BrokenMethodDescriptor(object):
617 """
618 A broken method descriptor. See bug #1785.
619 """
620 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700621 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100622
623 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700624 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100625
626
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000627# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000628def attrs_wo_objs(cls):
629 return [t[:3] for t in inspect.classify_class_attrs(cls)]
630
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100631
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000632class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000633 def test_newstyle_mro(self):
634 # The same w/ new-class MRO.
635 class A(object): pass
636 class B(A): pass
637 class C(A): pass
638 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000639
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000640 expected = (D, B, C, A, object)
641 got = inspect.getmro(D)
642 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000643
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500644 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
645 varkw_e=None, defaults_e=None, formatted=None):
646 with self.assertWarns(DeprecationWarning):
647 args, varargs, varkw, defaults = inspect.getargspec(routine)
648 self.assertEqual(args, args_e)
649 self.assertEqual(varargs, varargs_e)
650 self.assertEqual(varkw, varkw_e)
651 self.assertEqual(defaults, defaults_e)
652 if formatted is not None:
653 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
654 formatted)
655
Christian Heimes3795b532007-11-08 13:48:53 +0000656 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
657 varkw_e=None, defaults_e=None,
658 kwonlyargs_e=[], kwonlydefaults_e=None,
659 ann_e={}, formatted=None):
660 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
661 inspect.getfullargspec(routine)
662 self.assertEqual(args, args_e)
663 self.assertEqual(varargs, varargs_e)
664 self.assertEqual(varkw, varkw_e)
665 self.assertEqual(defaults, defaults_e)
666 self.assertEqual(kwonlyargs, kwonlyargs_e)
667 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
668 self.assertEqual(ann, ann_e)
669 if formatted is not None:
670 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
671 kwonlyargs, kwonlydefaults, ann),
672 formatted)
673
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500674 def test_getargspec(self):
675 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
676
677 self.assertArgSpecEquals(mod.spam,
678 ['a', 'b', 'c', 'd', 'e', 'f'],
679 'g', 'h', (3, 4, 5),
680 '(a, b, c, d=3, e=4, f=5, *g, **h)')
681
682 self.assertRaises(ValueError, self.assertArgSpecEquals,
683 mod2.keyworded, [])
684
685 self.assertRaises(ValueError, self.assertArgSpecEquals,
686 mod2.annotated, [])
687 self.assertRaises(ValueError, self.assertArgSpecEquals,
688 mod2.keyword_only_arg, [])
689
690
Christian Heimes3795b532007-11-08 13:48:53 +0000691 def test_getfullargspec(self):
692 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
693 kwonlyargs_e=['arg2'],
694 kwonlydefaults_e={'arg2':1},
695 formatted='(*arg1, arg2=1)')
696
697 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000698 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000699 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000700 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
701 kwonlyargs_e=['arg'],
702 formatted='(*, arg)')
703
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500704 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500705 # Issue 20684: low level introspection API must ignore __wrapped__
706 @functools.wraps(mod.spam)
707 def ham(x, y):
708 pass
709 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500710 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500711 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
712 self.assertFullArgSpecEquals(functools.partial(ham),
713 ['x', 'y'], formatted='(x, y)')
714 # Other variants
715 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500716 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
717 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500718 class C:
719 @functools.wraps(mod.spam)
720 def ham(self, x, y):
721 pass
722 pham = functools.partialmethod(ham)
723 @functools.wraps(mod.spam)
724 def __call__(self, x, y):
725 pass
726 check_method(C())
727 check_method(C.ham)
728 check_method(C().ham)
729 check_method(C.pham)
730 check_method(C().pham)
731
732 class C_new:
733 @functools.wraps(mod.spam)
734 def __new__(self, x, y):
735 pass
736 check_method(C_new)
737
738 class C_init:
739 @functools.wraps(mod.spam)
740 def __init__(self, x, y):
741 pass
742 check_method(C_init)
743
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500744 def test_getfullargspec_signature_attr(self):
745 def test():
746 pass
747 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
748 test.__signature__ = inspect.Signature(parameters=(spam_param,))
749
750 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
751
Yury Selivanov4cb93912014-01-29 11:54:12 -0500752 def test_getfullargspec_signature_annos(self):
753 def test(a:'spam') -> 'ham': pass
754 spec = inspect.getfullargspec(test)
755 self.assertEqual(test.__annotations__, spec.annotations)
756
757 def test(): pass
758 spec = inspect.getfullargspec(test)
759 self.assertEqual(test.__annotations__, spec.annotations)
760
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500761 @unittest.skipIf(MISSING_C_DOCSTRINGS,
762 "Signature information for builtins requires docstrings")
763 def test_getfullargspec_builtin_methods(self):
764 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
765 args_e=['self', 'obj'], formatted='(self, obj)')
766
767 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
768 args_e=['self', 'obj'], formatted='(self, obj)')
769
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500770 self.assertFullArgSpecEquals(
771 os.stat,
772 args_e=['path'],
773 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
774 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
775 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
776
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200777 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500778 @unittest.skipIf(MISSING_C_DOCSTRINGS,
779 "Signature information for builtins requires docstrings")
780 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200781 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500782 builtin = _testcapi.docstring_with_signature_with_defaults
783 spec = inspect.getfullargspec(builtin)
784 self.assertEqual(spec.defaults[0], 'avocado')
785
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200786 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500787 @unittest.skipIf(MISSING_C_DOCSTRINGS,
788 "Signature information for builtins requires docstrings")
789 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200790 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500791 builtin = _testcapi.docstring_no_signature
792 with self.assertRaises(TypeError):
793 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000794
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500795 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000796 class A(object):
797 def m(self):
798 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500799 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000800
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000801 def test_classify_newstyle(self):
802 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000803
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000804 def s(): pass
805 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000806
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000807 def c(cls): pass
808 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000809
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000810 def getp(self): pass
811 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000812
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000813 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000814
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000815 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000816
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000817 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000818
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100819 dd = _BrokenDataDescriptor()
820 md = _BrokenMethodDescriptor()
821
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000822 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500823
824 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
825 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
826
Benjamin Peterson577473f2010-01-19 00:09:57 +0000827 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
828 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
829 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000830 self.assertIn(('m', 'method', A), attrs,
831 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000832 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
833 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100834 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
835 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000836
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000837 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000838
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000839 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000840
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000841 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000842 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
843 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
844 self.assertIn(('p', 'property', A), attrs, 'missing property')
845 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
846 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
847 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100848 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
849 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000850
851
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000852 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000853
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000854 def m(self): pass
855 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000856
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000857 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000858 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
859 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
860 self.assertIn(('p', 'property', A), attrs, 'missing property')
861 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
862 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
863 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100864 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
865 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000866
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000867 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000868
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000869 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000870
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000871 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000872 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
873 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
874 self.assertIn(('p', 'property', A), attrs, 'missing property')
875 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
876 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
877 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100878 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
879 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
880
881 def test_classify_builtin_types(self):
882 # Simple sanity check that all built-in types can have their
883 # attributes classified.
884 for name in dir(__builtins__):
885 builtin = getattr(__builtins__, name)
886 if isinstance(builtin, type):
887 inspect.classify_class_attrs(builtin)
888
Ethan Furman63c141c2013-10-18 00:27:39 -0700889 def test_classify_DynamicClassAttribute(self):
890 class Meta(type):
891 def __getattr__(self, name):
892 if name == 'ham':
893 return 'spam'
894 return super().__getattr__(name)
895 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700896 @types.DynamicClassAttribute
897 def ham(self):
898 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700899 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
900 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700901 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700902 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
903
Yury Selivanovbf341fb2015-05-21 15:41:57 -0400904 def test_classify_overrides_bool(self):
905 class NoBool(object):
906 def __eq__(self, other):
907 return NoBool()
908
909 def __bool__(self):
910 raise NotImplementedError(
911 "This object does not specify a boolean value")
912
913 class HasNB(object):
914 dd = NoBool()
915
916 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
917 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
918
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700919 def test_classify_metaclass_class_attribute(self):
920 class Meta(type):
921 fish = 'slap'
922 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200923 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700924 class Class(metaclass=Meta):
925 pass
926 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
927 self.assertIn(should_find, inspect.classify_class_attrs(Class))
928
Ethan Furman63c141c2013-10-18 00:27:39 -0700929 def test_classify_VirtualAttribute(self):
930 class Meta(type):
931 def __dir__(cls):
932 return ['__class__', '__module__', '__name__', 'BOOM']
933 def __getattr__(self, name):
934 if name =='BOOM':
935 return 42
936 return super().__getattr(name)
937 class Class(metaclass=Meta):
938 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700939 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700940 self.assertIn(should_find, inspect.classify_class_attrs(Class))
941
942 def test_classify_VirtualAttribute_multi_classes(self):
943 class Meta1(type):
944 def __dir__(cls):
945 return ['__class__', '__module__', '__name__', 'one']
946 def __getattr__(self, name):
947 if name =='one':
948 return 1
949 return super().__getattr__(name)
950 class Meta2(type):
951 def __dir__(cls):
952 return ['__class__', '__module__', '__name__', 'two']
953 def __getattr__(self, name):
954 if name =='two':
955 return 2
956 return super().__getattr__(name)
957 class Meta3(Meta1, Meta2):
958 def __dir__(cls):
959 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
960 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
961 def __getattr__(self, name):
962 if name =='three':
963 return 3
964 return super().__getattr__(name)
965 class Class1(metaclass=Meta1):
966 pass
967 class Class2(Class1, metaclass=Meta3):
968 pass
969
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700970 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
971 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
972 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700973 cca = inspect.classify_class_attrs(Class2)
974 for sf in (should_find1, should_find2, should_find3):
975 self.assertIn(sf, cca)
976
977 def test_classify_class_attrs_with_buggy_dir(self):
978 class M(type):
979 def __dir__(cls):
980 return ['__class__', '__name__', 'missing']
981 class C(metaclass=M):
982 pass
983 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
984 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700985
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100986 def test_getmembers_descriptors(self):
987 class A(object):
988 dd = _BrokenDataDescriptor()
989 md = _BrokenMethodDescriptor()
990
991 def pred_wrapper(pred):
992 # A quick'n'dirty way to discard standard attributes of new-style
993 # classes.
994 class Empty(object):
995 pass
996 def wrapped(x):
997 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
998 return False
999 return pred(x)
1000 return wrapped
1001
1002 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1003 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1004
1005 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1006 [('md', A.__dict__['md'])])
1007 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1008 [('dd', A.__dict__['dd'])])
1009
1010 class B(A):
1011 pass
1012
1013 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1014 [('md', A.__dict__['md'])])
1015 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1016 [('dd', A.__dict__['dd'])])
1017
Antoine Pitrou0c603812012-01-18 17:40:18 +01001018 def test_getmembers_method(self):
1019 class B:
1020 def f(self):
1021 pass
1022
1023 self.assertIn(('f', B.f), inspect.getmembers(B))
1024 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1025 b = B()
1026 self.assertIn(('f', b.f), inspect.getmembers(b))
1027 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1028
Ethan Furmane03ea372013-09-25 07:14:41 -07001029 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001030 class M(type):
1031 def __getattr__(cls, name):
1032 if name == 'eggs':
1033 return 'scrambled'
1034 return super().__getattr__(name)
1035 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001036 @types.DynamicClassAttribute
1037 def eggs(self):
1038 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001039 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1040 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1041
1042 def test_getmembers_with_buggy_dir(self):
1043 class M(type):
1044 def __dir__(cls):
1045 return ['__class__', '__name__', 'missing']
1046 class C(metaclass=M):
1047 pass
1048 attrs = [a[0] for a in inspect.getmembers(C)]
1049 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001050
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001051
Nick Coghlan2f92e542012-06-23 19:39:55 +10001052_global_ref = object()
1053class TestGetClosureVars(unittest.TestCase):
1054
1055 def test_name_resolution(self):
1056 # Basic test of the 4 different resolution mechanisms
1057 def f(nonlocal_ref):
1058 def g(local_ref):
1059 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1060 return g
1061 _arg = object()
1062 nonlocal_vars = {"nonlocal_ref": _arg}
1063 global_vars = {"_global_ref": _global_ref}
1064 builtin_vars = {"print": print}
1065 unbound_names = {"unbound_ref"}
1066 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1067 builtin_vars, unbound_names)
1068 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1069
1070 def test_generator_closure(self):
1071 def f(nonlocal_ref):
1072 def g(local_ref):
1073 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1074 yield
1075 return g
1076 _arg = object()
1077 nonlocal_vars = {"nonlocal_ref": _arg}
1078 global_vars = {"_global_ref": _global_ref}
1079 builtin_vars = {"print": print}
1080 unbound_names = {"unbound_ref"}
1081 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1082 builtin_vars, unbound_names)
1083 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1084
1085 def test_method_closure(self):
1086 class C:
1087 def f(self, nonlocal_ref):
1088 def g(local_ref):
1089 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1090 return g
1091 _arg = object()
1092 nonlocal_vars = {"nonlocal_ref": _arg}
1093 global_vars = {"_global_ref": _global_ref}
1094 builtin_vars = {"print": print}
1095 unbound_names = {"unbound_ref"}
1096 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1097 builtin_vars, unbound_names)
1098 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1099
1100 def test_nonlocal_vars(self):
1101 # More complex tests of nonlocal resolution
1102 def _nonlocal_vars(f):
1103 return inspect.getclosurevars(f).nonlocals
1104
1105 def make_adder(x):
1106 def add(y):
1107 return x + y
1108 return add
1109
1110 def curry(func, arg1):
1111 return lambda arg2: func(arg1, arg2)
1112
1113 def less_than(a, b):
1114 return a < b
1115
1116 # The infamous Y combinator.
1117 def Y(le):
1118 def g(f):
1119 return le(lambda x: f(f)(x))
1120 Y.g_ref = g
1121 return g(g)
1122
1123 def check_y_combinator(func):
1124 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1125
1126 inc = make_adder(1)
1127 add_two = make_adder(2)
1128 greater_than_five = curry(less_than, 5)
1129
1130 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1131 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1132 self.assertEqual(_nonlocal_vars(greater_than_five),
1133 {'arg1': 5, 'func': less_than})
1134 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1135 {'x': 3})
1136 Y(check_y_combinator)
1137
1138 def test_getclosurevars_empty(self):
1139 def foo(): pass
1140 _empty = inspect.ClosureVars({}, {}, {}, set())
1141 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1142 self.assertEqual(inspect.getclosurevars(foo), _empty)
1143
1144 def test_getclosurevars_error(self):
1145 class T: pass
1146 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1147 self.assertRaises(TypeError, inspect.getclosurevars, list)
1148 self.assertRaises(TypeError, inspect.getclosurevars, {})
1149
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001150 def _private_globals(self):
1151 code = """def f(): print(path)"""
1152 ns = {}
1153 exec(code, ns)
1154 return ns["f"], ns
1155
1156 def test_builtins_fallback(self):
1157 f, ns = self._private_globals()
1158 ns.pop("__builtins__", None)
1159 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1160 self.assertEqual(inspect.getclosurevars(f), expected)
1161
1162 def test_builtins_as_dict(self):
1163 f, ns = self._private_globals()
1164 ns["__builtins__"] = {"path":1}
1165 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1166 self.assertEqual(inspect.getclosurevars(f), expected)
1167
1168 def test_builtins_as_module(self):
1169 f, ns = self._private_globals()
1170 ns["__builtins__"] = os
1171 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1172 self.assertEqual(inspect.getclosurevars(f), expected)
1173
Nick Coghlan2f92e542012-06-23 19:39:55 +10001174
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001175class TestGetcallargsFunctions(unittest.TestCase):
1176
1177 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1178 locs = dict(locs or {}, func=func)
1179 r1 = eval('func(%s)' % call_params_string, None, locs)
1180 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1181 locs)
1182 self.assertEqual(r1, r2)
1183
1184 def assertEqualException(self, func, call_param_string, locs=None):
1185 locs = dict(locs or {}, func=func)
1186 try:
1187 eval('func(%s)' % call_param_string, None, locs)
1188 except Exception as e:
1189 ex1 = e
1190 else:
1191 self.fail('Exception not raised')
1192 try:
1193 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1194 locs)
1195 except Exception as e:
1196 ex2 = e
1197 else:
1198 self.fail('Exception not raised')
1199 self.assertIs(type(ex1), type(ex2))
1200 self.assertEqual(str(ex1), str(ex2))
1201 del ex1, ex2
1202
1203 def makeCallable(self, signature):
1204 """Create a function that returns its locals()"""
1205 code = "lambda %s: locals()"
1206 return eval(code % signature)
1207
1208 def test_plain(self):
1209 f = self.makeCallable('a, b=1')
1210 self.assertEqualCallArgs(f, '2')
1211 self.assertEqualCallArgs(f, '2, 3')
1212 self.assertEqualCallArgs(f, 'a=2')
1213 self.assertEqualCallArgs(f, 'b=3, a=2')
1214 self.assertEqualCallArgs(f, '2, b=3')
1215 # expand *iterable / **mapping
1216 self.assertEqualCallArgs(f, '*(2,)')
1217 self.assertEqualCallArgs(f, '*[2]')
1218 self.assertEqualCallArgs(f, '*(2, 3)')
1219 self.assertEqualCallArgs(f, '*[2, 3]')
1220 self.assertEqualCallArgs(f, '**{"a":2}')
1221 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1222 self.assertEqualCallArgs(f, '2, **{"b":3}')
1223 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1224 # expand UserList / UserDict
1225 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1226 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1227 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1228 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1229 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1230
1231 def test_varargs(self):
1232 f = self.makeCallable('a, b=1, *c')
1233 self.assertEqualCallArgs(f, '2')
1234 self.assertEqualCallArgs(f, '2, 3')
1235 self.assertEqualCallArgs(f, '2, 3, 4')
1236 self.assertEqualCallArgs(f, '*(2,3,4)')
1237 self.assertEqualCallArgs(f, '2, *[3,4]')
1238 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1239
1240 def test_varkw(self):
1241 f = self.makeCallable('a, b=1, **c')
1242 self.assertEqualCallArgs(f, 'a=2')
1243 self.assertEqualCallArgs(f, '2, b=3, c=4')
1244 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1245 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1246 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1247 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1248 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1249 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1250 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1251
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001252 def test_varkw_only(self):
1253 # issue11256:
1254 f = self.makeCallable('**c')
1255 self.assertEqualCallArgs(f, '')
1256 self.assertEqualCallArgs(f, 'a=1')
1257 self.assertEqualCallArgs(f, 'a=1, b=2')
1258 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1259 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1260 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1261
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001262 def test_keyword_only(self):
1263 f = self.makeCallable('a=3, *, c, d=2')
1264 self.assertEqualCallArgs(f, 'c=3')
1265 self.assertEqualCallArgs(f, 'c=3, a=3')
1266 self.assertEqualCallArgs(f, 'a=2, c=4')
1267 self.assertEqualCallArgs(f, '4, c=4')
1268 self.assertEqualException(f, '')
1269 self.assertEqualException(f, '3')
1270 self.assertEqualException(f, 'a=3')
1271 self.assertEqualException(f, 'd=4')
1272
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001273 f = self.makeCallable('*, c, d=2')
1274 self.assertEqualCallArgs(f, 'c=3')
1275 self.assertEqualCallArgs(f, 'c=3, d=4')
1276 self.assertEqualCallArgs(f, 'd=4, c=3')
1277
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001278 def test_multiple_features(self):
1279 f = self.makeCallable('a, b=2, *f, **g')
1280 self.assertEqualCallArgs(f, '2, 3, 7')
1281 self.assertEqualCallArgs(f, '2, 3, x=8')
1282 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1283 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1284 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1285 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1286 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1287 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1288 '(4,[5,6])]), **collections.UserDict('
1289 'y=9, z=10)')
1290
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001291 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1292 self.assertEqualCallArgs(f, '2, 3, x=8')
1293 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1294 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1295 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1296 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1297 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1298 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1299 '(4,[5,6])]), q=0, **collections.UserDict('
1300 'y=9, z=10)')
1301
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001302 def test_errors(self):
1303 f0 = self.makeCallable('')
1304 f1 = self.makeCallable('a, b')
1305 f2 = self.makeCallable('a, b=1')
1306 # f0 takes no arguments
1307 self.assertEqualException(f0, '1')
1308 self.assertEqualException(f0, 'x=1')
1309 self.assertEqualException(f0, '1,x=1')
1310 # f1 takes exactly 2 arguments
1311 self.assertEqualException(f1, '')
1312 self.assertEqualException(f1, '1')
1313 self.assertEqualException(f1, 'a=2')
1314 self.assertEqualException(f1, 'b=3')
1315 # f2 takes at least 1 argument
1316 self.assertEqualException(f2, '')
1317 self.assertEqualException(f2, 'b=3')
1318 for f in f1, f2:
1319 # f1/f2 takes exactly/at most 2 arguments
1320 self.assertEqualException(f, '2, 3, 4')
1321 self.assertEqualException(f, '1, 2, 3, a=1')
1322 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001323 # XXX: success of this one depends on dict order
1324 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001325 # f got an unexpected keyword argument
1326 self.assertEqualException(f, 'c=2')
1327 self.assertEqualException(f, '2, c=3')
1328 self.assertEqualException(f, '2, 3, c=4')
1329 self.assertEqualException(f, '2, c=4, b=3')
1330 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1331 # f got multiple values for keyword argument
1332 self.assertEqualException(f, '1, a=2')
1333 self.assertEqualException(f, '1, **{"a":2}')
1334 self.assertEqualException(f, '1, 2, b=3')
1335 # XXX: Python inconsistency
1336 # - for functions and bound methods: unexpected keyword 'c'
1337 # - for unbound methods: multiple values for keyword 'a'
1338 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001339 # issue11256:
1340 f3 = self.makeCallable('**c')
1341 self.assertEqualException(f3, '1, 2')
1342 self.assertEqualException(f3, '1, 2, a=1, b=2')
1343 f4 = self.makeCallable('*, a, b=0')
1344 self.assertEqualException(f3, '1, 2')
1345 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001346
Yury Selivanov875df202014-03-27 18:23:03 -04001347 # issue #20816: getcallargs() fails to iterate over non-existent
1348 # kwonlydefaults and raises a wrong TypeError
1349 def f5(*, a): pass
1350 with self.assertRaisesRegex(TypeError,
1351 'missing 1 required keyword-only'):
1352 inspect.getcallargs(f5)
1353
1354
Yury Selivanovdccfa132014-03-27 18:42:52 -04001355 # issue20817:
1356 def f6(a, b, c):
1357 pass
1358 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1359 inspect.getcallargs(f6)
1360
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001361class TestGetcallargsMethods(TestGetcallargsFunctions):
1362
1363 def setUp(self):
1364 class Foo(object):
1365 pass
1366 self.cls = Foo
1367 self.inst = Foo()
1368
1369 def makeCallable(self, signature):
1370 assert 'self' not in signature
1371 mk = super(TestGetcallargsMethods, self).makeCallable
1372 self.cls.method = mk('self, ' + signature)
1373 return self.inst.method
1374
1375class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1376
1377 def makeCallable(self, signature):
1378 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1379 return self.cls.method
1380
1381 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1382 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1383 *self._getAssertEqualParams(func, call_params_string, locs))
1384
1385 def assertEqualException(self, func, call_params_string, locs=None):
1386 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1387 *self._getAssertEqualParams(func, call_params_string, locs))
1388
1389 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1390 assert 'inst' not in call_params_string
1391 locs = dict(locs or {}, inst=self.inst)
1392 return (func, 'inst,' + call_params_string, locs)
1393
Michael Foord95fc51d2010-11-20 15:07:30 +00001394
1395class TestGetattrStatic(unittest.TestCase):
1396
1397 def test_basic(self):
1398 class Thing(object):
1399 x = object()
1400
1401 thing = Thing()
1402 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1403 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1404 with self.assertRaises(AttributeError):
1405 inspect.getattr_static(thing, 'y')
1406
1407 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1408
1409 def test_inherited(self):
1410 class Thing(object):
1411 x = object()
1412 class OtherThing(Thing):
1413 pass
1414
1415 something = OtherThing()
1416 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1417
1418 def test_instance_attr(self):
1419 class Thing(object):
1420 x = 2
1421 def __init__(self, x):
1422 self.x = x
1423 thing = Thing(3)
1424 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1425 del thing.x
1426 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1427
1428 def test_property(self):
1429 class Thing(object):
1430 @property
1431 def x(self):
1432 raise AttributeError("I'm pretending not to exist")
1433 thing = Thing()
1434 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1435
Ezio Melotti75cbd732011-04-28 00:59:29 +03001436 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001437 class descriptor(object):
1438 def __get__(*_):
1439 raise AttributeError("I'm pretending not to exist")
1440 desc = descriptor()
1441 class Thing(object):
1442 x = desc
1443 thing = Thing()
1444 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1445
1446 def test_classAttribute(self):
1447 class Thing(object):
1448 x = object()
1449
1450 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1451
Ethan Furmane03ea372013-09-25 07:14:41 -07001452 def test_classVirtualAttribute(self):
1453 class Thing(object):
1454 @types.DynamicClassAttribute
1455 def x(self):
1456 return self._x
1457 _x = object()
1458
1459 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1460
Michael Foord95fc51d2010-11-20 15:07:30 +00001461 def test_inherited_classattribute(self):
1462 class Thing(object):
1463 x = object()
1464 class OtherThing(Thing):
1465 pass
1466
1467 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1468
1469 def test_slots(self):
1470 class Thing(object):
1471 y = 'bar'
1472 __slots__ = ['x']
1473 def __init__(self):
1474 self.x = 'foo'
1475 thing = Thing()
1476 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1477 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1478
1479 del thing.x
1480 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1481
1482 def test_metaclass(self):
1483 class meta(type):
1484 attr = 'foo'
1485 class Thing(object, metaclass=meta):
1486 pass
1487 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1488
1489 class sub(meta):
1490 pass
1491 class OtherThing(object, metaclass=sub):
1492 x = 3
1493 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1494
1495 class OtherOtherThing(OtherThing):
1496 pass
1497 # this test is odd, but it was added as it exposed a bug
1498 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1499
1500 def test_no_dict_no_slots(self):
1501 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1502 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1503
1504 def test_no_dict_no_slots_instance_member(self):
1505 # returns descriptor
1506 with open(__file__) as handle:
1507 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1508
1509 def test_inherited_slots(self):
1510 # returns descriptor
1511 class Thing(object):
1512 __slots__ = ['x']
1513 def __init__(self):
1514 self.x = 'foo'
1515
1516 class OtherThing(Thing):
1517 pass
1518 # it would be nice if this worked...
1519 # we get the descriptor instead of the instance attribute
1520 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1521
1522 def test_descriptor(self):
1523 class descriptor(object):
1524 def __get__(self, instance, owner):
1525 return 3
1526 class Foo(object):
1527 d = descriptor()
1528
1529 foo = Foo()
1530
1531 # for a non data descriptor we return the instance attribute
1532 foo.__dict__['d'] = 1
1533 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1534
1535 # if the descriptor is a data-desciptor we should return the
1536 # descriptor
1537 descriptor.__set__ = lambda s, i, v: None
1538 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1539
1540
1541 def test_metaclass_with_descriptor(self):
1542 class descriptor(object):
1543 def __get__(self, instance, owner):
1544 return 3
1545 class meta(type):
1546 d = descriptor()
1547 class Thing(object, metaclass=meta):
1548 pass
1549 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1550
1551
Michael Foordcc7ebb82010-11-20 16:20:16 +00001552 def test_class_as_property(self):
1553 class Base(object):
1554 foo = 3
1555
1556 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001557 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001558 @property
1559 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001560 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001561 return object
1562
Michael Foord35184ed2010-11-20 16:58:30 +00001563 instance = Something()
1564 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1565 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001566 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1567
Michael Foorde5162652010-11-20 16:40:44 +00001568 def test_mro_as_property(self):
1569 class Meta(type):
1570 @property
1571 def __mro__(self):
1572 return (object,)
1573
1574 class Base(object):
1575 foo = 3
1576
1577 class Something(Base, metaclass=Meta):
1578 pass
1579
1580 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1581 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1582
Michael Foorddcebe0f2011-03-15 19:20:44 -04001583 def test_dict_as_property(self):
1584 test = self
1585 test.called = False
1586
1587 class Foo(dict):
1588 a = 3
1589 @property
1590 def __dict__(self):
1591 test.called = True
1592 return {}
1593
1594 foo = Foo()
1595 foo.a = 4
1596 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1597 self.assertFalse(test.called)
1598
1599 def test_custom_object_dict(self):
1600 test = self
1601 test.called = False
1602
1603 class Custom(dict):
1604 def get(self, key, default=None):
1605 test.called = True
1606 super().get(key, default)
1607
1608 class Foo(object):
1609 a = 3
1610 foo = Foo()
1611 foo.__dict__ = Custom()
1612 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1613 self.assertFalse(test.called)
1614
1615 def test_metaclass_dict_as_property(self):
1616 class Meta(type):
1617 @property
1618 def __dict__(self):
1619 self.executed = True
1620
1621 class Thing(metaclass=Meta):
1622 executed = False
1623
1624 def __init__(self):
1625 self.spam = 42
1626
1627 instance = Thing()
1628 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1629 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001630
Michael Foorda51623b2011-12-18 22:01:40 +00001631 def test_module(self):
1632 sentinel = object()
1633 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1634 sentinel)
1635
Michael Foord3ba95f82011-12-22 01:13:37 +00001636 def test_metaclass_with_metaclass_with_dict_as_property(self):
1637 class MetaMeta(type):
1638 @property
1639 def __dict__(self):
1640 self.executed = True
1641 return dict(spam=42)
1642
1643 class Meta(type, metaclass=MetaMeta):
1644 executed = False
1645
1646 class Thing(metaclass=Meta):
1647 pass
1648
1649 with self.assertRaises(AttributeError):
1650 inspect.getattr_static(Thing, "spam")
1651 self.assertFalse(Thing.executed)
1652
Nick Coghlane0f04652010-11-21 03:44:04 +00001653class TestGetGeneratorState(unittest.TestCase):
1654
1655 def setUp(self):
1656 def number_generator():
1657 for number in range(5):
1658 yield number
1659 self.generator = number_generator()
1660
1661 def _generatorstate(self):
1662 return inspect.getgeneratorstate(self.generator)
1663
1664 def test_created(self):
1665 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1666
1667 def test_suspended(self):
1668 next(self.generator)
1669 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1670
1671 def test_closed_after_exhaustion(self):
1672 for i in self.generator:
1673 pass
1674 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1675
1676 def test_closed_after_immediate_exception(self):
1677 with self.assertRaises(RuntimeError):
1678 self.generator.throw(RuntimeError)
1679 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1680
1681 def test_running(self):
1682 # As mentioned on issue #10220, checking for the RUNNING state only
1683 # makes sense inside the generator itself.
1684 # The following generator checks for this by using the closure's
1685 # reference to self and the generator state checking helper method
1686 def running_check_generator():
1687 for number in range(5):
1688 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1689 yield number
1690 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1691 self.generator = running_check_generator()
1692 # Running up to the first yield
1693 next(self.generator)
1694 # Running after the first yield
1695 next(self.generator)
1696
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001697 def test_easy_debugging(self):
1698 # repr() and str() of a generator state should contain the state name
1699 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1700 for name in names:
1701 state = getattr(inspect, name)
1702 self.assertIn(name, repr(state))
1703 self.assertIn(name, str(state))
1704
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001705 def test_getgeneratorlocals(self):
1706 def each(lst, a=None):
1707 b=(1, 2, 3)
1708 for v in lst:
1709 if v == 3:
1710 c = 12
1711 yield v
1712
1713 numbers = each([1, 2, 3])
1714 self.assertEqual(inspect.getgeneratorlocals(numbers),
1715 {'a': None, 'lst': [1, 2, 3]})
1716 next(numbers)
1717 self.assertEqual(inspect.getgeneratorlocals(numbers),
1718 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1719 'b': (1, 2, 3)})
1720 next(numbers)
1721 self.assertEqual(inspect.getgeneratorlocals(numbers),
1722 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1723 'b': (1, 2, 3)})
1724 next(numbers)
1725 self.assertEqual(inspect.getgeneratorlocals(numbers),
1726 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1727 'b': (1, 2, 3), 'c': 12})
1728 try:
1729 next(numbers)
1730 except StopIteration:
1731 pass
1732 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1733
1734 def test_getgeneratorlocals_empty(self):
1735 def yield_one():
1736 yield 1
1737 one = yield_one()
1738 self.assertEqual(inspect.getgeneratorlocals(one), {})
1739 try:
1740 next(one)
1741 except StopIteration:
1742 pass
1743 self.assertEqual(inspect.getgeneratorlocals(one), {})
1744
1745 def test_getgeneratorlocals_error(self):
1746 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1747 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1748 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1749 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1750
Nick Coghlane0f04652010-11-21 03:44:04 +00001751
Yury Selivanov5376ba92015-06-22 12:19:30 -04001752class TestGetCoroutineState(unittest.TestCase):
1753
1754 def setUp(self):
1755 @types.coroutine
1756 def number_coroutine():
1757 for number in range(5):
1758 yield number
1759 async def coroutine():
1760 await number_coroutine()
1761 self.coroutine = coroutine()
1762
1763 def tearDown(self):
1764 self.coroutine.close()
1765
1766 def _coroutinestate(self):
1767 return inspect.getcoroutinestate(self.coroutine)
1768
1769 def test_created(self):
1770 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1771
1772 def test_suspended(self):
1773 self.coroutine.send(None)
1774 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1775
1776 def test_closed_after_exhaustion(self):
1777 while True:
1778 try:
1779 self.coroutine.send(None)
1780 except StopIteration:
1781 break
1782
1783 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1784
1785 def test_closed_after_immediate_exception(self):
1786 with self.assertRaises(RuntimeError):
1787 self.coroutine.throw(RuntimeError)
1788 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1789
1790 def test_easy_debugging(self):
1791 # repr() and str() of a coroutine state should contain the state name
1792 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1793 for name in names:
1794 state = getattr(inspect, name)
1795 self.assertIn(name, repr(state))
1796 self.assertIn(name, str(state))
1797
1798 def test_getcoroutinelocals(self):
1799 @types.coroutine
1800 def gencoro():
1801 yield
1802
1803 gencoro = gencoro()
1804 async def func(a=None):
1805 b = 'spam'
1806 await gencoro
1807
1808 coro = func()
1809 self.assertEqual(inspect.getcoroutinelocals(coro),
1810 {'a': None, 'gencoro': gencoro})
1811 coro.send(None)
1812 self.assertEqual(inspect.getcoroutinelocals(coro),
1813 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
1814
1815
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001816class MySignature(inspect.Signature):
1817 # Top-level to make it picklable;
1818 # used in test_signature_object_pickle
1819 pass
1820
1821class MyParameter(inspect.Parameter):
1822 # Top-level to make it picklable;
1823 # used in test_signature_object_pickle
1824 pass
1825
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001826
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001827
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001828class TestSignatureObject(unittest.TestCase):
1829 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04001830 def signature(func, **kw):
1831 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001832 return (tuple((param.name,
1833 (... if param.default is param.empty else param.default),
1834 (... if param.annotation is param.empty
1835 else param.annotation),
1836 str(param.kind).lower())
1837 for param in sig.parameters.values()),
1838 (... if sig.return_annotation is sig.empty
1839 else sig.return_annotation))
1840
1841 def test_signature_object(self):
1842 S = inspect.Signature
1843 P = inspect.Parameter
1844
1845 self.assertEqual(str(S()), '()')
1846
Yury Selivanov07a9e452014-01-29 10:58:16 -05001847 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001848 pass
1849 sig = inspect.signature(test)
1850 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001851 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001852 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001853 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001854 args = sig.parameters['args']
1855 ko = sig.parameters['ko']
1856 kwargs = sig.parameters['kwargs']
1857
1858 S((po, pk, args, ko, kwargs))
1859
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001860 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001861 S((pk, po, args, ko, kwargs))
1862
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001863 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001864 S((po, args, pk, ko, kwargs))
1865
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001866 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001867 S((args, po, pk, ko, kwargs))
1868
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001869 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001870 S((po, pk, args, kwargs, ko))
1871
1872 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001873 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001874 S((po, pk, args, kwargs2, ko))
1875
Yury Selivanov07a9e452014-01-29 10:58:16 -05001876 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1877 S((pod, po))
1878
1879 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1880 S((po, pkd, pk))
1881
1882 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1883 S((pkd, pk))
1884
Yury Selivanov374375d2014-03-27 12:41:53 -04001885 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04001886 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04001887
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001888 def test_signature_object_pickle(self):
1889 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1890 foo_partial = functools.partial(foo, a=1)
1891
1892 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001893
1894 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1895 with self.subTest(pickle_ver=ver, subclass=False):
1896 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1897 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001898
1899 # Test that basic sub-classing works
1900 sig = inspect.signature(foo)
1901 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1902 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1903 mysig = MySignature().replace(parameters=myparams.values(),
1904 return_annotation=sig.return_annotation)
1905 self.assertTrue(isinstance(mysig, MySignature))
1906 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1907
1908 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1909 with self.subTest(pickle_ver=ver, subclass=True):
1910 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1911 self.assertEqual(mysig, sig_pickled)
1912 self.assertTrue(isinstance(sig_pickled, MySignature))
1913 self.assertTrue(isinstance(sig_pickled.parameters['z'],
1914 MyParameter))
1915
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001916 def test_signature_immutability(self):
1917 def test(a):
1918 pass
1919 sig = inspect.signature(test)
1920
1921 with self.assertRaises(AttributeError):
1922 sig.foo = 'bar'
1923
1924 with self.assertRaises(TypeError):
1925 sig.parameters['a'] = None
1926
1927 def test_signature_on_noarg(self):
1928 def test():
1929 pass
1930 self.assertEqual(self.signature(test), ((), ...))
1931
1932 def test_signature_on_wargs(self):
1933 def test(a, b:'foo') -> 123:
1934 pass
1935 self.assertEqual(self.signature(test),
1936 ((('a', ..., ..., "positional_or_keyword"),
1937 ('b', ..., 'foo', "positional_or_keyword")),
1938 123))
1939
1940 def test_signature_on_wkwonly(self):
1941 def test(*, a:float, b:str) -> int:
1942 pass
1943 self.assertEqual(self.signature(test),
1944 ((('a', ..., float, "keyword_only"),
1945 ('b', ..., str, "keyword_only")),
1946 int))
1947
1948 def test_signature_on_complex_args(self):
1949 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1950 pass
1951 self.assertEqual(self.signature(test),
1952 ((('a', ..., ..., "positional_or_keyword"),
1953 ('b', 10, 'foo', "positional_or_keyword"),
1954 ('args', ..., 'bar', "var_positional"),
1955 ('spam', ..., 'baz', "keyword_only"),
1956 ('ham', 123, ..., "keyword_only"),
1957 ('kwargs', ..., int, "var_keyword")),
1958 ...))
1959
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001960 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001961 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1962 "Signature information for builtins requires docstrings")
1963 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001964 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001965
Larry Hastings5c661892014-01-24 06:17:25 -08001966 def test_unbound_method(o):
1967 """Use this to test unbound methods (things that should have a self)"""
1968 signature = inspect.signature(o)
1969 self.assertTrue(isinstance(signature, inspect.Signature))
1970 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1971 return signature
1972
1973 def test_callable(o):
1974 """Use this to test bound methods or normal callables (things that don't expect self)"""
1975 signature = inspect.signature(o)
1976 self.assertTrue(isinstance(signature, inspect.Signature))
1977 if signature.parameters:
1978 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1979 return signature
1980
1981 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001982 def p(name): return signature.parameters[name].default
1983 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001984 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001985 self.assertEqual(p('d'), 3.14)
1986 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001987 self.assertEqual(p('n'), None)
1988 self.assertEqual(p('t'), True)
1989 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001990 self.assertEqual(p('local'), 3)
1991 self.assertEqual(p('sys'), sys.maxsize)
1992 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001993
Larry Hastings5c661892014-01-24 06:17:25 -08001994 test_callable(object)
1995
1996 # normal method
1997 # (PyMethodDescr_Type, "method_descriptor")
1998 test_unbound_method(_pickle.Pickler.dump)
1999 d = _pickle.Pickler(io.StringIO())
2000 test_callable(d.dump)
2001
2002 # static method
2003 test_callable(str.maketrans)
2004 test_callable('abc'.maketrans)
2005
2006 # class method
2007 test_callable(dict.fromkeys)
2008 test_callable({}.fromkeys)
2009
2010 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2011 test_unbound_method(type.__call__)
2012 test_unbound_method(int.__add__)
2013 test_callable((3).__add__)
2014
2015 # _PyMethodWrapper_Type
2016 # support for 'method-wrapper'
2017 test_callable(min.__call__)
2018
Larry Hastings2623c8c2014-02-08 22:15:29 -08002019 # This doesn't work now.
2020 # (We don't have a valid signature for "type" in 3.4)
2021 with self.assertRaisesRegex(ValueError, "no signature found"):
2022 class ThisWorksNow:
2023 __call__ = type
2024 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002025
Yury Selivanov056e2652014-03-02 12:25:27 -05002026 # Regression test for issue #20786
2027 test_unbound_method(dict.__delitem__)
2028 test_unbound_method(property.__delete__)
2029
Zachary Ware8ef887c2015-04-13 18:22:35 -05002030 # Regression test for issue #20586
2031 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2032
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002033 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002034 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2035 "Signature information for builtins requires docstrings")
2036 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002037 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002038 func = _testcapi.docstring_with_signature_with_defaults
2039
2040 def decorator(func):
2041 @functools.wraps(func)
2042 def wrapper(*args, **kwargs) -> int:
2043 return func(*args, **kwargs)
2044 return wrapper
2045
2046 decorated_func = decorator(func)
2047
2048 self.assertEqual(inspect.signature(func),
2049 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002050
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002051 def wrapper_like(*args, **kwargs) -> int: pass
2052 self.assertEqual(inspect.signature(decorated_func,
2053 follow_wrapped=False),
2054 inspect.signature(wrapper_like))
2055
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002056 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002057 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002058 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002059 with self.assertRaisesRegex(ValueError,
2060 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002061 inspect.signature(_testcapi.docstring_no_signature)
2062
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002063 with self.assertRaisesRegex(ValueError,
2064 'no signature found for builtin'):
2065 inspect.signature(str)
2066
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002067 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002068 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002069 inspect.signature(42)
2070
Yury Selivanov63da7c72014-01-31 14:48:37 -05002071 def test_signature_from_functionlike_object(self):
2072 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2073 pass
2074
2075 class funclike:
2076 # Has to be callable, and have correct
2077 # __code__, __annotations__, __defaults__, __name__,
2078 # and __kwdefaults__ attributes
2079
2080 def __init__(self, func):
2081 self.__name__ = func.__name__
2082 self.__code__ = func.__code__
2083 self.__annotations__ = func.__annotations__
2084 self.__defaults__ = func.__defaults__
2085 self.__kwdefaults__ = func.__kwdefaults__
2086 self.func = func
2087
2088 def __call__(self, *args, **kwargs):
2089 return self.func(*args, **kwargs)
2090
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002091 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002092
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002093 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002094 self.assertEqual(sig_funclike, sig_func)
2095
2096 sig_funclike = inspect.signature(funclike(func))
2097 self.assertEqual(sig_funclike, sig_func)
2098
2099 # If object is not a duck type of function, then
2100 # signature will try to get a signature for its '__call__'
2101 # method
2102 fl = funclike(func)
2103 del fl.__defaults__
2104 self.assertEqual(self.signature(fl),
2105 ((('args', ..., ..., "var_positional"),
2106 ('kwargs', ..., ..., "var_keyword")),
2107 ...))
2108
Yury Selivanova773de02014-02-21 18:30:53 -05002109 # Test with cython-like builtins:
2110 _orig_isdesc = inspect.ismethoddescriptor
2111 def _isdesc(obj):
2112 if hasattr(obj, '_builtinmock'):
2113 return True
2114 return _orig_isdesc(obj)
2115
2116 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2117 builtin_func = funclike(func)
2118 # Make sure that our mock setup is working
2119 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2120 builtin_func._builtinmock = True
2121 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2122 self.assertEqual(inspect.signature(builtin_func), sig_func)
2123
Yury Selivanov63da7c72014-01-31 14:48:37 -05002124 def test_signature_functionlike_class(self):
2125 # We only want to duck type function-like objects,
2126 # not classes.
2127
2128 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2129 pass
2130
2131 class funclike:
2132 def __init__(self, marker):
2133 pass
2134
2135 __name__ = func.__name__
2136 __code__ = func.__code__
2137 __annotations__ = func.__annotations__
2138 __defaults__ = func.__defaults__
2139 __kwdefaults__ = func.__kwdefaults__
2140
Yury Selivanov63da7c72014-01-31 14:48:37 -05002141 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2142
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002143 def test_signature_on_method(self):
2144 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002145 def __init__(*args):
2146 pass
2147 def m1(self, arg1, arg2=1) -> int:
2148 pass
2149 def m2(*args):
2150 pass
2151 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002152 pass
2153
Yury Selivanov62560fb2014-01-28 12:26:24 -05002154 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002155 ((('arg1', ..., ..., "positional_or_keyword"),
2156 ('arg2', 1, ..., "positional_or_keyword")),
2157 int))
2158
Yury Selivanov62560fb2014-01-28 12:26:24 -05002159 self.assertEqual(self.signature(Test().m2),
2160 ((('args', ..., ..., "var_positional"),),
2161 ...))
2162
2163 self.assertEqual(self.signature(Test),
2164 ((('args', ..., ..., "var_positional"),),
2165 ...))
2166
2167 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2168 self.signature(Test())
2169
Yury Selivanov46c759d2015-05-27 21:56:53 -04002170 def test_signature_wrapped_bound_method(self):
2171 # Issue 24298
2172 class Test:
2173 def m1(self, arg1, arg2=1) -> int:
2174 pass
2175 @functools.wraps(Test().m1)
2176 def m1d(*args, **kwargs):
2177 pass
2178 self.assertEqual(self.signature(m1d),
2179 ((('arg1', ..., ..., "positional_or_keyword"),
2180 ('arg2', 1, ..., "positional_or_keyword")),
2181 int))
2182
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002183 def test_signature_on_classmethod(self):
2184 class Test:
2185 @classmethod
2186 def foo(cls, arg1, *, arg2=1):
2187 pass
2188
2189 meth = Test().foo
2190 self.assertEqual(self.signature(meth),
2191 ((('arg1', ..., ..., "positional_or_keyword"),
2192 ('arg2', 1, ..., "keyword_only")),
2193 ...))
2194
2195 meth = Test.foo
2196 self.assertEqual(self.signature(meth),
2197 ((('arg1', ..., ..., "positional_or_keyword"),
2198 ('arg2', 1, ..., "keyword_only")),
2199 ...))
2200
2201 def test_signature_on_staticmethod(self):
2202 class Test:
2203 @staticmethod
2204 def foo(cls, *, arg):
2205 pass
2206
2207 meth = Test().foo
2208 self.assertEqual(self.signature(meth),
2209 ((('cls', ..., ..., "positional_or_keyword"),
2210 ('arg', ..., ..., "keyword_only")),
2211 ...))
2212
2213 meth = Test.foo
2214 self.assertEqual(self.signature(meth),
2215 ((('cls', ..., ..., "positional_or_keyword"),
2216 ('arg', ..., ..., "keyword_only")),
2217 ...))
2218
2219 def test_signature_on_partial(self):
2220 from functools import partial
2221
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002222 Parameter = inspect.Parameter
2223
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002224 def test():
2225 pass
2226
2227 self.assertEqual(self.signature(partial(test)), ((), ...))
2228
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002229 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002230 inspect.signature(partial(test, 1))
2231
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002232 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002233 inspect.signature(partial(test, a=1))
2234
2235 def test(a, b, *, c, d):
2236 pass
2237
2238 self.assertEqual(self.signature(partial(test)),
2239 ((('a', ..., ..., "positional_or_keyword"),
2240 ('b', ..., ..., "positional_or_keyword"),
2241 ('c', ..., ..., "keyword_only"),
2242 ('d', ..., ..., "keyword_only")),
2243 ...))
2244
2245 self.assertEqual(self.signature(partial(test, 1)),
2246 ((('b', ..., ..., "positional_or_keyword"),
2247 ('c', ..., ..., "keyword_only"),
2248 ('d', ..., ..., "keyword_only")),
2249 ...))
2250
2251 self.assertEqual(self.signature(partial(test, 1, c=2)),
2252 ((('b', ..., ..., "positional_or_keyword"),
2253 ('c', 2, ..., "keyword_only"),
2254 ('d', ..., ..., "keyword_only")),
2255 ...))
2256
2257 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2258 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002259 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002260 ('c', 2, ..., "keyword_only"),
2261 ('d', ..., ..., "keyword_only")),
2262 ...))
2263
2264 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002265 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002266 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002267 ('d', ..., ..., "keyword_only")),
2268 ...))
2269
2270 self.assertEqual(self.signature(partial(test, a=1)),
2271 ((('a', 1, ..., "keyword_only"),
2272 ('b', ..., ..., "keyword_only"),
2273 ('c', ..., ..., "keyword_only"),
2274 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002275 ...))
2276
2277 def test(a, *args, b, **kwargs):
2278 pass
2279
2280 self.assertEqual(self.signature(partial(test, 1)),
2281 ((('args', ..., ..., "var_positional"),
2282 ('b', ..., ..., "keyword_only"),
2283 ('kwargs', ..., ..., "var_keyword")),
2284 ...))
2285
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002286 self.assertEqual(self.signature(partial(test, a=1)),
2287 ((('a', 1, ..., "keyword_only"),
2288 ('b', ..., ..., "keyword_only"),
2289 ('kwargs', ..., ..., "var_keyword")),
2290 ...))
2291
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002292 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2293 ((('args', ..., ..., "var_positional"),
2294 ('b', ..., ..., "keyword_only"),
2295 ('kwargs', ..., ..., "var_keyword")),
2296 ...))
2297
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002298 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2299 ((('args', ..., ..., "var_positional"),
2300 ('b', ..., ..., "keyword_only"),
2301 ('kwargs', ..., ..., "var_keyword")),
2302 ...))
2303
2304 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2305 ((('args', ..., ..., "var_positional"),
2306 ('b', 0, ..., "keyword_only"),
2307 ('kwargs', ..., ..., "var_keyword")),
2308 ...))
2309
2310 self.assertEqual(self.signature(partial(test, b=0)),
2311 ((('a', ..., ..., "positional_or_keyword"),
2312 ('args', ..., ..., "var_positional"),
2313 ('b', 0, ..., "keyword_only"),
2314 ('kwargs', ..., ..., "var_keyword")),
2315 ...))
2316
2317 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2318 ((('a', ..., ..., "positional_or_keyword"),
2319 ('args', ..., ..., "var_positional"),
2320 ('b', 0, ..., "keyword_only"),
2321 ('kwargs', ..., ..., "var_keyword")),
2322 ...))
2323
2324 def test(a, b, c:int) -> 42:
2325 pass
2326
2327 sig = test.__signature__ = inspect.signature(test)
2328
2329 self.assertEqual(self.signature(partial(partial(test, 1))),
2330 ((('b', ..., ..., "positional_or_keyword"),
2331 ('c', ..., int, "positional_or_keyword")),
2332 42))
2333
2334 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2335 ((('c', ..., int, "positional_or_keyword"),),
2336 42))
2337
2338 psig = inspect.signature(partial(partial(test, 1), 2))
2339
2340 def foo(a):
2341 return a
2342 _foo = partial(partial(foo, a=10), a=20)
2343 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002344 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002345 ...))
2346 # check that we don't have any side-effects in signature(),
2347 # and the partial object is still functioning
2348 self.assertEqual(_foo(), 20)
2349
2350 def foo(a, b, c):
2351 return a, b, c
2352 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002353
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002354 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002355 ((('b', 30, ..., "keyword_only"),
2356 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002357 ...))
2358 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002359
2360 def foo(a, b, c, *, d):
2361 return a, b, c, d
2362 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2363 self.assertEqual(self.signature(_foo),
2364 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002365 ('b', 10, ..., "keyword_only"),
2366 ('c', 20, ..., "keyword_only"),
2367 ('d', 30, ..., "keyword_only"),
2368 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002369 ...))
2370 ba = inspect.signature(_foo).bind(a=200, b=11)
2371 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2372
2373 def foo(a=1, b=2, c=3):
2374 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002375 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2376
2377 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002378 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002379
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002380 ba = inspect.signature(_foo).bind(11, 12)
2381 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002382
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002383 ba = inspect.signature(_foo).bind(11, b=12)
2384 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002385
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002386 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002387 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2388
2389 _foo = partial(_foo, b=10, c=20)
2390 ba = inspect.signature(_foo).bind(12)
2391 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2392
2393
2394 def foo(a, b, c, d, **kwargs):
2395 pass
2396 sig = inspect.signature(foo)
2397 params = sig.parameters.copy()
2398 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2399 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2400 foo.__signature__ = inspect.Signature(params.values())
2401 sig = inspect.signature(foo)
2402 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2403
2404 self.assertEqual(self.signature(partial(foo, 1)),
2405 ((('b', ..., ..., 'positional_only'),
2406 ('c', ..., ..., 'positional_or_keyword'),
2407 ('d', ..., ..., 'positional_or_keyword'),
2408 ('kwargs', ..., ..., 'var_keyword')),
2409 ...))
2410
2411 self.assertEqual(self.signature(partial(foo, 1, 2)),
2412 ((('c', ..., ..., 'positional_or_keyword'),
2413 ('d', ..., ..., 'positional_or_keyword'),
2414 ('kwargs', ..., ..., 'var_keyword')),
2415 ...))
2416
2417 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2418 ((('d', ..., ..., 'positional_or_keyword'),
2419 ('kwargs', ..., ..., 'var_keyword')),
2420 ...))
2421
2422 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2423 ((('c', 3, ..., 'keyword_only'),
2424 ('d', ..., ..., 'keyword_only'),
2425 ('kwargs', ..., ..., 'var_keyword')),
2426 ...))
2427
2428 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2429 ((('b', ..., ..., 'positional_only'),
2430 ('c', 3, ..., 'keyword_only'),
2431 ('d', ..., ..., 'keyword_only'),
2432 ('kwargs', ..., ..., 'var_keyword')),
2433 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002434
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002435 def test_signature_on_partialmethod(self):
2436 from functools import partialmethod
2437
2438 class Spam:
2439 def test():
2440 pass
2441 ham = partialmethod(test)
2442
2443 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2444 inspect.signature(Spam.ham)
2445
2446 class Spam:
2447 def test(it, a, *, c) -> 'spam':
2448 pass
2449 ham = partialmethod(test, c=1)
2450
2451 self.assertEqual(self.signature(Spam.ham),
2452 ((('it', ..., ..., 'positional_or_keyword'),
2453 ('a', ..., ..., 'positional_or_keyword'),
2454 ('c', 1, ..., 'keyword_only')),
2455 'spam'))
2456
2457 self.assertEqual(self.signature(Spam().ham),
2458 ((('a', ..., ..., 'positional_or_keyword'),
2459 ('c', 1, ..., 'keyword_only')),
2460 'spam'))
2461
Yury Selivanov0486f812014-01-29 12:18:59 -05002462 def test_signature_on_fake_partialmethod(self):
2463 def foo(a): pass
2464 foo._partialmethod = 'spam'
2465 self.assertEqual(str(inspect.signature(foo)), '(a)')
2466
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002467 def test_signature_on_decorated(self):
2468 import functools
2469
2470 def decorator(func):
2471 @functools.wraps(func)
2472 def wrapper(*args, **kwargs) -> int:
2473 return func(*args, **kwargs)
2474 return wrapper
2475
2476 class Foo:
2477 @decorator
2478 def bar(self, a, b):
2479 pass
2480
2481 self.assertEqual(self.signature(Foo.bar),
2482 ((('self', ..., ..., "positional_or_keyword"),
2483 ('a', ..., ..., "positional_or_keyword"),
2484 ('b', ..., ..., "positional_or_keyword")),
2485 ...))
2486
2487 self.assertEqual(self.signature(Foo().bar),
2488 ((('a', ..., ..., "positional_or_keyword"),
2489 ('b', ..., ..., "positional_or_keyword")),
2490 ...))
2491
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002492 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2493 ((('args', ..., ..., "var_positional"),
2494 ('kwargs', ..., ..., "var_keyword")),
2495 ...)) # functools.wraps will copy __annotations__
2496 # from "func" to "wrapper", hence no
2497 # return_annotation
2498
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002499 # Test that we handle method wrappers correctly
2500 def decorator(func):
2501 @functools.wraps(func)
2502 def wrapper(*args, **kwargs) -> int:
2503 return func(42, *args, **kwargs)
2504 sig = inspect.signature(func)
2505 new_params = tuple(sig.parameters.values())[1:]
2506 wrapper.__signature__ = sig.replace(parameters=new_params)
2507 return wrapper
2508
2509 class Foo:
2510 @decorator
2511 def __call__(self, a, b):
2512 pass
2513
2514 self.assertEqual(self.signature(Foo.__call__),
2515 ((('a', ..., ..., "positional_or_keyword"),
2516 ('b', ..., ..., "positional_or_keyword")),
2517 ...))
2518
2519 self.assertEqual(self.signature(Foo().__call__),
2520 ((('b', ..., ..., "positional_or_keyword"),),
2521 ...))
2522
Nick Coghlane8c45d62013-07-28 20:00:01 +10002523 # Test we handle __signature__ partway down the wrapper stack
2524 def wrapped_foo_call():
2525 pass
2526 wrapped_foo_call.__wrapped__ = Foo.__call__
2527
2528 self.assertEqual(self.signature(wrapped_foo_call),
2529 ((('a', ..., ..., "positional_or_keyword"),
2530 ('b', ..., ..., "positional_or_keyword")),
2531 ...))
2532
2533
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002534 def test_signature_on_class(self):
2535 class C:
2536 def __init__(self, a):
2537 pass
2538
2539 self.assertEqual(self.signature(C),
2540 ((('a', ..., ..., "positional_or_keyword"),),
2541 ...))
2542
2543 class CM(type):
2544 def __call__(cls, a):
2545 pass
2546 class C(metaclass=CM):
2547 def __init__(self, b):
2548 pass
2549
2550 self.assertEqual(self.signature(C),
2551 ((('a', ..., ..., "positional_or_keyword"),),
2552 ...))
2553
2554 class CM(type):
2555 def __new__(mcls, name, bases, dct, *, foo=1):
2556 return super().__new__(mcls, name, bases, dct)
2557 class C(metaclass=CM):
2558 def __init__(self, b):
2559 pass
2560
2561 self.assertEqual(self.signature(C),
2562 ((('b', ..., ..., "positional_or_keyword"),),
2563 ...))
2564
2565 self.assertEqual(self.signature(CM),
2566 ((('name', ..., ..., "positional_or_keyword"),
2567 ('bases', ..., ..., "positional_or_keyword"),
2568 ('dct', ..., ..., "positional_or_keyword"),
2569 ('foo', 1, ..., "keyword_only")),
2570 ...))
2571
2572 class CMM(type):
2573 def __new__(mcls, name, bases, dct, *, foo=1):
2574 return super().__new__(mcls, name, bases, dct)
2575 def __call__(cls, nm, bs, dt):
2576 return type(nm, bs, dt)
2577 class CM(type, metaclass=CMM):
2578 def __new__(mcls, name, bases, dct, *, bar=2):
2579 return super().__new__(mcls, name, bases, dct)
2580 class C(metaclass=CM):
2581 def __init__(self, b):
2582 pass
2583
2584 self.assertEqual(self.signature(CMM),
2585 ((('name', ..., ..., "positional_or_keyword"),
2586 ('bases', ..., ..., "positional_or_keyword"),
2587 ('dct', ..., ..., "positional_or_keyword"),
2588 ('foo', 1, ..., "keyword_only")),
2589 ...))
2590
2591 self.assertEqual(self.signature(CM),
2592 ((('nm', ..., ..., "positional_or_keyword"),
2593 ('bs', ..., ..., "positional_or_keyword"),
2594 ('dt', ..., ..., "positional_or_keyword")),
2595 ...))
2596
2597 self.assertEqual(self.signature(C),
2598 ((('b', ..., ..., "positional_or_keyword"),),
2599 ...))
2600
2601 class CM(type):
2602 def __init__(cls, name, bases, dct, *, bar=2):
2603 return super().__init__(name, bases, dct)
2604 class C(metaclass=CM):
2605 def __init__(self, b):
2606 pass
2607
2608 self.assertEqual(self.signature(CM),
2609 ((('name', ..., ..., "positional_or_keyword"),
2610 ('bases', ..., ..., "positional_or_keyword"),
2611 ('dct', ..., ..., "positional_or_keyword"),
2612 ('bar', 2, ..., "keyword_only")),
2613 ...))
2614
Yury Selivanov145dff82014-02-01 13:49:29 -05002615 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2616 "Signature information for builtins requires docstrings")
2617 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002618 # Test classes without user-defined __init__ or __new__
2619 class C: pass
2620 self.assertEqual(str(inspect.signature(C)), '()')
2621 class D(C): pass
2622 self.assertEqual(str(inspect.signature(D)), '()')
2623
2624 # Test meta-classes without user-defined __init__ or __new__
2625 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002626 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002627 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2628 self.assertEqual(inspect.signature(C), None)
2629 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2630 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002631
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002632 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2633 "Signature information for builtins requires docstrings")
2634 def test_signature_on_builtin_class(self):
2635 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2636 '(file, protocol=None, fix_imports=True)')
2637
2638 class P(_pickle.Pickler): pass
2639 class EmptyTrait: pass
2640 class P2(EmptyTrait, P): pass
2641 self.assertEqual(str(inspect.signature(P)),
2642 '(file, protocol=None, fix_imports=True)')
2643 self.assertEqual(str(inspect.signature(P2)),
2644 '(file, protocol=None, fix_imports=True)')
2645
2646 class P3(P2):
2647 def __init__(self, spam):
2648 pass
2649 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2650
2651 class MetaP(type):
2652 def __call__(cls, foo, bar):
2653 pass
2654 class P4(P2, metaclass=MetaP):
2655 pass
2656 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2657
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002658 def test_signature_on_callable_objects(self):
2659 class Foo:
2660 def __call__(self, a):
2661 pass
2662
2663 self.assertEqual(self.signature(Foo()),
2664 ((('a', ..., ..., "positional_or_keyword"),),
2665 ...))
2666
2667 class Spam:
2668 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002669 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002670 inspect.signature(Spam())
2671
2672 class Bar(Spam, Foo):
2673 pass
2674
2675 self.assertEqual(self.signature(Bar()),
2676 ((('a', ..., ..., "positional_or_keyword"),),
2677 ...))
2678
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002679 class Wrapped:
2680 pass
2681 Wrapped.__wrapped__ = lambda a: None
2682 self.assertEqual(self.signature(Wrapped),
2683 ((('a', ..., ..., "positional_or_keyword"),),
2684 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002685 # wrapper loop:
2686 Wrapped.__wrapped__ = Wrapped
2687 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2688 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002689
2690 def test_signature_on_lambdas(self):
2691 self.assertEqual(self.signature((lambda a=10: a)),
2692 ((('a', 10, ..., "positional_or_keyword"),),
2693 ...))
2694
2695 def test_signature_equality(self):
2696 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002697 self.assertFalse(inspect.signature(foo) == 42)
2698 self.assertTrue(inspect.signature(foo) != 42)
2699 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2700 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002701
2702 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002703 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2704 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002705 self.assertEqual(
2706 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002707
2708 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002709 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2710 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002711 self.assertNotEqual(
2712 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002713
2714 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002715 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2716 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002717 self.assertNotEqual(
2718 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002719
2720 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002721 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2722 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002723 self.assertNotEqual(
2724 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002725
2726 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002727 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2728 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002729 self.assertNotEqual(
2730 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002731
2732 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002733 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2734 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002735 self.assertNotEqual(
2736 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002737 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002738 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
2739 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002740 self.assertNotEqual(
2741 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002742
2743 def foo(*, a, b, c): pass
2744 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002745 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2746 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002747 self.assertEqual(
2748 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002749
2750 def foo(*, a=1, b, c): pass
2751 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002752 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2753 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002754 self.assertEqual(
2755 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002756
2757 def foo(pos, *, a=1, b, c): pass
2758 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002759 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2760 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002761 self.assertEqual(
2762 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002763
2764 def foo(pos, *, a, b, c): pass
2765 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002766 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2767 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002768 self.assertNotEqual(
2769 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002770
2771 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2772 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002773 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2774 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002775 self.assertEqual(
2776 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002777
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002778 def test_signature_hashable(self):
2779 S = inspect.Signature
2780 P = inspect.Parameter
2781
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002782 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002783 foo_sig = inspect.signature(foo)
2784
2785 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2786
2787 self.assertEqual(hash(foo_sig), hash(manual_sig))
2788 self.assertNotEqual(hash(foo_sig),
2789 hash(manual_sig.replace(return_annotation='spam')))
2790
2791 def bar(a) -> 1: pass
2792 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2793
2794 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002795 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002796 hash(inspect.signature(foo))
2797
2798 def foo(a) -> {}: pass
2799 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2800 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002801
2802 def test_signature_str(self):
2803 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2804 pass
2805 self.assertEqual(str(inspect.signature(foo)),
2806 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2807
2808 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2809 pass
2810 self.assertEqual(str(inspect.signature(foo)),
2811 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2812
2813 def foo():
2814 pass
2815 self.assertEqual(str(inspect.signature(foo)), '()')
2816
2817 def test_signature_str_positional_only(self):
2818 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002819 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002820
2821 def test(a_po, *, b, **kwargs):
2822 return a_po, kwargs
2823
2824 sig = inspect.signature(test)
2825 new_params = list(sig.parameters.values())
2826 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2827 test.__signature__ = sig.replace(parameters=new_params)
2828
2829 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002830 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002831
Yury Selivanov2393dca2014-01-27 15:07:58 -05002832 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2833 '(foo, /)')
2834
2835 self.assertEqual(str(S(parameters=[
2836 P('foo', P.POSITIONAL_ONLY),
2837 P('bar', P.VAR_KEYWORD)])),
2838 '(foo, /, **bar)')
2839
2840 self.assertEqual(str(S(parameters=[
2841 P('foo', P.POSITIONAL_ONLY),
2842 P('bar', P.VAR_POSITIONAL)])),
2843 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002844
2845 def test_signature_replace_anno(self):
2846 def test() -> 42:
2847 pass
2848
2849 sig = inspect.signature(test)
2850 sig = sig.replace(return_annotation=None)
2851 self.assertIs(sig.return_annotation, None)
2852 sig = sig.replace(return_annotation=sig.empty)
2853 self.assertIs(sig.return_annotation, sig.empty)
2854 sig = sig.replace(return_annotation=42)
2855 self.assertEqual(sig.return_annotation, 42)
2856 self.assertEqual(sig, inspect.signature(test))
2857
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002858 def test_signature_on_mangled_parameters(self):
2859 class Spam:
2860 def foo(self, __p1:1=2, *, __p2:2=3):
2861 pass
2862 class Ham(Spam):
2863 pass
2864
2865 self.assertEqual(self.signature(Spam.foo),
2866 ((('self', ..., ..., "positional_or_keyword"),
2867 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2868 ('_Spam__p2', 3, 2, "keyword_only")),
2869 ...))
2870
2871 self.assertEqual(self.signature(Spam.foo),
2872 self.signature(Ham.foo))
2873
Yury Selivanovda396452014-03-27 12:09:24 -04002874 def test_signature_from_callable_python_obj(self):
2875 class MySignature(inspect.Signature): pass
2876 def foo(a, *, b:1): pass
2877 foo_sig = MySignature.from_callable(foo)
2878 self.assertTrue(isinstance(foo_sig, MySignature))
2879
2880 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2881 "Signature information for builtins requires docstrings")
2882 def test_signature_from_callable_builtin_obj(self):
2883 class MySignature(inspect.Signature): pass
2884 sig = MySignature.from_callable(_pickle.Pickler)
2885 self.assertTrue(isinstance(sig, MySignature))
2886
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002887
2888class TestParameterObject(unittest.TestCase):
2889 def test_signature_parameter_kinds(self):
2890 P = inspect.Parameter
2891 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2892 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2893
2894 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2895 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2896
2897 def test_signature_parameter_object(self):
2898 p = inspect.Parameter('foo', default=10,
2899 kind=inspect.Parameter.POSITIONAL_ONLY)
2900 self.assertEqual(p.name, 'foo')
2901 self.assertEqual(p.default, 10)
2902 self.assertIs(p.annotation, p.empty)
2903 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2904
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002905 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002906 inspect.Parameter('foo', default=10, kind='123')
2907
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002908 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002909 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2910
Yury Selivanov2393dca2014-01-27 15:07:58 -05002911 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002912 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2913
Yury Selivanov2393dca2014-01-27 15:07:58 -05002914 with self.assertRaisesRegex(ValueError,
2915 'is not a valid parameter name'):
2916 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2917
Nick Coghlanb4b966e2016-06-04 14:40:03 -07002918 with self.assertRaisesRegex(ValueError,
2919 'is not a valid parameter name'):
2920 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
2921
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002922 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002923 inspect.Parameter('a', default=42,
2924 kind=inspect.Parameter.VAR_KEYWORD)
2925
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002926 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002927 inspect.Parameter('a', default=42,
2928 kind=inspect.Parameter.VAR_POSITIONAL)
2929
2930 p = inspect.Parameter('a', default=42,
2931 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002932 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002933 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2934
2935 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002936 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002937
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002938 def test_signature_parameter_hashable(self):
2939 P = inspect.Parameter
2940 foo = P('foo', kind=P.POSITIONAL_ONLY)
2941 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
2942 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
2943 default=42)))
2944 self.assertNotEqual(hash(foo),
2945 hash(foo.replace(kind=P.VAR_POSITIONAL)))
2946
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002947 def test_signature_parameter_equality(self):
2948 P = inspect.Parameter
2949 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2950
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002951 self.assertTrue(p == p)
2952 self.assertFalse(p != p)
2953 self.assertFalse(p == 42)
2954 self.assertTrue(p != 42)
2955 self.assertTrue(p == EqualsToAll())
2956 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002957
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002958 self.assertTrue(p == P('foo', default=42,
2959 kind=inspect.Parameter.KEYWORD_ONLY))
2960 self.assertFalse(p != P('foo', default=42,
2961 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002962
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002963 def test_signature_parameter_replace(self):
2964 p = inspect.Parameter('foo', default=42,
2965 kind=inspect.Parameter.KEYWORD_ONLY)
2966
2967 self.assertIsNot(p, p.replace())
2968 self.assertEqual(p, p.replace())
2969
2970 p2 = p.replace(annotation=1)
2971 self.assertEqual(p2.annotation, 1)
2972 p2 = p2.replace(annotation=p2.empty)
2973 self.assertEqual(p, p2)
2974
2975 p2 = p2.replace(name='bar')
2976 self.assertEqual(p2.name, 'bar')
2977 self.assertNotEqual(p2, p)
2978
Yury Selivanov2393dca2014-01-27 15:07:58 -05002979 with self.assertRaisesRegex(ValueError,
2980 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002981 p2 = p2.replace(name=p2.empty)
2982
2983 p2 = p2.replace(name='foo', default=None)
2984 self.assertIs(p2.default, None)
2985 self.assertNotEqual(p2, p)
2986
2987 p2 = p2.replace(name='foo', default=p2.empty)
2988 self.assertIs(p2.default, p2.empty)
2989
2990
2991 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2992 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2993 self.assertNotEqual(p2, p)
2994
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002995 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002996 p2 = p2.replace(kind=p2.empty)
2997
2998 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2999 self.assertEqual(p2, p)
3000
3001 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003002 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3003 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003004
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003005 @cpython_only
3006 def test_signature_parameter_implicit(self):
3007 with self.assertRaisesRegex(ValueError,
3008 'implicit arguments must be passed in as'):
3009 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3010
3011 param = inspect.Parameter(
3012 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3013 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3014 self.assertEqual(param.name, 'implicit0')
3015
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003016 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003017 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003018
3019 with self.assertRaises(AttributeError):
3020 p.foo = 'bar'
3021
3022 with self.assertRaises(AttributeError):
3023 p.kind = 123
3024
3025
3026class TestSignatureBind(unittest.TestCase):
3027 @staticmethod
3028 def call(func, *args, **kwargs):
3029 sig = inspect.signature(func)
3030 ba = sig.bind(*args, **kwargs)
3031 return func(*ba.args, **ba.kwargs)
3032
3033 def test_signature_bind_empty(self):
3034 def test():
3035 return 42
3036
3037 self.assertEqual(self.call(test), 42)
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)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003040 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003041 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003042 with self.assertRaisesRegex(
3043 TypeError, "got an unexpected keyword argument 'spam'"):
3044
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003045 self.call(test, spam=1)
3046
3047 def test_signature_bind_var(self):
3048 def test(*args, **kwargs):
3049 return args, kwargs
3050
3051 self.assertEqual(self.call(test), ((), {}))
3052 self.assertEqual(self.call(test, 1), ((1,), {}))
3053 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3054 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3055 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3056 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3057 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3058 ((1, 2), {'foo': 'bar'}))
3059
3060 def test_signature_bind_just_args(self):
3061 def test(a, b, c):
3062 return a, b, c
3063
3064 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3065
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003066 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003067 self.call(test, 1, 2, 3, 4)
3068
Yury Selivanov86872752015-05-19 00:27:49 -04003069 with self.assertRaisesRegex(TypeError,
3070 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003071 self.call(test, 1)
3072
Yury Selivanov86872752015-05-19 00:27:49 -04003073 with self.assertRaisesRegex(TypeError,
3074 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003075 self.call(test)
3076
3077 def test(a, b, c=10):
3078 return a, b, c
3079 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3080 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3081
3082 def test(a=1, b=2, c=3):
3083 return a, b, c
3084 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3085 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3086 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3087
3088 def test_signature_bind_varargs_order(self):
3089 def test(*args):
3090 return args
3091
3092 self.assertEqual(self.call(test), ())
3093 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3094
3095 def test_signature_bind_args_and_varargs(self):
3096 def test(a, b, c=3, *args):
3097 return a, b, c, args
3098
3099 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3100 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3101 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3102 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3103
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003104 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003105 "multiple values for argument 'c'"):
3106 self.call(test, 1, 2, 3, c=4)
3107
3108 def test_signature_bind_just_kwargs(self):
3109 def test(**kwargs):
3110 return kwargs
3111
3112 self.assertEqual(self.call(test), {})
3113 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3114 {'foo': 'bar', 'spam': 'ham'})
3115
3116 def test_signature_bind_args_and_kwargs(self):
3117 def test(a, b, c=3, **kwargs):
3118 return a, b, c, kwargs
3119
3120 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3121 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3122 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3123 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3124 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3125 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3126 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3127 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3128 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3129 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3130 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3131 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3132 (1, 2, 4, {'foo': 'bar'}))
3133 self.assertEqual(self.call(test, c=5, a=4, b=3),
3134 (4, 3, 5, {}))
3135
3136 def test_signature_bind_kwonly(self):
3137 def test(*, foo):
3138 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003139 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003140 'too many positional arguments'):
3141 self.call(test, 1)
3142 self.assertEqual(self.call(test, foo=1), 1)
3143
3144 def test(a, *, foo=1, bar):
3145 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003146 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003147 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003148 self.call(test, 1)
3149
3150 def test(foo, *, bar):
3151 return foo, bar
3152 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3153 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3154
Yury Selivanov86872752015-05-19 00:27:49 -04003155 with self.assertRaisesRegex(
3156 TypeError, "got an unexpected keyword argument 'spam'"):
3157
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003158 self.call(test, bar=2, foo=1, spam=10)
3159
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003160 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003161 'too many positional arguments'):
3162 self.call(test, 1, 2)
3163
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003164 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003165 'too many positional arguments'):
3166 self.call(test, 1, 2, bar=2)
3167
Yury Selivanov86872752015-05-19 00:27:49 -04003168 with self.assertRaisesRegex(
3169 TypeError, "got an unexpected keyword argument 'spam'"):
3170
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003171 self.call(test, 1, bar=2, spam='ham')
3172
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003173 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003174 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003175 self.call(test, 1)
3176
3177 def test(foo, *, bar, **bin):
3178 return foo, bar, bin
3179 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3180 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3181 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3182 (1, 2, {'spam': 'ham'}))
3183 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3184 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003185 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003186 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003187 self.call(test, spam='ham', bar=2)
3188 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3189 (1, 2, {'bin': 1, 'spam': 10}))
3190
3191 def test_signature_bind_arguments(self):
3192 def test(a, *args, b, z=100, **kwargs):
3193 pass
3194 sig = inspect.signature(test)
3195 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3196 # we won't have 'z' argument in the bound arguments object, as we didn't
3197 # pass it to the 'bind'
3198 self.assertEqual(tuple(ba.arguments.items()),
3199 (('a', 10), ('args', (20,)), ('b', 30),
3200 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3201 self.assertEqual(ba.kwargs,
3202 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3203 self.assertEqual(ba.args, (10, 20))
3204
3205 def test_signature_bind_positional_only(self):
3206 P = inspect.Parameter
3207
3208 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3209 return a_po, b_po, c_po, foo, bar, kwargs
3210
3211 sig = inspect.signature(test)
3212 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3213 for name in ('a_po', 'b_po', 'c_po'):
3214 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3215 new_sig = sig.replace(parameters=new_params.values())
3216 test.__signature__ = new_sig
3217
3218 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3219 (1, 2, 4, 5, 6, {}))
3220
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003221 self.assertEqual(self.call(test, 1, 2),
3222 (1, 2, 3, 42, 50, {}))
3223
3224 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3225 (1, 2, 3, 4, 5, {}))
3226
3227 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3228 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3229
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003230 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003231 self.call(test, 1, 2, c_po=4)
3232
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003233 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003234 self.call(test, a_po=1, b_po=2)
3235
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003236 def test_signature_bind_with_self_arg(self):
3237 # Issue #17071: one of the parameters is named "self
3238 def test(a, self, b):
3239 pass
3240 sig = inspect.signature(test)
3241 ba = sig.bind(1, 2, 3)
3242 self.assertEqual(ba.args, (1, 2, 3))
3243 ba = sig.bind(1, self=2, b=3)
3244 self.assertEqual(ba.args, (1, 2, 3))
3245
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003246 def test_signature_bind_vararg_name(self):
3247 def test(a, *args):
3248 return a, args
3249 sig = inspect.signature(test)
3250
Yury Selivanov86872752015-05-19 00:27:49 -04003251 with self.assertRaisesRegex(
3252 TypeError, "got an unexpected keyword argument 'args'"):
3253
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003254 sig.bind(a=0, args=1)
3255
3256 def test(*args, **kwargs):
3257 return args, kwargs
3258 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3259
3260 sig = inspect.signature(test)
3261 ba = sig.bind(args=1)
3262 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3263
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003264 @cpython_only
3265 def test_signature_bind_implicit_arg(self):
3266 # Issue #19611: getcallargs should work with set comprehensions
3267 def make_set():
3268 return {z * z for z in range(5)}
3269 setcomp_code = make_set.__code__.co_consts[1]
3270 setcomp_func = types.FunctionType(setcomp_code, {})
3271
3272 iterator = iter(range(5))
3273 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3274
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003275
3276class TestBoundArguments(unittest.TestCase):
3277 def test_signature_bound_arguments_unhashable(self):
3278 def foo(a): pass
3279 ba = inspect.signature(foo).bind(1)
3280
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003281 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003282 hash(ba)
3283
3284 def test_signature_bound_arguments_equality(self):
3285 def foo(a): pass
3286 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003287 self.assertTrue(ba == ba)
3288 self.assertFalse(ba != ba)
3289 self.assertTrue(ba == EqualsToAll())
3290 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003291
3292 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003293 self.assertTrue(ba == ba2)
3294 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003295
3296 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003297 self.assertFalse(ba == ba3)
3298 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003299 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003300 self.assertTrue(ba == ba3)
3301 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003302
3303 def bar(b): pass
3304 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003305 self.assertFalse(ba == ba4)
3306 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003307
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003308 def foo(*, a, b): pass
3309 sig = inspect.signature(foo)
3310 ba1 = sig.bind(a=1, b=2)
3311 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003312 self.assertTrue(ba1 == ba2)
3313 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003314
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003315 def test_signature_bound_arguments_pickle(self):
3316 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3317 sig = inspect.signature(foo)
3318 ba = sig.bind(20, 30, z={})
3319
3320 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3321 with self.subTest(pickle_ver=ver):
3322 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3323 self.assertEqual(ba, ba_pickled)
3324
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003325 def test_signature_bound_arguments_repr(self):
3326 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3327 sig = inspect.signature(foo)
3328 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003329 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003330
Yury Selivanovb907a512015-05-16 13:45:09 -04003331 def test_signature_bound_arguments_apply_defaults(self):
3332 def foo(a, b=1, *args, c:1={}, **kw): pass
3333 sig = inspect.signature(foo)
3334
3335 ba = sig.bind(20)
3336 ba.apply_defaults()
3337 self.assertEqual(
3338 list(ba.arguments.items()),
3339 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3340
3341 # Make sure that we preserve the order:
3342 # i.e. 'c' should be *before* 'kw'.
3343 ba = sig.bind(10, 20, 30, d=1)
3344 ba.apply_defaults()
3345 self.assertEqual(
3346 list(ba.arguments.items()),
3347 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3348
3349 # Make sure that BoundArguments produced by bind_partial()
3350 # are supported.
3351 def foo(a, b): pass
3352 sig = inspect.signature(foo)
3353 ba = sig.bind_partial(20)
3354 ba.apply_defaults()
3355 self.assertEqual(
3356 list(ba.arguments.items()),
3357 [('a', 20)])
3358
3359 # Test no args
3360 def foo(): pass
3361 sig = inspect.signature(foo)
3362 ba = sig.bind()
3363 ba.apply_defaults()
3364 self.assertEqual(list(ba.arguments.items()), [])
3365
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003366 # Make sure a no-args binding still acquires proper defaults.
3367 def foo(a='spam'): pass
3368 sig = inspect.signature(foo)
3369 ba = sig.bind()
3370 ba.apply_defaults()
3371 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3372
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003373
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003374class TestSignaturePrivateHelpers(unittest.TestCase):
3375 def test_signature_get_bound_param(self):
3376 getter = inspect._signature_get_bound_param
3377
3378 self.assertEqual(getter('($self)'), 'self')
3379 self.assertEqual(getter('($self, obj)'), 'self')
3380 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3381
Larry Hastings2623c8c2014-02-08 22:15:29 -08003382 def _strip_non_python_syntax(self, input,
3383 clean_signature, self_parameter, last_positional_only):
3384 computed_clean_signature, \
3385 computed_self_parameter, \
3386 computed_last_positional_only = \
3387 inspect._signature_strip_non_python_syntax(input)
3388 self.assertEqual(computed_clean_signature, clean_signature)
3389 self.assertEqual(computed_self_parameter, self_parameter)
3390 self.assertEqual(computed_last_positional_only, last_positional_only)
3391
3392 def test_signature_strip_non_python_syntax(self):
3393 self._strip_non_python_syntax(
3394 "($module, /, path, mode, *, dir_fd=None, " +
3395 "effective_ids=False,\n follow_symlinks=True)",
3396 "(module, path, mode, *, dir_fd=None, " +
3397 "effective_ids=False, follow_symlinks=True)",
3398 0,
3399 0)
3400
3401 self._strip_non_python_syntax(
3402 "($module, word, salt, /)",
3403 "(module, word, salt)",
3404 0,
3405 2)
3406
3407 self._strip_non_python_syntax(
3408 "(x, y=None, z=None, /)",
3409 "(x, y=None, z=None)",
3410 None,
3411 2)
3412
3413 self._strip_non_python_syntax(
3414 "(x, y=None, z=None)",
3415 "(x, y=None, z=None)",
3416 None,
3417 None)
3418
3419 self._strip_non_python_syntax(
3420 "(x,\n y=None,\n z = None )",
3421 "(x, y=None, z=None)",
3422 None,
3423 None)
3424
3425 self._strip_non_python_syntax(
3426 "",
3427 "",
3428 None,
3429 None)
3430
3431 self._strip_non_python_syntax(
3432 None,
3433 None,
3434 None,
3435 None)
3436
Nick Coghlan9c680b02015-04-13 12:54:54 -04003437class TestSignatureDefinitions(unittest.TestCase):
3438 # This test case provides a home for checking that particular APIs
3439 # have signatures available for introspection
3440
3441 @cpython_only
3442 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3443 "Signature information for builtins requires docstrings")
3444 def test_builtins_have_signatures(self):
3445 # This checks all builtin callables in CPython have signatures
3446 # A few have signatures Signature can't yet handle, so we skip those
3447 # since they will have to wait until PEP 457 adds the required
3448 # introspection support to the inspect module
3449 # Some others also haven't been converted yet for various other
3450 # reasons, so we also skip those for the time being, but design
3451 # the test to fail in order to indicate when it needs to be
3452 # updated.
3453 no_signature = set()
3454 # These need PEP 457 groups
3455 needs_groups = {"range", "slice", "dir", "getattr",
3456 "next", "iter", "vars"}
3457 no_signature |= needs_groups
3458 # These need PEP 457 groups or a signature change to accept None
3459 needs_semantic_update = {"round"}
3460 no_signature |= needs_semantic_update
3461 # These need *args support in Argument Clinic
3462 needs_varargs = {"min", "max", "print", "__build_class__"}
3463 no_signature |= needs_varargs
3464 # These simply weren't covered in the initial AC conversion
3465 # for builtin callables
3466 not_converted_yet = {"open", "__import__"}
3467 no_signature |= not_converted_yet
3468 # These builtin types are expected to provide introspection info
3469 types_with_signatures = set()
3470 # Check the signatures we expect to be there
3471 ns = vars(builtins)
3472 for name, obj in sorted(ns.items()):
3473 if not callable(obj):
3474 continue
3475 # The builtin types haven't been converted to AC yet
3476 if isinstance(obj, type) and (name not in types_with_signatures):
3477 # Note that this also skips all the exception types
3478 no_signature.add(name)
3479 if (name in no_signature):
3480 # Not yet converted
3481 continue
3482 with self.subTest(builtin=name):
3483 self.assertIsNotNone(inspect.signature(obj))
3484 # Check callables that haven't been converted don't claim a signature
3485 # This ensures this test will start failing as more signatures are
3486 # added, so the affected items can be moved into the scope of the
3487 # regression test above
3488 for name in no_signature:
3489 with self.subTest(builtin=name):
3490 self.assertIsNone(obj.__text_signature__)
3491
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003492
Nick Coghlane8c45d62013-07-28 20:00:01 +10003493class TestUnwrap(unittest.TestCase):
3494
3495 def test_unwrap_one(self):
3496 def func(a, b):
3497 return a + b
3498 wrapper = functools.lru_cache(maxsize=20)(func)
3499 self.assertIs(inspect.unwrap(wrapper), func)
3500
3501 def test_unwrap_several(self):
3502 def func(a, b):
3503 return a + b
3504 wrapper = func
3505 for __ in range(10):
3506 @functools.wraps(wrapper)
3507 def wrapper():
3508 pass
3509 self.assertIsNot(wrapper.__wrapped__, func)
3510 self.assertIs(inspect.unwrap(wrapper), func)
3511
3512 def test_stop(self):
3513 def func1(a, b):
3514 return a + b
3515 @functools.wraps(func1)
3516 def func2():
3517 pass
3518 @functools.wraps(func2)
3519 def wrapper():
3520 pass
3521 func2.stop_here = 1
3522 unwrapped = inspect.unwrap(wrapper,
3523 stop=(lambda f: hasattr(f, "stop_here")))
3524 self.assertIs(unwrapped, func2)
3525
3526 def test_cycle(self):
3527 def func1(): pass
3528 func1.__wrapped__ = func1
3529 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3530 inspect.unwrap(func1)
3531
3532 def func2(): pass
3533 func2.__wrapped__ = func1
3534 func1.__wrapped__ = func2
3535 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3536 inspect.unwrap(func1)
3537 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3538 inspect.unwrap(func2)
3539
3540 def test_unhashable(self):
3541 def func(): pass
3542 func.__wrapped__ = None
3543 class C:
3544 __hash__ = None
3545 __wrapped__ = func
3546 self.assertIsNone(inspect.unwrap(C()))
3547
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003548class TestMain(unittest.TestCase):
3549 def test_only_source(self):
3550 module = importlib.import_module('unittest')
3551 rc, out, err = assert_python_ok('-m', 'inspect',
3552 'unittest')
3553 lines = out.decode().splitlines()
3554 # ignore the final newline
3555 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3556 self.assertEqual(err, b'')
3557
Yury Selivanov42407ab2014-06-23 10:23:50 -07003558 def test_custom_getattr(self):
3559 def foo():
3560 pass
3561 foo.__signature__ = 42
3562 with self.assertRaises(TypeError):
3563 inspect.signature(foo)
3564
Brett Cannon634a8fc2013-10-02 10:25:42 -04003565 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003566 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003567 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003568 rc, out, err = assert_python_ok('-m', 'inspect',
3569 'concurrent.futures:ThreadPoolExecutor')
3570 lines = out.decode().splitlines()
3571 # ignore the final newline
3572 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003573 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003574 self.assertEqual(err, b'')
3575
3576 def test_builtins(self):
3577 module = importlib.import_module('unittest')
3578 _, out, err = assert_python_failure('-m', 'inspect',
3579 'sys')
3580 lines = err.decode().splitlines()
3581 self.assertEqual(lines, ["Can't get info for builtin modules."])
3582
3583 def test_details(self):
3584 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003585 args = support.optim_args_from_interpreter_flags()
3586 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003587 'unittest', '--details')
3588 output = out.decode()
3589 # Just a quick sanity check on the output
3590 self.assertIn(module.__name__, output)
3591 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003592 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003593 self.assertEqual(err, b'')
3594
3595
Yury Selivanovef1e7502014-12-08 16:05:34 -05003596class TestReload(unittest.TestCase):
3597
3598 src_before = textwrap.dedent("""\
3599def foo():
3600 print("Bla")
3601 """)
3602
3603 src_after = textwrap.dedent("""\
3604def foo():
3605 print("Oh no!")
3606 """)
3607
3608 def assertInspectEqual(self, path, source):
3609 inspected_src = inspect.getsource(source)
3610 with open(path) as src:
3611 self.assertEqual(
3612 src.read().splitlines(True),
3613 inspected_src.splitlines(True)
3614 )
3615
3616 def test_getsource_reload(self):
3617 # see issue 1218234
3618 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3619 module = importlib.import_module(name)
3620 self.assertInspectEqual(path, module)
3621 with open(path, 'w') as src:
3622 src.write(self.src_after)
3623 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003624
Nick Coghlane8c45d62013-07-28 20:00:01 +10003625
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003626def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003627 run_unittest(
3628 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3629 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3630 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003631 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003632 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003633 TestBoundArguments, TestSignaturePrivateHelpers,
3634 TestSignatureDefinitions,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003635 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
3636 TestGetCoroutineState
Michael Foord95fc51d2010-11-20 15:07:30 +00003637 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003638
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003639if __name__ == "__main__":
3640 test_main()