blob: 042617b60dc1c80e61a1cd317617ddd2870c77fe [file] [log] [blame]
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001import builtins
Guido van Rossum813b0e52007-05-21 18:11:34 +00002import collections
Larry Hastings5c661892014-01-24 06:17:25 -08003import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10004import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10005import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08006import inspect
7import io
8import linecache
9import os
Christian Heimesa3538eb2007-11-06 11:44:48 +000010from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080011import _pickle
Yury Selivanova5d63dd2014-03-27 11:31:43 -040012import pickle
Larry Hastings5c661892014-01-24 06:17:25 -080013import re
14import shutil
15import sys
16import types
Yury Selivanovef1e7502014-12-08 16:05:34 -050017import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080018import unicodedata
19import unittest
Yury Selivanova773de02014-02-21 18:30:53 -050020import unittest.mock
Yury Selivanov75445082015-05-11 22:57:16 -040021import warnings
Larry Hastings5c661892014-01-24 06:17:25 -080022
Brett Cannon634a8fc2013-10-02 10:25:42 -040023try:
24 from concurrent.futures import ThreadPoolExecutor
25except ImportError:
26 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000027
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020028from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Nick Coghlanf9e227e2014-08-17 14:01:19 +100029from test.support import MISSING_C_DOCSTRINGS, cpython_only
Berker Peksagce643912015-05-06 06:33:17 +030030from test.support.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000031from test import inspect_fodder as mod
32from test import inspect_fodder2 as mod2
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,
41# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
42# 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
Georg Brandl1a3284e2007-12-02 09:40:06 +000058import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000059
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000060git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000061
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000062class IsTestBase(unittest.TestCase):
63 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
64 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000065 inspect.ismodule, inspect.istraceback,
Yury Selivanov75445082015-05-11 22:57:16 -040066 inspect.isgenerator, inspect.isgeneratorfunction,
67 inspect.iscoroutine, inspect.iscoroutinefunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000068
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000069 def istest(self, predicate, exp):
70 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000071 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000072
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000073 for other in self.predicates - set([predicate]):
Yury Selivanov75445082015-05-11 22:57:16 -040074 if (predicate == inspect.isgeneratorfunction or \
75 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 Selivanov75445082015-05-11 22:57:16 -040084async def coroutine_function_example(self):
85 return 'spam'
86
87@types.coroutine
88def gen_coroutine_function_example(self):
89 yield
90 return 'spam'
91
Serhiy Storchaka3018cc42015-07-18 23:19:05 +030092class EqualsToAll:
93 def __eq__(self, other):
94 return True
Yury Selivanova5d63dd2014-03-27 11:31:43 -040095
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000096class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +000097
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000098 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020099 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000100 self.istest(inspect.isbuiltin, 'sys.exit')
101 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +0000102 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200103 try:
104 1/0
105 except:
106 tb = sys.exc_info()[2]
107 self.istest(inspect.isframe, 'tb.tb_frame')
108 self.istest(inspect.istraceback, 'tb')
109 if hasattr(types, 'GetSetDescriptorType'):
110 self.istest(inspect.isgetsetdescriptor,
111 'type(tb.tb_frame).f_locals')
112 else:
113 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
114 finally:
115 # Clear traceback and all the frames and local variables hanging to it.
116 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000117 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000118 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000119 self.istest(inspect.ismethod, 'git.argue')
120 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000121 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000122 self.istest(inspect.isgenerator, '(x for x in range(2))')
123 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400124
125 with warnings.catch_warnings():
126 warnings.simplefilter("ignore")
127 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
128 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
129
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000130 if hasattr(types, 'MemberDescriptorType'):
131 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
132 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000133 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000134
Yury Selivanov75445082015-05-11 22:57:16 -0400135 def test_iscoroutine(self):
136 gen_coro = gen_coroutine_function_example(1)
137 coro = coroutine_function_example(1)
138
Yury Selivanov5376ba92015-06-22 12:19:30 -0400139 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400140 inspect.iscoroutinefunction(gen_coroutine_function_example))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400141 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400142
143 self.assertTrue(
144 inspect.isgeneratorfunction(gen_coroutine_function_example))
145 self.assertTrue(inspect.isgenerator(gen_coro))
146
147 self.assertTrue(
148 inspect.iscoroutinefunction(coroutine_function_example))
149 self.assertTrue(inspect.iscoroutine(coro))
150
151 self.assertFalse(
152 inspect.isgeneratorfunction(coroutine_function_example))
153 self.assertFalse(inspect.isgenerator(coro))
154
155 coro.close(); gen_coro.close() # silence warnings
156
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400157 def test_isawaitable(self):
158 def gen(): yield
159 self.assertFalse(inspect.isawaitable(gen()))
160
161 coro = coroutine_function_example(1)
162 gen_coro = gen_coroutine_function_example(1)
163
164 self.assertTrue(inspect.isawaitable(coro))
165 self.assertTrue(inspect.isawaitable(gen_coro))
166
167 class Future:
168 def __await__():
169 pass
170 self.assertTrue(inspect.isawaitable(Future()))
171 self.assertFalse(inspect.isawaitable(Future))
172
173 class NotFuture: pass
174 not_fut = NotFuture()
175 not_fut.__await__ = lambda: None
176 self.assertFalse(inspect.isawaitable(not_fut))
177
178 coro.close(); gen_coro.close() # silence warnings
179
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000180 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000181 self.assertTrue(inspect.isroutine(mod.spam))
182 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000183
Benjamin Petersonc4656002009-01-17 22:41:18 +0000184 def test_isclass(self):
185 self.istest(inspect.isclass, 'mod.StupidGit')
186 self.assertTrue(inspect.isclass(list))
187
188 class CustomGetattr(object):
189 def __getattr__(self, attr):
190 return None
191 self.assertFalse(inspect.isclass(CustomGetattr()))
192
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000193 def test_get_slot_members(self):
194 class C(object):
195 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000196 x = C()
197 x.a = 42
198 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000199 self.assertIn('a', members)
200 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000201
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000202 def test_isabstract(self):
203 from abc import ABCMeta, abstractmethod
204
205 class AbstractClassExample(metaclass=ABCMeta):
206
207 @abstractmethod
208 def foo(self):
209 pass
210
211 class ClassExample(AbstractClassExample):
212 def foo(self):
213 pass
214
215 a = ClassExample()
216
217 # Test general behaviour.
218 self.assertTrue(inspect.isabstract(AbstractClassExample))
219 self.assertFalse(inspect.isabstract(ClassExample))
220 self.assertFalse(inspect.isabstract(a))
221 self.assertFalse(inspect.isabstract(int))
222 self.assertFalse(inspect.isabstract(5))
223
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000224
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000225class TestInterpreterStack(IsTestBase):
226 def __init__(self, *args, **kwargs):
227 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000228
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000229 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000230
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000231 def test_abuse_done(self):
232 self.istest(inspect.istraceback, 'git.ex[2]')
233 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000234
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000235 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000236 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000237 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000238 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000239 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000240 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000241 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000242 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000243 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000244 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400245 # Test named tuple fields
246 record = mod.st[0]
247 self.assertIs(record.frame, mod.fr)
248 self.assertEqual(record.lineno, 16)
249 self.assertEqual(record.filename, mod.__file__)
250 self.assertEqual(record.function, 'eggs')
251 self.assertIn('inspect.stack()', record.code_context[0])
252 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000253
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000254 def test_trace(self):
255 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000256 self.assertEqual(revise(*git.tr[0][1:]),
257 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
258 self.assertEqual(revise(*git.tr[1][1:]),
259 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
260 self.assertEqual(revise(*git.tr[2][1:]),
261 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000262
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000263 def test_frame(self):
264 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
265 self.assertEqual(args, ['x', 'y'])
266 self.assertEqual(varargs, None)
267 self.assertEqual(varkw, None)
268 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
269 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
270 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000271
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000272 def test_previous_frame(self):
273 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000274 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000275 self.assertEqual(varargs, 'g')
276 self.assertEqual(varkw, 'h')
277 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000278 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000279
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000280class GetSourceBase(unittest.TestCase):
281 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000282 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000283
Yury Selivanov6738b112015-05-16 10:10:21 -0400284 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000285 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000286 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000287
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000288 def sourcerange(self, top, bottom):
289 lines = self.source.split("\n")
290 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000291
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000292 def assertSourceEqual(self, obj, top, bottom):
293 self.assertEqual(inspect.getsource(obj),
294 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000295
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000296class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000297 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000298
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000299 def test_getclasses(self):
300 classes = inspect.getmembers(mod, inspect.isclass)
301 self.assertEqual(classes,
302 [('FesteringGob', mod.FesteringGob),
303 ('MalodorousPervert', mod.MalodorousPervert),
304 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300305 ('StupidGit', mod.StupidGit),
306 ('Tit', mod.MalodorousPervert),
307 ])
308 tree = inspect.getclasstree([cls[1] for cls in classes])
309 self.assertEqual(tree,
310 [(object, ()),
311 [(mod.ParrotDroppings, (object,)),
312 [(mod.FesteringGob, (mod.MalodorousPervert,
313 mod.ParrotDroppings))
314 ],
315 (mod.StupidGit, (object,)),
316 [(mod.MalodorousPervert, (mod.StupidGit,)),
317 [(mod.FesteringGob, (mod.MalodorousPervert,
318 mod.ParrotDroppings))
319 ]
320 ]
321 ]
322 ])
323 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000324 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000325 [(object, ()),
326 [(mod.ParrotDroppings, (object,)),
327 (mod.StupidGit, (object,)),
328 [(mod.MalodorousPervert, (mod.StupidGit,)),
329 [(mod.FesteringGob, (mod.MalodorousPervert,
330 mod.ParrotDroppings))
331 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000332 ]
333 ]
334 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000335
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000336 def test_getfunctions(self):
337 functions = inspect.getmembers(mod, inspect.isfunction)
338 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300339 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000340 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000341
R. David Murray378c0cf2010-02-24 01:46:21 +0000342 @unittest.skipIf(sys.flags.optimize >= 2,
343 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000344 def test_getdoc(self):
345 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
346 self.assertEqual(inspect.getdoc(mod.StupidGit),
347 'A longer,\n\nindented\n\ndocstring.')
348 self.assertEqual(inspect.getdoc(git.abuse),
349 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000350
Serhiy Storchaka5cf2b7252015-04-03 22:38:53 +0300351 @unittest.skipIf(sys.flags.optimize >= 2,
352 "Docstrings are omitted with -O2 and above")
353 def test_getdoc_inherited(self):
354 self.assertEqual(inspect.getdoc(mod.FesteringGob),
355 'A longer,\n\nindented\n\ndocstring.')
356 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
357 'Another\n\ndocstring\n\ncontaining\n\ntabs')
358 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
359 'Another\n\ndocstring\n\ncontaining\n\ntabs')
360 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
361 'The automatic gainsaying.')
362
363 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
364 def test_finddoc(self):
365 finddoc = inspect._finddoc
366 self.assertEqual(finddoc(int), int.__doc__)
367 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
368 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
369 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
370 self.assertEqual(finddoc(int.real), int.real.__doc__)
371
Georg Brandl0c77a822008-06-10 16:37:50 +0000372 def test_cleandoc(self):
373 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
374 'An\nindented\ndocstring.')
375
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000376 def test_getcomments(self):
377 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
378 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000379
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000380 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000381 # Check actual module
382 self.assertEqual(inspect.getmodule(mod), mod)
383 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000384 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000385 # Check a method (no __module__ attribute, falls back to filename)
386 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
387 # Do it again (check the caching isn't broken)
388 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
389 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000390 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000391 # Check filename override
392 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000393
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000394 def test_getsource(self):
395 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchaka5cf2b7252015-04-03 22:38:53 +0300396 self.assertSourceEqual(mod.StupidGit, 21, 50)
Yury Selivanove4e811d2015-07-21 19:01:52 +0300397 self.assertSourceEqual(mod.lobbest, 70, 71)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000398
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000399 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000400 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
401 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000402 fn = "_non_existing_filename_used_for_sourcefile_test.py"
403 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000404 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000405 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200406 try:
407 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
408 finally:
409 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000410
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000411 def test_getfile(self):
412 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000413
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500414 def test_getfile_class_without_module(self):
415 class CM(type):
416 @property
417 def __module__(cls):
418 raise AttributeError
419 class C(metaclass=CM):
420 pass
421 with self.assertRaises(TypeError):
422 inspect.getfile(C)
423
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000424 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000425 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000426 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000427 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000428 m.__file__ = "<string>" # hopefully not a real filename...
429 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000430 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000431 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000432 del sys.modules[name]
433 inspect.getmodule(compile('a=10','','single'))
434
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500435 def test_proceed_with_fake_filename(self):
436 '''doctest monkeypatches linecache to enable inspection'''
437 fn, source = '<test>', 'def x(): pass\n'
438 getlines = linecache.getlines
439 def monkey(filename, module_globals=None):
440 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300441 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500442 else:
443 return getlines(filename, module_globals)
444 linecache.getlines = monkey
445 try:
446 ns = {}
447 exec(compile(source, fn, 'single'), ns)
448 inspect.getsource(ns["x"])
449 finally:
450 linecache.getlines = getlines
451
Antoine Pitroua8723a02015-04-15 00:41:29 +0200452 def test_getsource_on_code_object(self):
453 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
454
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000455class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000456 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000457
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000458 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000459 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000460
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000461 def test_replacing_decorator(self):
462 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000463
Yury Selivanov081bbf62014-09-26 17:34:54 -0400464 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200465 self.assertSourceEqual(mod2.real, 130, 132)
466
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300467 @unittest.expectedFailure
Antoine Pitroua8723a02015-04-15 00:41:29 +0200468 def test_decorator_with_lambda(self):
469 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400470
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000471class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000472 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000473 def test_oneline_lambda(self):
474 # Test inspect.getsource with a one-line lambda function.
475 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000476
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000477 def test_threeline_lambda(self):
478 # Test inspect.getsource with a three-line lambda function,
479 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000480 self.assertSourceEqual(mod2.tll, 28, 30)
481
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000482 def test_twoline_indented_lambda(self):
483 # Test inspect.getsource with a two-line lambda function,
484 # where the second line _is_ indented.
485 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000486
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000487 def test_onelinefunc(self):
488 # Test inspect.getsource with a regular one-line function.
489 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000490
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000491 def test_manyargs(self):
492 # Test inspect.getsource with a regular function where
493 # the arguments are on two lines and _not_ indented and
494 # the body on the second line with the last arguments.
495 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000496
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000497 def test_twolinefunc(self):
498 # Test inspect.getsource with a regular function where
499 # the body is on two lines, following the argument list and
500 # continued on the next line by a \\.
501 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000502
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000503 def test_lambda_in_list(self):
504 # Test inspect.getsource with a one-line lambda function
505 # defined in a list, indented.
506 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000507
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000508 def test_anonymous(self):
509 # Test inspect.getsource with a lambda function defined
510 # as argument to another function.
511 self.assertSourceEqual(mod2.anonymous, 55, 55)
512
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000513class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000514 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000515
516 def test_with_comment(self):
517 self.assertSourceEqual(mod2.with_comment, 58, 59)
518
519 def test_multiline_sig(self):
520 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
521
Armin Rigodd5c0232005-09-25 11:45:45 +0000522 def test_nested_class(self):
523 self.assertSourceEqual(mod2.func69().func71, 71, 72)
524
525 def test_one_liner_followed_by_non_name(self):
526 self.assertSourceEqual(mod2.func77, 77, 77)
527
528 def test_one_liner_dedent_non_name(self):
529 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
530
531 def test_with_comment_instead_of_docstring(self):
532 self.assertSourceEqual(mod2.func88, 88, 90)
533
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000534 def test_method_in_dynamic_class(self):
535 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
536
R David Murray32562d72014-10-03 11:15:38 -0400537 # This should not skip for CPython, but might on a repackaged python where
538 # unicodedata is not an external module, or on pypy.
539 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
540 unicodedata.__file__.endswith('.py'),
541 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000542 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200543 self.assertRaises(OSError, inspect.getsource, unicodedata)
544 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000545
R. David Murraya1b37402010-06-17 02:04:29 +0000546 def test_findsource_code_in_linecache(self):
547 lines = ["x=1"]
548 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200549 self.assertRaises(OSError, inspect.findsource, co)
550 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000551 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200552 try:
553 self.assertEqual(inspect.findsource(co), (lines,0))
554 self.assertEqual(inspect.getsource(co), lines[0])
555 finally:
556 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000557
Ezio Melotti1b145922013-03-30 05:17:24 +0200558 def test_findsource_without_filename(self):
559 for fname in ['', '<string>']:
560 co = compile('x=1', fname, "exec")
561 self.assertRaises(IOError, inspect.findsource, co)
562 self.assertRaises(IOError, inspect.getsource, co)
563
Antoine Pitroua8723a02015-04-15 00:41:29 +0200564 def test_getsource_on_method(self):
565 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
566
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300567 def test_nested_func(self):
568 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
569
570
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000571class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400572 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000573 self.tempdir = TESTFN + '_dir'
574 os.mkdir(self.tempdir)
575 with open(os.path.join(self.tempdir,
576 'inspect_fodder3%spy' % os.extsep), 'w') as f:
577 f.write("class X:\n pass # No EOL")
578 with DirsOnSysPath(self.tempdir):
579 import inspect_fodder3 as mod3
580 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400581 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000582
583 def tearDown(self):
584 shutil.rmtree(self.tempdir)
585
586 def test_class(self):
587 self.assertSourceEqual(self.fodderModule.X, 1, 2)
588
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100589
590class _BrokenDataDescriptor(object):
591 """
592 A broken data descriptor. See bug #1785.
593 """
594 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700595 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100596
597 def __set__(*args):
598 raise RuntimeError
599
600 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700601 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100602
603
604class _BrokenMethodDescriptor(object):
605 """
606 A broken method descriptor. See bug #1785.
607 """
608 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700609 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100610
611 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700612 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100613
614
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000615# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000616def attrs_wo_objs(cls):
617 return [t[:3] for t in inspect.classify_class_attrs(cls)]
618
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100619
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000620class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000621 def test_newstyle_mro(self):
622 # The same w/ new-class MRO.
623 class A(object): pass
624 class B(A): pass
625 class C(A): pass
626 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000627
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000628 expected = (D, B, C, A, object)
629 got = inspect.getmro(D)
630 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000631
Christian Heimes3795b532007-11-08 13:48:53 +0000632 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
633 varkw_e=None, defaults_e=None, formatted=None):
Yury Selivanov3cfec2e2015-05-22 11:38:38 -0400634 with self.assertWarns(DeprecationWarning):
635 args, varargs, varkw, defaults = inspect.getargspec(routine)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000636 self.assertEqual(args, args_e)
637 self.assertEqual(varargs, varargs_e)
638 self.assertEqual(varkw, varkw_e)
639 self.assertEqual(defaults, defaults_e)
640 if formatted is not None:
641 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
642 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000643
Christian Heimes3795b532007-11-08 13:48:53 +0000644 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
645 varkw_e=None, defaults_e=None,
646 kwonlyargs_e=[], kwonlydefaults_e=None,
647 ann_e={}, formatted=None):
648 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
649 inspect.getfullargspec(routine)
650 self.assertEqual(args, args_e)
651 self.assertEqual(varargs, varargs_e)
652 self.assertEqual(varkw, varkw_e)
653 self.assertEqual(defaults, defaults_e)
654 self.assertEqual(kwonlyargs, kwonlyargs_e)
655 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
656 self.assertEqual(ann, ann_e)
657 if formatted is not None:
658 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
659 kwonlyargs, kwonlydefaults, ann),
660 formatted)
661
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000662 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000663 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000664
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000665 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000666 ['a', 'b', 'c', 'd', 'e', 'f'],
667 'g', 'h', (3, 4, 5),
668 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000669
Christian Heimes3795b532007-11-08 13:48:53 +0000670 self.assertRaises(ValueError, self.assertArgSpecEquals,
671 mod2.keyworded, [])
672
673 self.assertRaises(ValueError, self.assertArgSpecEquals,
674 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000675 self.assertRaises(ValueError, self.assertArgSpecEquals,
676 mod2.keyword_only_arg, [])
677
Christian Heimes3795b532007-11-08 13:48:53 +0000678
679 def test_getfullargspec(self):
680 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
681 kwonlyargs_e=['arg2'],
682 kwonlydefaults_e={'arg2':1},
683 formatted='(*arg1, arg2=1)')
684
685 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000686 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000687 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000688 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
689 kwonlyargs_e=['arg'],
690 formatted='(*, arg)')
691
Yury Selivanov57d240e2014-02-19 16:27:23 -0500692 def test_argspec_api_ignores_wrapped(self):
693 # Issue 20684: low level introspection API must ignore __wrapped__
694 @functools.wraps(mod.spam)
695 def ham(x, y):
696 pass
697 # Basic check
698 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
699 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
700 self.assertFullArgSpecEquals(functools.partial(ham),
701 ['x', 'y'], formatted='(x, y)')
702 # Other variants
703 def check_method(f):
704 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
705 formatted='(self, x, y)')
706 class C:
707 @functools.wraps(mod.spam)
708 def ham(self, x, y):
709 pass
710 pham = functools.partialmethod(ham)
711 @functools.wraps(mod.spam)
712 def __call__(self, x, y):
713 pass
714 check_method(C())
715 check_method(C.ham)
716 check_method(C().ham)
717 check_method(C.pham)
718 check_method(C().pham)
719
720 class C_new:
721 @functools.wraps(mod.spam)
722 def __new__(self, x, y):
723 pass
724 check_method(C_new)
725
726 class C_init:
727 @functools.wraps(mod.spam)
728 def __init__(self, x, y):
729 pass
730 check_method(C_init)
731
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500732 def test_getfullargspec_signature_attr(self):
733 def test():
734 pass
735 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
736 test.__signature__ = inspect.Signature(parameters=(spam_param,))
737
738 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
739
Yury Selivanov4cb93912014-01-29 11:54:12 -0500740 def test_getfullargspec_signature_annos(self):
741 def test(a:'spam') -> 'ham': pass
742 spec = inspect.getfullargspec(test)
743 self.assertEqual(test.__annotations__, spec.annotations)
744
745 def test(): pass
746 spec = inspect.getfullargspec(test)
747 self.assertEqual(test.__annotations__, spec.annotations)
748
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500749 @unittest.skipIf(MISSING_C_DOCSTRINGS,
750 "Signature information for builtins requires docstrings")
751 def test_getfullargspec_builtin_methods(self):
752 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
753 args_e=['self', 'obj'], formatted='(self, obj)')
754
755 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
756 args_e=['self', 'obj'], formatted='(self, obj)')
757
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500758 self.assertFullArgSpecEquals(
759 os.stat,
760 args_e=['path'],
761 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
762 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
763 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
764
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200765 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500766 @unittest.skipIf(MISSING_C_DOCSTRINGS,
767 "Signature information for builtins requires docstrings")
768 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200769 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500770 builtin = _testcapi.docstring_with_signature_with_defaults
771 spec = inspect.getfullargspec(builtin)
772 self.assertEqual(spec.defaults[0], 'avocado')
773
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200774 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500775 @unittest.skipIf(MISSING_C_DOCSTRINGS,
776 "Signature information for builtins requires docstrings")
777 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200778 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500779 builtin = _testcapi.docstring_no_signature
780 with self.assertRaises(TypeError):
781 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000782
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000783 def test_getargspec_method(self):
784 class A(object):
785 def m(self):
786 pass
787 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000788
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000789 def test_classify_newstyle(self):
790 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000791
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000792 def s(): pass
793 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000794
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000795 def c(cls): pass
796 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000797
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000798 def getp(self): pass
799 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000800
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000801 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000802
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000803 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000804
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000805 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000806
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100807 dd = _BrokenDataDescriptor()
808 md = _BrokenMethodDescriptor()
809
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000810 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500811
812 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
813 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
814
Benjamin Peterson577473f2010-01-19 00:09:57 +0000815 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
816 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
817 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000818 self.assertIn(('m', 'method', A), attrs,
819 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000820 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
821 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100822 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
823 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000824
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000825 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000826
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000827 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000828
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000829 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000830 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
831 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
832 self.assertIn(('p', 'property', A), attrs, 'missing property')
833 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
834 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
835 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100836 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
837 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000838
839
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000840 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000841
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000842 def m(self): pass
843 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000844
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000845 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000846 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
847 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
848 self.assertIn(('p', 'property', A), attrs, 'missing property')
849 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
850 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
851 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100852 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
853 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000854
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000855 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000856
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000857 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000858
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000859 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000860 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
861 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
862 self.assertIn(('p', 'property', A), attrs, 'missing property')
863 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
864 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
865 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100866 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
867 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
868
869 def test_classify_builtin_types(self):
870 # Simple sanity check that all built-in types can have their
871 # attributes classified.
872 for name in dir(__builtins__):
873 builtin = getattr(__builtins__, name)
874 if isinstance(builtin, type):
875 inspect.classify_class_attrs(builtin)
876
Ethan Furman63c141c2013-10-18 00:27:39 -0700877 def test_classify_DynamicClassAttribute(self):
878 class Meta(type):
879 def __getattr__(self, name):
880 if name == 'ham':
881 return 'spam'
882 return super().__getattr__(name)
883 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700884 @types.DynamicClassAttribute
885 def ham(self):
886 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700887 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
888 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700889 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700890 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
891
Yury Selivanovbf341fb2015-05-21 15:41:57 -0400892 def test_classify_overrides_bool(self):
893 class NoBool(object):
894 def __eq__(self, other):
895 return NoBool()
896
897 def __bool__(self):
898 raise NotImplementedError(
899 "This object does not specify a boolean value")
900
901 class HasNB(object):
902 dd = NoBool()
903
904 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
905 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
906
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700907 def test_classify_metaclass_class_attribute(self):
908 class Meta(type):
909 fish = 'slap'
910 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200911 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700912 class Class(metaclass=Meta):
913 pass
914 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
915 self.assertIn(should_find, inspect.classify_class_attrs(Class))
916
Ethan Furman63c141c2013-10-18 00:27:39 -0700917 def test_classify_VirtualAttribute(self):
918 class Meta(type):
919 def __dir__(cls):
920 return ['__class__', '__module__', '__name__', 'BOOM']
921 def __getattr__(self, name):
922 if name =='BOOM':
923 return 42
924 return super().__getattr(name)
925 class Class(metaclass=Meta):
926 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700927 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700928 self.assertIn(should_find, inspect.classify_class_attrs(Class))
929
930 def test_classify_VirtualAttribute_multi_classes(self):
931 class Meta1(type):
932 def __dir__(cls):
933 return ['__class__', '__module__', '__name__', 'one']
934 def __getattr__(self, name):
935 if name =='one':
936 return 1
937 return super().__getattr__(name)
938 class Meta2(type):
939 def __dir__(cls):
940 return ['__class__', '__module__', '__name__', 'two']
941 def __getattr__(self, name):
942 if name =='two':
943 return 2
944 return super().__getattr__(name)
945 class Meta3(Meta1, Meta2):
946 def __dir__(cls):
947 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
948 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
949 def __getattr__(self, name):
950 if name =='three':
951 return 3
952 return super().__getattr__(name)
953 class Class1(metaclass=Meta1):
954 pass
955 class Class2(Class1, metaclass=Meta3):
956 pass
957
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700958 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
959 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
960 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700961 cca = inspect.classify_class_attrs(Class2)
962 for sf in (should_find1, should_find2, should_find3):
963 self.assertIn(sf, cca)
964
965 def test_classify_class_attrs_with_buggy_dir(self):
966 class M(type):
967 def __dir__(cls):
968 return ['__class__', '__name__', 'missing']
969 class C(metaclass=M):
970 pass
971 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
972 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700973
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100974 def test_getmembers_descriptors(self):
975 class A(object):
976 dd = _BrokenDataDescriptor()
977 md = _BrokenMethodDescriptor()
978
979 def pred_wrapper(pred):
980 # A quick'n'dirty way to discard standard attributes of new-style
981 # classes.
982 class Empty(object):
983 pass
984 def wrapped(x):
985 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
986 return False
987 return pred(x)
988 return wrapped
989
990 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
991 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
992
993 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
994 [('md', A.__dict__['md'])])
995 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
996 [('dd', A.__dict__['dd'])])
997
998 class B(A):
999 pass
1000
1001 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1002 [('md', A.__dict__['md'])])
1003 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1004 [('dd', A.__dict__['dd'])])
1005
Antoine Pitrou0c603812012-01-18 17:40:18 +01001006 def test_getmembers_method(self):
1007 class B:
1008 def f(self):
1009 pass
1010
1011 self.assertIn(('f', B.f), inspect.getmembers(B))
1012 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1013 b = B()
1014 self.assertIn(('f', b.f), inspect.getmembers(b))
1015 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1016
Ethan Furmane03ea372013-09-25 07:14:41 -07001017 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001018 class M(type):
1019 def __getattr__(cls, name):
1020 if name == 'eggs':
1021 return 'scrambled'
1022 return super().__getattr__(name)
1023 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001024 @types.DynamicClassAttribute
1025 def eggs(self):
1026 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001027 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1028 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1029
1030 def test_getmembers_with_buggy_dir(self):
1031 class M(type):
1032 def __dir__(cls):
1033 return ['__class__', '__name__', 'missing']
1034 class C(metaclass=M):
1035 pass
1036 attrs = [a[0] for a in inspect.getmembers(C)]
1037 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001038
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001039
Nick Coghlan2f92e542012-06-23 19:39:55 +10001040_global_ref = object()
1041class TestGetClosureVars(unittest.TestCase):
1042
1043 def test_name_resolution(self):
1044 # Basic test of the 4 different resolution mechanisms
1045 def f(nonlocal_ref):
1046 def g(local_ref):
1047 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1048 return g
1049 _arg = object()
1050 nonlocal_vars = {"nonlocal_ref": _arg}
1051 global_vars = {"_global_ref": _global_ref}
1052 builtin_vars = {"print": print}
1053 unbound_names = {"unbound_ref"}
1054 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1055 builtin_vars, unbound_names)
1056 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1057
1058 def test_generator_closure(self):
1059 def f(nonlocal_ref):
1060 def g(local_ref):
1061 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1062 yield
1063 return g
1064 _arg = object()
1065 nonlocal_vars = {"nonlocal_ref": _arg}
1066 global_vars = {"_global_ref": _global_ref}
1067 builtin_vars = {"print": print}
1068 unbound_names = {"unbound_ref"}
1069 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1070 builtin_vars, unbound_names)
1071 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1072
1073 def test_method_closure(self):
1074 class C:
1075 def f(self, nonlocal_ref):
1076 def g(local_ref):
1077 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1078 return g
1079 _arg = object()
1080 nonlocal_vars = {"nonlocal_ref": _arg}
1081 global_vars = {"_global_ref": _global_ref}
1082 builtin_vars = {"print": print}
1083 unbound_names = {"unbound_ref"}
1084 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1085 builtin_vars, unbound_names)
1086 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1087
1088 def test_nonlocal_vars(self):
1089 # More complex tests of nonlocal resolution
1090 def _nonlocal_vars(f):
1091 return inspect.getclosurevars(f).nonlocals
1092
1093 def make_adder(x):
1094 def add(y):
1095 return x + y
1096 return add
1097
1098 def curry(func, arg1):
1099 return lambda arg2: func(arg1, arg2)
1100
1101 def less_than(a, b):
1102 return a < b
1103
1104 # The infamous Y combinator.
1105 def Y(le):
1106 def g(f):
1107 return le(lambda x: f(f)(x))
1108 Y.g_ref = g
1109 return g(g)
1110
1111 def check_y_combinator(func):
1112 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1113
1114 inc = make_adder(1)
1115 add_two = make_adder(2)
1116 greater_than_five = curry(less_than, 5)
1117
1118 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1119 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1120 self.assertEqual(_nonlocal_vars(greater_than_five),
1121 {'arg1': 5, 'func': less_than})
1122 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1123 {'x': 3})
1124 Y(check_y_combinator)
1125
1126 def test_getclosurevars_empty(self):
1127 def foo(): pass
1128 _empty = inspect.ClosureVars({}, {}, {}, set())
1129 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1130 self.assertEqual(inspect.getclosurevars(foo), _empty)
1131
1132 def test_getclosurevars_error(self):
1133 class T: pass
1134 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1135 self.assertRaises(TypeError, inspect.getclosurevars, list)
1136 self.assertRaises(TypeError, inspect.getclosurevars, {})
1137
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001138 def _private_globals(self):
1139 code = """def f(): print(path)"""
1140 ns = {}
1141 exec(code, ns)
1142 return ns["f"], ns
1143
1144 def test_builtins_fallback(self):
1145 f, ns = self._private_globals()
1146 ns.pop("__builtins__", None)
1147 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1148 self.assertEqual(inspect.getclosurevars(f), expected)
1149
1150 def test_builtins_as_dict(self):
1151 f, ns = self._private_globals()
1152 ns["__builtins__"] = {"path":1}
1153 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1154 self.assertEqual(inspect.getclosurevars(f), expected)
1155
1156 def test_builtins_as_module(self):
1157 f, ns = self._private_globals()
1158 ns["__builtins__"] = os
1159 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1160 self.assertEqual(inspect.getclosurevars(f), expected)
1161
Nick Coghlan2f92e542012-06-23 19:39:55 +10001162
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001163class TestGetcallargsFunctions(unittest.TestCase):
1164
1165 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1166 locs = dict(locs or {}, func=func)
1167 r1 = eval('func(%s)' % call_params_string, None, locs)
1168 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1169 locs)
1170 self.assertEqual(r1, r2)
1171
1172 def assertEqualException(self, func, call_param_string, locs=None):
1173 locs = dict(locs or {}, func=func)
1174 try:
1175 eval('func(%s)' % call_param_string, None, locs)
1176 except Exception as e:
1177 ex1 = e
1178 else:
1179 self.fail('Exception not raised')
1180 try:
1181 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1182 locs)
1183 except Exception as e:
1184 ex2 = e
1185 else:
1186 self.fail('Exception not raised')
1187 self.assertIs(type(ex1), type(ex2))
1188 self.assertEqual(str(ex1), str(ex2))
1189 del ex1, ex2
1190
1191 def makeCallable(self, signature):
1192 """Create a function that returns its locals()"""
1193 code = "lambda %s: locals()"
1194 return eval(code % signature)
1195
1196 def test_plain(self):
1197 f = self.makeCallable('a, b=1')
1198 self.assertEqualCallArgs(f, '2')
1199 self.assertEqualCallArgs(f, '2, 3')
1200 self.assertEqualCallArgs(f, 'a=2')
1201 self.assertEqualCallArgs(f, 'b=3, a=2')
1202 self.assertEqualCallArgs(f, '2, b=3')
1203 # expand *iterable / **mapping
1204 self.assertEqualCallArgs(f, '*(2,)')
1205 self.assertEqualCallArgs(f, '*[2]')
1206 self.assertEqualCallArgs(f, '*(2, 3)')
1207 self.assertEqualCallArgs(f, '*[2, 3]')
1208 self.assertEqualCallArgs(f, '**{"a":2}')
1209 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1210 self.assertEqualCallArgs(f, '2, **{"b":3}')
1211 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1212 # expand UserList / UserDict
1213 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1214 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1215 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1216 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1217 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1218
1219 def test_varargs(self):
1220 f = self.makeCallable('a, b=1, *c')
1221 self.assertEqualCallArgs(f, '2')
1222 self.assertEqualCallArgs(f, '2, 3')
1223 self.assertEqualCallArgs(f, '2, 3, 4')
1224 self.assertEqualCallArgs(f, '*(2,3,4)')
1225 self.assertEqualCallArgs(f, '2, *[3,4]')
1226 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1227
1228 def test_varkw(self):
1229 f = self.makeCallable('a, b=1, **c')
1230 self.assertEqualCallArgs(f, 'a=2')
1231 self.assertEqualCallArgs(f, '2, b=3, c=4')
1232 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1233 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1234 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1235 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1236 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1237 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1238 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1239
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001240 def test_varkw_only(self):
1241 # issue11256:
1242 f = self.makeCallable('**c')
1243 self.assertEqualCallArgs(f, '')
1244 self.assertEqualCallArgs(f, 'a=1')
1245 self.assertEqualCallArgs(f, 'a=1, b=2')
1246 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1247 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1248 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1249
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001250 def test_keyword_only(self):
1251 f = self.makeCallable('a=3, *, c, d=2')
1252 self.assertEqualCallArgs(f, 'c=3')
1253 self.assertEqualCallArgs(f, 'c=3, a=3')
1254 self.assertEqualCallArgs(f, 'a=2, c=4')
1255 self.assertEqualCallArgs(f, '4, c=4')
1256 self.assertEqualException(f, '')
1257 self.assertEqualException(f, '3')
1258 self.assertEqualException(f, 'a=3')
1259 self.assertEqualException(f, 'd=4')
1260
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001261 f = self.makeCallable('*, c, d=2')
1262 self.assertEqualCallArgs(f, 'c=3')
1263 self.assertEqualCallArgs(f, 'c=3, d=4')
1264 self.assertEqualCallArgs(f, 'd=4, c=3')
1265
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001266 def test_multiple_features(self):
1267 f = self.makeCallable('a, b=2, *f, **g')
1268 self.assertEqualCallArgs(f, '2, 3, 7')
1269 self.assertEqualCallArgs(f, '2, 3, x=8')
1270 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1271 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1272 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1273 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1274 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1275 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1276 '(4,[5,6])]), **collections.UserDict('
1277 'y=9, z=10)')
1278
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001279 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1280 self.assertEqualCallArgs(f, '2, 3, x=8')
1281 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1282 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1283 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1284 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1285 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1286 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1287 '(4,[5,6])]), q=0, **collections.UserDict('
1288 'y=9, z=10)')
1289
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001290 def test_errors(self):
1291 f0 = self.makeCallable('')
1292 f1 = self.makeCallable('a, b')
1293 f2 = self.makeCallable('a, b=1')
1294 # f0 takes no arguments
1295 self.assertEqualException(f0, '1')
1296 self.assertEqualException(f0, 'x=1')
1297 self.assertEqualException(f0, '1,x=1')
1298 # f1 takes exactly 2 arguments
1299 self.assertEqualException(f1, '')
1300 self.assertEqualException(f1, '1')
1301 self.assertEqualException(f1, 'a=2')
1302 self.assertEqualException(f1, 'b=3')
1303 # f2 takes at least 1 argument
1304 self.assertEqualException(f2, '')
1305 self.assertEqualException(f2, 'b=3')
1306 for f in f1, f2:
1307 # f1/f2 takes exactly/at most 2 arguments
1308 self.assertEqualException(f, '2, 3, 4')
1309 self.assertEqualException(f, '1, 2, 3, a=1')
1310 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001311 # XXX: success of this one depends on dict order
1312 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001313 # f got an unexpected keyword argument
1314 self.assertEqualException(f, 'c=2')
1315 self.assertEqualException(f, '2, c=3')
1316 self.assertEqualException(f, '2, 3, c=4')
1317 self.assertEqualException(f, '2, c=4, b=3')
1318 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1319 # f got multiple values for keyword argument
1320 self.assertEqualException(f, '1, a=2')
1321 self.assertEqualException(f, '1, **{"a":2}')
1322 self.assertEqualException(f, '1, 2, b=3')
1323 # XXX: Python inconsistency
1324 # - for functions and bound methods: unexpected keyword 'c'
1325 # - for unbound methods: multiple values for keyword 'a'
1326 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001327 # issue11256:
1328 f3 = self.makeCallable('**c')
1329 self.assertEqualException(f3, '1, 2')
1330 self.assertEqualException(f3, '1, 2, a=1, b=2')
1331 f4 = self.makeCallable('*, a, b=0')
1332 self.assertEqualException(f3, '1, 2')
1333 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001334
Yury Selivanov875df202014-03-27 18:23:03 -04001335 # issue #20816: getcallargs() fails to iterate over non-existent
1336 # kwonlydefaults and raises a wrong TypeError
1337 def f5(*, a): pass
1338 with self.assertRaisesRegex(TypeError,
1339 'missing 1 required keyword-only'):
1340 inspect.getcallargs(f5)
1341
1342
Yury Selivanovdccfa132014-03-27 18:42:52 -04001343 # issue20817:
1344 def f6(a, b, c):
1345 pass
1346 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1347 inspect.getcallargs(f6)
1348
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001349class TestGetcallargsMethods(TestGetcallargsFunctions):
1350
1351 def setUp(self):
1352 class Foo(object):
1353 pass
1354 self.cls = Foo
1355 self.inst = Foo()
1356
1357 def makeCallable(self, signature):
1358 assert 'self' not in signature
1359 mk = super(TestGetcallargsMethods, self).makeCallable
1360 self.cls.method = mk('self, ' + signature)
1361 return self.inst.method
1362
1363class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1364
1365 def makeCallable(self, signature):
1366 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1367 return self.cls.method
1368
1369 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1370 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1371 *self._getAssertEqualParams(func, call_params_string, locs))
1372
1373 def assertEqualException(self, func, call_params_string, locs=None):
1374 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1375 *self._getAssertEqualParams(func, call_params_string, locs))
1376
1377 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1378 assert 'inst' not in call_params_string
1379 locs = dict(locs or {}, inst=self.inst)
1380 return (func, 'inst,' + call_params_string, locs)
1381
Michael Foord95fc51d2010-11-20 15:07:30 +00001382
1383class TestGetattrStatic(unittest.TestCase):
1384
1385 def test_basic(self):
1386 class Thing(object):
1387 x = object()
1388
1389 thing = Thing()
1390 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1391 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1392 with self.assertRaises(AttributeError):
1393 inspect.getattr_static(thing, 'y')
1394
1395 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1396
1397 def test_inherited(self):
1398 class Thing(object):
1399 x = object()
1400 class OtherThing(Thing):
1401 pass
1402
1403 something = OtherThing()
1404 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1405
1406 def test_instance_attr(self):
1407 class Thing(object):
1408 x = 2
1409 def __init__(self, x):
1410 self.x = x
1411 thing = Thing(3)
1412 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1413 del thing.x
1414 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1415
1416 def test_property(self):
1417 class Thing(object):
1418 @property
1419 def x(self):
1420 raise AttributeError("I'm pretending not to exist")
1421 thing = Thing()
1422 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1423
Ezio Melotti75cbd732011-04-28 00:59:29 +03001424 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001425 class descriptor(object):
1426 def __get__(*_):
1427 raise AttributeError("I'm pretending not to exist")
1428 desc = descriptor()
1429 class Thing(object):
1430 x = desc
1431 thing = Thing()
1432 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1433
1434 def test_classAttribute(self):
1435 class Thing(object):
1436 x = object()
1437
1438 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1439
Ethan Furmane03ea372013-09-25 07:14:41 -07001440 def test_classVirtualAttribute(self):
1441 class Thing(object):
1442 @types.DynamicClassAttribute
1443 def x(self):
1444 return self._x
1445 _x = object()
1446
1447 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1448
Michael Foord95fc51d2010-11-20 15:07:30 +00001449 def test_inherited_classattribute(self):
1450 class Thing(object):
1451 x = object()
1452 class OtherThing(Thing):
1453 pass
1454
1455 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1456
1457 def test_slots(self):
1458 class Thing(object):
1459 y = 'bar'
1460 __slots__ = ['x']
1461 def __init__(self):
1462 self.x = 'foo'
1463 thing = Thing()
1464 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1465 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1466
1467 del thing.x
1468 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1469
1470 def test_metaclass(self):
1471 class meta(type):
1472 attr = 'foo'
1473 class Thing(object, metaclass=meta):
1474 pass
1475 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1476
1477 class sub(meta):
1478 pass
1479 class OtherThing(object, metaclass=sub):
1480 x = 3
1481 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1482
1483 class OtherOtherThing(OtherThing):
1484 pass
1485 # this test is odd, but it was added as it exposed a bug
1486 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1487
1488 def test_no_dict_no_slots(self):
1489 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1490 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1491
1492 def test_no_dict_no_slots_instance_member(self):
1493 # returns descriptor
1494 with open(__file__) as handle:
1495 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1496
1497 def test_inherited_slots(self):
1498 # returns descriptor
1499 class Thing(object):
1500 __slots__ = ['x']
1501 def __init__(self):
1502 self.x = 'foo'
1503
1504 class OtherThing(Thing):
1505 pass
1506 # it would be nice if this worked...
1507 # we get the descriptor instead of the instance attribute
1508 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1509
1510 def test_descriptor(self):
1511 class descriptor(object):
1512 def __get__(self, instance, owner):
1513 return 3
1514 class Foo(object):
1515 d = descriptor()
1516
1517 foo = Foo()
1518
1519 # for a non data descriptor we return the instance attribute
1520 foo.__dict__['d'] = 1
1521 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1522
1523 # if the descriptor is a data-desciptor we should return the
1524 # descriptor
1525 descriptor.__set__ = lambda s, i, v: None
1526 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1527
1528
1529 def test_metaclass_with_descriptor(self):
1530 class descriptor(object):
1531 def __get__(self, instance, owner):
1532 return 3
1533 class meta(type):
1534 d = descriptor()
1535 class Thing(object, metaclass=meta):
1536 pass
1537 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1538
1539
Michael Foordcc7ebb82010-11-20 16:20:16 +00001540 def test_class_as_property(self):
1541 class Base(object):
1542 foo = 3
1543
1544 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001545 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001546 @property
1547 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001548 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001549 return object
1550
Michael Foord35184ed2010-11-20 16:58:30 +00001551 instance = Something()
1552 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1553 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001554 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1555
Michael Foorde5162652010-11-20 16:40:44 +00001556 def test_mro_as_property(self):
1557 class Meta(type):
1558 @property
1559 def __mro__(self):
1560 return (object,)
1561
1562 class Base(object):
1563 foo = 3
1564
1565 class Something(Base, metaclass=Meta):
1566 pass
1567
1568 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1569 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1570
Michael Foorddcebe0f2011-03-15 19:20:44 -04001571 def test_dict_as_property(self):
1572 test = self
1573 test.called = False
1574
1575 class Foo(dict):
1576 a = 3
1577 @property
1578 def __dict__(self):
1579 test.called = True
1580 return {}
1581
1582 foo = Foo()
1583 foo.a = 4
1584 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1585 self.assertFalse(test.called)
1586
1587 def test_custom_object_dict(self):
1588 test = self
1589 test.called = False
1590
1591 class Custom(dict):
1592 def get(self, key, default=None):
1593 test.called = True
1594 super().get(key, default)
1595
1596 class Foo(object):
1597 a = 3
1598 foo = Foo()
1599 foo.__dict__ = Custom()
1600 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1601 self.assertFalse(test.called)
1602
1603 def test_metaclass_dict_as_property(self):
1604 class Meta(type):
1605 @property
1606 def __dict__(self):
1607 self.executed = True
1608
1609 class Thing(metaclass=Meta):
1610 executed = False
1611
1612 def __init__(self):
1613 self.spam = 42
1614
1615 instance = Thing()
1616 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1617 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001618
Michael Foorda51623b2011-12-18 22:01:40 +00001619 def test_module(self):
1620 sentinel = object()
1621 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1622 sentinel)
1623
Michael Foord3ba95f82011-12-22 01:13:37 +00001624 def test_metaclass_with_metaclass_with_dict_as_property(self):
1625 class MetaMeta(type):
1626 @property
1627 def __dict__(self):
1628 self.executed = True
1629 return dict(spam=42)
1630
1631 class Meta(type, metaclass=MetaMeta):
1632 executed = False
1633
1634 class Thing(metaclass=Meta):
1635 pass
1636
1637 with self.assertRaises(AttributeError):
1638 inspect.getattr_static(Thing, "spam")
1639 self.assertFalse(Thing.executed)
1640
Nick Coghlane0f04652010-11-21 03:44:04 +00001641class TestGetGeneratorState(unittest.TestCase):
1642
1643 def setUp(self):
1644 def number_generator():
1645 for number in range(5):
1646 yield number
1647 self.generator = number_generator()
1648
1649 def _generatorstate(self):
1650 return inspect.getgeneratorstate(self.generator)
1651
1652 def test_created(self):
1653 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1654
1655 def test_suspended(self):
1656 next(self.generator)
1657 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1658
1659 def test_closed_after_exhaustion(self):
1660 for i in self.generator:
1661 pass
1662 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1663
1664 def test_closed_after_immediate_exception(self):
1665 with self.assertRaises(RuntimeError):
1666 self.generator.throw(RuntimeError)
1667 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1668
1669 def test_running(self):
1670 # As mentioned on issue #10220, checking for the RUNNING state only
1671 # makes sense inside the generator itself.
1672 # The following generator checks for this by using the closure's
1673 # reference to self and the generator state checking helper method
1674 def running_check_generator():
1675 for number in range(5):
1676 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1677 yield number
1678 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1679 self.generator = running_check_generator()
1680 # Running up to the first yield
1681 next(self.generator)
1682 # Running after the first yield
1683 next(self.generator)
1684
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001685 def test_easy_debugging(self):
1686 # repr() and str() of a generator state should contain the state name
1687 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1688 for name in names:
1689 state = getattr(inspect, name)
1690 self.assertIn(name, repr(state))
1691 self.assertIn(name, str(state))
1692
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001693 def test_getgeneratorlocals(self):
1694 def each(lst, a=None):
1695 b=(1, 2, 3)
1696 for v in lst:
1697 if v == 3:
1698 c = 12
1699 yield v
1700
1701 numbers = each([1, 2, 3])
1702 self.assertEqual(inspect.getgeneratorlocals(numbers),
1703 {'a': None, 'lst': [1, 2, 3]})
1704 next(numbers)
1705 self.assertEqual(inspect.getgeneratorlocals(numbers),
1706 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1707 'b': (1, 2, 3)})
1708 next(numbers)
1709 self.assertEqual(inspect.getgeneratorlocals(numbers),
1710 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1711 'b': (1, 2, 3)})
1712 next(numbers)
1713 self.assertEqual(inspect.getgeneratorlocals(numbers),
1714 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1715 'b': (1, 2, 3), 'c': 12})
1716 try:
1717 next(numbers)
1718 except StopIteration:
1719 pass
1720 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1721
1722 def test_getgeneratorlocals_empty(self):
1723 def yield_one():
1724 yield 1
1725 one = yield_one()
1726 self.assertEqual(inspect.getgeneratorlocals(one), {})
1727 try:
1728 next(one)
1729 except StopIteration:
1730 pass
1731 self.assertEqual(inspect.getgeneratorlocals(one), {})
1732
1733 def test_getgeneratorlocals_error(self):
1734 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1735 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1736 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1737 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1738
Nick Coghlane0f04652010-11-21 03:44:04 +00001739
Yury Selivanov5376ba92015-06-22 12:19:30 -04001740class TestGetCoroutineState(unittest.TestCase):
1741
1742 def setUp(self):
1743 @types.coroutine
1744 def number_coroutine():
1745 for number in range(5):
1746 yield number
1747 async def coroutine():
1748 await number_coroutine()
1749 self.coroutine = coroutine()
1750
1751 def tearDown(self):
1752 self.coroutine.close()
1753
1754 def _coroutinestate(self):
1755 return inspect.getcoroutinestate(self.coroutine)
1756
1757 def test_created(self):
1758 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1759
1760 def test_suspended(self):
1761 self.coroutine.send(None)
1762 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1763
1764 def test_closed_after_exhaustion(self):
1765 while True:
1766 try:
1767 self.coroutine.send(None)
1768 except StopIteration:
1769 break
1770
1771 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1772
1773 def test_closed_after_immediate_exception(self):
1774 with self.assertRaises(RuntimeError):
1775 self.coroutine.throw(RuntimeError)
1776 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1777
1778 def test_easy_debugging(self):
1779 # repr() and str() of a coroutine state should contain the state name
1780 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1781 for name in names:
1782 state = getattr(inspect, name)
1783 self.assertIn(name, repr(state))
1784 self.assertIn(name, str(state))
1785
1786 def test_getcoroutinelocals(self):
1787 @types.coroutine
1788 def gencoro():
1789 yield
1790
1791 gencoro = gencoro()
1792 async def func(a=None):
1793 b = 'spam'
1794 await gencoro
1795
1796 coro = func()
1797 self.assertEqual(inspect.getcoroutinelocals(coro),
1798 {'a': None, 'gencoro': gencoro})
1799 coro.send(None)
1800 self.assertEqual(inspect.getcoroutinelocals(coro),
1801 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
1802
1803
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001804class MySignature(inspect.Signature):
1805 # Top-level to make it picklable;
1806 # used in test_signature_object_pickle
1807 pass
1808
1809class MyParameter(inspect.Parameter):
1810 # Top-level to make it picklable;
1811 # used in test_signature_object_pickle
1812 pass
1813
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001814
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001815
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001816class TestSignatureObject(unittest.TestCase):
1817 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04001818 def signature(func, **kw):
1819 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001820 return (tuple((param.name,
1821 (... if param.default is param.empty else param.default),
1822 (... if param.annotation is param.empty
1823 else param.annotation),
1824 str(param.kind).lower())
1825 for param in sig.parameters.values()),
1826 (... if sig.return_annotation is sig.empty
1827 else sig.return_annotation))
1828
1829 def test_signature_object(self):
1830 S = inspect.Signature
1831 P = inspect.Parameter
1832
1833 self.assertEqual(str(S()), '()')
1834
Yury Selivanov07a9e452014-01-29 10:58:16 -05001835 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001836 pass
1837 sig = inspect.signature(test)
1838 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001839 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001840 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001841 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001842 args = sig.parameters['args']
1843 ko = sig.parameters['ko']
1844 kwargs = sig.parameters['kwargs']
1845
1846 S((po, pk, args, ko, kwargs))
1847
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001848 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001849 S((pk, po, args, ko, kwargs))
1850
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001851 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001852 S((po, args, pk, ko, kwargs))
1853
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001854 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001855 S((args, po, pk, ko, kwargs))
1856
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001857 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001858 S((po, pk, args, kwargs, ko))
1859
1860 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001861 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001862 S((po, pk, args, kwargs2, ko))
1863
Yury Selivanov07a9e452014-01-29 10:58:16 -05001864 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1865 S((pod, po))
1866
1867 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1868 S((po, pkd, pk))
1869
1870 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1871 S((pkd, pk))
1872
Yury Selivanov374375d2014-03-27 12:41:53 -04001873 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04001874 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04001875
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001876 def test_signature_object_pickle(self):
1877 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1878 foo_partial = functools.partial(foo, a=1)
1879
1880 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001881
1882 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1883 with self.subTest(pickle_ver=ver, subclass=False):
1884 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1885 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001886
1887 # Test that basic sub-classing works
1888 sig = inspect.signature(foo)
1889 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1890 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1891 mysig = MySignature().replace(parameters=myparams.values(),
1892 return_annotation=sig.return_annotation)
1893 self.assertTrue(isinstance(mysig, MySignature))
1894 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1895
1896 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1897 with self.subTest(pickle_ver=ver, subclass=True):
1898 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1899 self.assertEqual(mysig, sig_pickled)
1900 self.assertTrue(isinstance(sig_pickled, MySignature))
1901 self.assertTrue(isinstance(sig_pickled.parameters['z'],
1902 MyParameter))
1903
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001904 def test_signature_immutability(self):
1905 def test(a):
1906 pass
1907 sig = inspect.signature(test)
1908
1909 with self.assertRaises(AttributeError):
1910 sig.foo = 'bar'
1911
1912 with self.assertRaises(TypeError):
1913 sig.parameters['a'] = None
1914
1915 def test_signature_on_noarg(self):
1916 def test():
1917 pass
1918 self.assertEqual(self.signature(test), ((), ...))
1919
1920 def test_signature_on_wargs(self):
1921 def test(a, b:'foo') -> 123:
1922 pass
1923 self.assertEqual(self.signature(test),
1924 ((('a', ..., ..., "positional_or_keyword"),
1925 ('b', ..., 'foo', "positional_or_keyword")),
1926 123))
1927
1928 def test_signature_on_wkwonly(self):
1929 def test(*, a:float, b:str) -> int:
1930 pass
1931 self.assertEqual(self.signature(test),
1932 ((('a', ..., float, "keyword_only"),
1933 ('b', ..., str, "keyword_only")),
1934 int))
1935
1936 def test_signature_on_complex_args(self):
1937 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1938 pass
1939 self.assertEqual(self.signature(test),
1940 ((('a', ..., ..., "positional_or_keyword"),
1941 ('b', 10, 'foo', "positional_or_keyword"),
1942 ('args', ..., 'bar', "var_positional"),
1943 ('spam', ..., 'baz', "keyword_only"),
1944 ('ham', 123, ..., "keyword_only"),
1945 ('kwargs', ..., int, "var_keyword")),
1946 ...))
1947
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001948 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001949 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1950 "Signature information for builtins requires docstrings")
1951 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001952 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001953
Larry Hastings5c661892014-01-24 06:17:25 -08001954 def test_unbound_method(o):
1955 """Use this to test unbound methods (things that should have a self)"""
1956 signature = inspect.signature(o)
1957 self.assertTrue(isinstance(signature, inspect.Signature))
1958 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1959 return signature
1960
1961 def test_callable(o):
1962 """Use this to test bound methods or normal callables (things that don't expect self)"""
1963 signature = inspect.signature(o)
1964 self.assertTrue(isinstance(signature, inspect.Signature))
1965 if signature.parameters:
1966 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1967 return signature
1968
1969 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001970 def p(name): return signature.parameters[name].default
1971 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001972 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001973 self.assertEqual(p('d'), 3.14)
1974 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001975 self.assertEqual(p('n'), None)
1976 self.assertEqual(p('t'), True)
1977 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001978 self.assertEqual(p('local'), 3)
1979 self.assertEqual(p('sys'), sys.maxsize)
1980 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001981
Larry Hastings5c661892014-01-24 06:17:25 -08001982 test_callable(object)
1983
1984 # normal method
1985 # (PyMethodDescr_Type, "method_descriptor")
1986 test_unbound_method(_pickle.Pickler.dump)
1987 d = _pickle.Pickler(io.StringIO())
1988 test_callable(d.dump)
1989
1990 # static method
1991 test_callable(str.maketrans)
1992 test_callable('abc'.maketrans)
1993
1994 # class method
1995 test_callable(dict.fromkeys)
1996 test_callable({}.fromkeys)
1997
1998 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1999 test_unbound_method(type.__call__)
2000 test_unbound_method(int.__add__)
2001 test_callable((3).__add__)
2002
2003 # _PyMethodWrapper_Type
2004 # support for 'method-wrapper'
2005 test_callable(min.__call__)
2006
Larry Hastings2623c8c2014-02-08 22:15:29 -08002007 # This doesn't work now.
2008 # (We don't have a valid signature for "type" in 3.4)
2009 with self.assertRaisesRegex(ValueError, "no signature found"):
2010 class ThisWorksNow:
2011 __call__ = type
2012 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002013
Yury Selivanov056e2652014-03-02 12:25:27 -05002014 # Regression test for issue #20786
2015 test_unbound_method(dict.__delitem__)
2016 test_unbound_method(property.__delete__)
2017
Zachary Ware8ef887c2015-04-13 18:22:35 -05002018 # Regression test for issue #20586
2019 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2020
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002021 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002022 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2023 "Signature information for builtins requires docstrings")
2024 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002025 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002026 func = _testcapi.docstring_with_signature_with_defaults
2027
2028 def decorator(func):
2029 @functools.wraps(func)
2030 def wrapper(*args, **kwargs) -> int:
2031 return func(*args, **kwargs)
2032 return wrapper
2033
2034 decorated_func = decorator(func)
2035
2036 self.assertEqual(inspect.signature(func),
2037 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002038
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002039 def wrapper_like(*args, **kwargs) -> int: pass
2040 self.assertEqual(inspect.signature(decorated_func,
2041 follow_wrapped=False),
2042 inspect.signature(wrapper_like))
2043
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002044 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002045 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002046 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002047 with self.assertRaisesRegex(ValueError,
2048 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002049 inspect.signature(_testcapi.docstring_no_signature)
2050
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002051 with self.assertRaisesRegex(ValueError,
2052 'no signature found for builtin'):
2053 inspect.signature(str)
2054
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002055 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002056 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002057 inspect.signature(42)
2058
Yury Selivanov63da7c72014-01-31 14:48:37 -05002059 def test_signature_from_functionlike_object(self):
2060 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2061 pass
2062
2063 class funclike:
2064 # Has to be callable, and have correct
2065 # __code__, __annotations__, __defaults__, __name__,
2066 # and __kwdefaults__ attributes
2067
2068 def __init__(self, func):
2069 self.__name__ = func.__name__
2070 self.__code__ = func.__code__
2071 self.__annotations__ = func.__annotations__
2072 self.__defaults__ = func.__defaults__
2073 self.__kwdefaults__ = func.__kwdefaults__
2074 self.func = func
2075
2076 def __call__(self, *args, **kwargs):
2077 return self.func(*args, **kwargs)
2078
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002079 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002080
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002081 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002082 self.assertEqual(sig_funclike, sig_func)
2083
2084 sig_funclike = inspect.signature(funclike(func))
2085 self.assertEqual(sig_funclike, sig_func)
2086
2087 # If object is not a duck type of function, then
2088 # signature will try to get a signature for its '__call__'
2089 # method
2090 fl = funclike(func)
2091 del fl.__defaults__
2092 self.assertEqual(self.signature(fl),
2093 ((('args', ..., ..., "var_positional"),
2094 ('kwargs', ..., ..., "var_keyword")),
2095 ...))
2096
Yury Selivanova773de02014-02-21 18:30:53 -05002097 # Test with cython-like builtins:
2098 _orig_isdesc = inspect.ismethoddescriptor
2099 def _isdesc(obj):
2100 if hasattr(obj, '_builtinmock'):
2101 return True
2102 return _orig_isdesc(obj)
2103
2104 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2105 builtin_func = funclike(func)
2106 # Make sure that our mock setup is working
2107 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2108 builtin_func._builtinmock = True
2109 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2110 self.assertEqual(inspect.signature(builtin_func), sig_func)
2111
Yury Selivanov63da7c72014-01-31 14:48:37 -05002112 def test_signature_functionlike_class(self):
2113 # We only want to duck type function-like objects,
2114 # not classes.
2115
2116 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2117 pass
2118
2119 class funclike:
2120 def __init__(self, marker):
2121 pass
2122
2123 __name__ = func.__name__
2124 __code__ = func.__code__
2125 __annotations__ = func.__annotations__
2126 __defaults__ = func.__defaults__
2127 __kwdefaults__ = func.__kwdefaults__
2128
Yury Selivanov63da7c72014-01-31 14:48:37 -05002129 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2130
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002131 def test_signature_on_method(self):
2132 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002133 def __init__(*args):
2134 pass
2135 def m1(self, arg1, arg2=1) -> int:
2136 pass
2137 def m2(*args):
2138 pass
2139 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002140 pass
2141
Yury Selivanov62560fb2014-01-28 12:26:24 -05002142 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002143 ((('arg1', ..., ..., "positional_or_keyword"),
2144 ('arg2', 1, ..., "positional_or_keyword")),
2145 int))
2146
Yury Selivanov62560fb2014-01-28 12:26:24 -05002147 self.assertEqual(self.signature(Test().m2),
2148 ((('args', ..., ..., "var_positional"),),
2149 ...))
2150
2151 self.assertEqual(self.signature(Test),
2152 ((('args', ..., ..., "var_positional"),),
2153 ...))
2154
2155 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2156 self.signature(Test())
2157
Yury Selivanov46c759d2015-05-27 21:56:53 -04002158 def test_signature_wrapped_bound_method(self):
2159 # Issue 24298
2160 class Test:
2161 def m1(self, arg1, arg2=1) -> int:
2162 pass
2163 @functools.wraps(Test().m1)
2164 def m1d(*args, **kwargs):
2165 pass
2166 self.assertEqual(self.signature(m1d),
2167 ((('arg1', ..., ..., "positional_or_keyword"),
2168 ('arg2', 1, ..., "positional_or_keyword")),
2169 int))
2170
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002171 def test_signature_on_classmethod(self):
2172 class Test:
2173 @classmethod
2174 def foo(cls, arg1, *, arg2=1):
2175 pass
2176
2177 meth = Test().foo
2178 self.assertEqual(self.signature(meth),
2179 ((('arg1', ..., ..., "positional_or_keyword"),
2180 ('arg2', 1, ..., "keyword_only")),
2181 ...))
2182
2183 meth = Test.foo
2184 self.assertEqual(self.signature(meth),
2185 ((('arg1', ..., ..., "positional_or_keyword"),
2186 ('arg2', 1, ..., "keyword_only")),
2187 ...))
2188
2189 def test_signature_on_staticmethod(self):
2190 class Test:
2191 @staticmethod
2192 def foo(cls, *, arg):
2193 pass
2194
2195 meth = Test().foo
2196 self.assertEqual(self.signature(meth),
2197 ((('cls', ..., ..., "positional_or_keyword"),
2198 ('arg', ..., ..., "keyword_only")),
2199 ...))
2200
2201 meth = Test.foo
2202 self.assertEqual(self.signature(meth),
2203 ((('cls', ..., ..., "positional_or_keyword"),
2204 ('arg', ..., ..., "keyword_only")),
2205 ...))
2206
2207 def test_signature_on_partial(self):
2208 from functools import partial
2209
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002210 Parameter = inspect.Parameter
2211
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002212 def test():
2213 pass
2214
2215 self.assertEqual(self.signature(partial(test)), ((), ...))
2216
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002217 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002218 inspect.signature(partial(test, 1))
2219
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002220 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002221 inspect.signature(partial(test, a=1))
2222
2223 def test(a, b, *, c, d):
2224 pass
2225
2226 self.assertEqual(self.signature(partial(test)),
2227 ((('a', ..., ..., "positional_or_keyword"),
2228 ('b', ..., ..., "positional_or_keyword"),
2229 ('c', ..., ..., "keyword_only"),
2230 ('d', ..., ..., "keyword_only")),
2231 ...))
2232
2233 self.assertEqual(self.signature(partial(test, 1)),
2234 ((('b', ..., ..., "positional_or_keyword"),
2235 ('c', ..., ..., "keyword_only"),
2236 ('d', ..., ..., "keyword_only")),
2237 ...))
2238
2239 self.assertEqual(self.signature(partial(test, 1, c=2)),
2240 ((('b', ..., ..., "positional_or_keyword"),
2241 ('c', 2, ..., "keyword_only"),
2242 ('d', ..., ..., "keyword_only")),
2243 ...))
2244
2245 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2246 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002247 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002248 ('c', 2, ..., "keyword_only"),
2249 ('d', ..., ..., "keyword_only")),
2250 ...))
2251
2252 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002253 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002254 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002255 ('d', ..., ..., "keyword_only")),
2256 ...))
2257
2258 self.assertEqual(self.signature(partial(test, a=1)),
2259 ((('a', 1, ..., "keyword_only"),
2260 ('b', ..., ..., "keyword_only"),
2261 ('c', ..., ..., "keyword_only"),
2262 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002263 ...))
2264
2265 def test(a, *args, b, **kwargs):
2266 pass
2267
2268 self.assertEqual(self.signature(partial(test, 1)),
2269 ((('args', ..., ..., "var_positional"),
2270 ('b', ..., ..., "keyword_only"),
2271 ('kwargs', ..., ..., "var_keyword")),
2272 ...))
2273
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002274 self.assertEqual(self.signature(partial(test, a=1)),
2275 ((('a', 1, ..., "keyword_only"),
2276 ('b', ..., ..., "keyword_only"),
2277 ('kwargs', ..., ..., "var_keyword")),
2278 ...))
2279
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002280 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2281 ((('args', ..., ..., "var_positional"),
2282 ('b', ..., ..., "keyword_only"),
2283 ('kwargs', ..., ..., "var_keyword")),
2284 ...))
2285
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002286 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2287 ((('args', ..., ..., "var_positional"),
2288 ('b', ..., ..., "keyword_only"),
2289 ('kwargs', ..., ..., "var_keyword")),
2290 ...))
2291
2292 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2293 ((('args', ..., ..., "var_positional"),
2294 ('b', 0, ..., "keyword_only"),
2295 ('kwargs', ..., ..., "var_keyword")),
2296 ...))
2297
2298 self.assertEqual(self.signature(partial(test, b=0)),
2299 ((('a', ..., ..., "positional_or_keyword"),
2300 ('args', ..., ..., "var_positional"),
2301 ('b', 0, ..., "keyword_only"),
2302 ('kwargs', ..., ..., "var_keyword")),
2303 ...))
2304
2305 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2306 ((('a', ..., ..., "positional_or_keyword"),
2307 ('args', ..., ..., "var_positional"),
2308 ('b', 0, ..., "keyword_only"),
2309 ('kwargs', ..., ..., "var_keyword")),
2310 ...))
2311
2312 def test(a, b, c:int) -> 42:
2313 pass
2314
2315 sig = test.__signature__ = inspect.signature(test)
2316
2317 self.assertEqual(self.signature(partial(partial(test, 1))),
2318 ((('b', ..., ..., "positional_or_keyword"),
2319 ('c', ..., int, "positional_or_keyword")),
2320 42))
2321
2322 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2323 ((('c', ..., int, "positional_or_keyword"),),
2324 42))
2325
2326 psig = inspect.signature(partial(partial(test, 1), 2))
2327
2328 def foo(a):
2329 return a
2330 _foo = partial(partial(foo, a=10), a=20)
2331 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002332 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002333 ...))
2334 # check that we don't have any side-effects in signature(),
2335 # and the partial object is still functioning
2336 self.assertEqual(_foo(), 20)
2337
2338 def foo(a, b, c):
2339 return a, b, c
2340 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002341
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002342 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002343 ((('b', 30, ..., "keyword_only"),
2344 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002345 ...))
2346 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002347
2348 def foo(a, b, c, *, d):
2349 return a, b, c, d
2350 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2351 self.assertEqual(self.signature(_foo),
2352 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002353 ('b', 10, ..., "keyword_only"),
2354 ('c', 20, ..., "keyword_only"),
2355 ('d', 30, ..., "keyword_only"),
2356 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002357 ...))
2358 ba = inspect.signature(_foo).bind(a=200, b=11)
2359 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2360
2361 def foo(a=1, b=2, c=3):
2362 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002363 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2364
2365 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002366 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002367
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002368 ba = inspect.signature(_foo).bind(11, 12)
2369 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002370
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002371 ba = inspect.signature(_foo).bind(11, b=12)
2372 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002373
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002374 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002375 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2376
2377 _foo = partial(_foo, b=10, c=20)
2378 ba = inspect.signature(_foo).bind(12)
2379 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2380
2381
2382 def foo(a, b, c, d, **kwargs):
2383 pass
2384 sig = inspect.signature(foo)
2385 params = sig.parameters.copy()
2386 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2387 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2388 foo.__signature__ = inspect.Signature(params.values())
2389 sig = inspect.signature(foo)
2390 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2391
2392 self.assertEqual(self.signature(partial(foo, 1)),
2393 ((('b', ..., ..., 'positional_only'),
2394 ('c', ..., ..., 'positional_or_keyword'),
2395 ('d', ..., ..., 'positional_or_keyword'),
2396 ('kwargs', ..., ..., 'var_keyword')),
2397 ...))
2398
2399 self.assertEqual(self.signature(partial(foo, 1, 2)),
2400 ((('c', ..., ..., 'positional_or_keyword'),
2401 ('d', ..., ..., 'positional_or_keyword'),
2402 ('kwargs', ..., ..., 'var_keyword')),
2403 ...))
2404
2405 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2406 ((('d', ..., ..., 'positional_or_keyword'),
2407 ('kwargs', ..., ..., 'var_keyword')),
2408 ...))
2409
2410 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2411 ((('c', 3, ..., 'keyword_only'),
2412 ('d', ..., ..., 'keyword_only'),
2413 ('kwargs', ..., ..., 'var_keyword')),
2414 ...))
2415
2416 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2417 ((('b', ..., ..., 'positional_only'),
2418 ('c', 3, ..., 'keyword_only'),
2419 ('d', ..., ..., 'keyword_only'),
2420 ('kwargs', ..., ..., 'var_keyword')),
2421 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002422
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002423 def test_signature_on_partialmethod(self):
2424 from functools import partialmethod
2425
2426 class Spam:
2427 def test():
2428 pass
2429 ham = partialmethod(test)
2430
2431 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2432 inspect.signature(Spam.ham)
2433
2434 class Spam:
2435 def test(it, a, *, c) -> 'spam':
2436 pass
2437 ham = partialmethod(test, c=1)
2438
2439 self.assertEqual(self.signature(Spam.ham),
2440 ((('it', ..., ..., 'positional_or_keyword'),
2441 ('a', ..., ..., 'positional_or_keyword'),
2442 ('c', 1, ..., 'keyword_only')),
2443 'spam'))
2444
2445 self.assertEqual(self.signature(Spam().ham),
2446 ((('a', ..., ..., 'positional_or_keyword'),
2447 ('c', 1, ..., 'keyword_only')),
2448 'spam'))
2449
Yury Selivanov0486f812014-01-29 12:18:59 -05002450 def test_signature_on_fake_partialmethod(self):
2451 def foo(a): pass
2452 foo._partialmethod = 'spam'
2453 self.assertEqual(str(inspect.signature(foo)), '(a)')
2454
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002455 def test_signature_on_decorated(self):
2456 import functools
2457
2458 def decorator(func):
2459 @functools.wraps(func)
2460 def wrapper(*args, **kwargs) -> int:
2461 return func(*args, **kwargs)
2462 return wrapper
2463
2464 class Foo:
2465 @decorator
2466 def bar(self, a, b):
2467 pass
2468
2469 self.assertEqual(self.signature(Foo.bar),
2470 ((('self', ..., ..., "positional_or_keyword"),
2471 ('a', ..., ..., "positional_or_keyword"),
2472 ('b', ..., ..., "positional_or_keyword")),
2473 ...))
2474
2475 self.assertEqual(self.signature(Foo().bar),
2476 ((('a', ..., ..., "positional_or_keyword"),
2477 ('b', ..., ..., "positional_or_keyword")),
2478 ...))
2479
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002480 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2481 ((('args', ..., ..., "var_positional"),
2482 ('kwargs', ..., ..., "var_keyword")),
2483 ...)) # functools.wraps will copy __annotations__
2484 # from "func" to "wrapper", hence no
2485 # return_annotation
2486
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002487 # Test that we handle method wrappers correctly
2488 def decorator(func):
2489 @functools.wraps(func)
2490 def wrapper(*args, **kwargs) -> int:
2491 return func(42, *args, **kwargs)
2492 sig = inspect.signature(func)
2493 new_params = tuple(sig.parameters.values())[1:]
2494 wrapper.__signature__ = sig.replace(parameters=new_params)
2495 return wrapper
2496
2497 class Foo:
2498 @decorator
2499 def __call__(self, a, b):
2500 pass
2501
2502 self.assertEqual(self.signature(Foo.__call__),
2503 ((('a', ..., ..., "positional_or_keyword"),
2504 ('b', ..., ..., "positional_or_keyword")),
2505 ...))
2506
2507 self.assertEqual(self.signature(Foo().__call__),
2508 ((('b', ..., ..., "positional_or_keyword"),),
2509 ...))
2510
Nick Coghlane8c45d62013-07-28 20:00:01 +10002511 # Test we handle __signature__ partway down the wrapper stack
2512 def wrapped_foo_call():
2513 pass
2514 wrapped_foo_call.__wrapped__ = Foo.__call__
2515
2516 self.assertEqual(self.signature(wrapped_foo_call),
2517 ((('a', ..., ..., "positional_or_keyword"),
2518 ('b', ..., ..., "positional_or_keyword")),
2519 ...))
2520
2521
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002522 def test_signature_on_class(self):
2523 class C:
2524 def __init__(self, a):
2525 pass
2526
2527 self.assertEqual(self.signature(C),
2528 ((('a', ..., ..., "positional_or_keyword"),),
2529 ...))
2530
2531 class CM(type):
2532 def __call__(cls, a):
2533 pass
2534 class C(metaclass=CM):
2535 def __init__(self, b):
2536 pass
2537
2538 self.assertEqual(self.signature(C),
2539 ((('a', ..., ..., "positional_or_keyword"),),
2540 ...))
2541
2542 class CM(type):
2543 def __new__(mcls, name, bases, dct, *, foo=1):
2544 return super().__new__(mcls, name, bases, dct)
2545 class C(metaclass=CM):
2546 def __init__(self, b):
2547 pass
2548
2549 self.assertEqual(self.signature(C),
2550 ((('b', ..., ..., "positional_or_keyword"),),
2551 ...))
2552
2553 self.assertEqual(self.signature(CM),
2554 ((('name', ..., ..., "positional_or_keyword"),
2555 ('bases', ..., ..., "positional_or_keyword"),
2556 ('dct', ..., ..., "positional_or_keyword"),
2557 ('foo', 1, ..., "keyword_only")),
2558 ...))
2559
2560 class CMM(type):
2561 def __new__(mcls, name, bases, dct, *, foo=1):
2562 return super().__new__(mcls, name, bases, dct)
2563 def __call__(cls, nm, bs, dt):
2564 return type(nm, bs, dt)
2565 class CM(type, metaclass=CMM):
2566 def __new__(mcls, name, bases, dct, *, bar=2):
2567 return super().__new__(mcls, name, bases, dct)
2568 class C(metaclass=CM):
2569 def __init__(self, b):
2570 pass
2571
2572 self.assertEqual(self.signature(CMM),
2573 ((('name', ..., ..., "positional_or_keyword"),
2574 ('bases', ..., ..., "positional_or_keyword"),
2575 ('dct', ..., ..., "positional_or_keyword"),
2576 ('foo', 1, ..., "keyword_only")),
2577 ...))
2578
2579 self.assertEqual(self.signature(CM),
2580 ((('nm', ..., ..., "positional_or_keyword"),
2581 ('bs', ..., ..., "positional_or_keyword"),
2582 ('dt', ..., ..., "positional_or_keyword")),
2583 ...))
2584
2585 self.assertEqual(self.signature(C),
2586 ((('b', ..., ..., "positional_or_keyword"),),
2587 ...))
2588
2589 class CM(type):
2590 def __init__(cls, name, bases, dct, *, bar=2):
2591 return super().__init__(name, bases, dct)
2592 class C(metaclass=CM):
2593 def __init__(self, b):
2594 pass
2595
2596 self.assertEqual(self.signature(CM),
2597 ((('name', ..., ..., "positional_or_keyword"),
2598 ('bases', ..., ..., "positional_or_keyword"),
2599 ('dct', ..., ..., "positional_or_keyword"),
2600 ('bar', 2, ..., "keyword_only")),
2601 ...))
2602
Yury Selivanov145dff82014-02-01 13:49:29 -05002603 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2604 "Signature information for builtins requires docstrings")
2605 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002606 # Test classes without user-defined __init__ or __new__
2607 class C: pass
2608 self.assertEqual(str(inspect.signature(C)), '()')
2609 class D(C): pass
2610 self.assertEqual(str(inspect.signature(D)), '()')
2611
2612 # Test meta-classes without user-defined __init__ or __new__
2613 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002614 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002615 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2616 self.assertEqual(inspect.signature(C), None)
2617 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2618 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002619
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002620 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2621 "Signature information for builtins requires docstrings")
2622 def test_signature_on_builtin_class(self):
2623 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2624 '(file, protocol=None, fix_imports=True)')
2625
2626 class P(_pickle.Pickler): pass
2627 class EmptyTrait: pass
2628 class P2(EmptyTrait, P): pass
2629 self.assertEqual(str(inspect.signature(P)),
2630 '(file, protocol=None, fix_imports=True)')
2631 self.assertEqual(str(inspect.signature(P2)),
2632 '(file, protocol=None, fix_imports=True)')
2633
2634 class P3(P2):
2635 def __init__(self, spam):
2636 pass
2637 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2638
2639 class MetaP(type):
2640 def __call__(cls, foo, bar):
2641 pass
2642 class P4(P2, metaclass=MetaP):
2643 pass
2644 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2645
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002646 def test_signature_on_callable_objects(self):
2647 class Foo:
2648 def __call__(self, a):
2649 pass
2650
2651 self.assertEqual(self.signature(Foo()),
2652 ((('a', ..., ..., "positional_or_keyword"),),
2653 ...))
2654
2655 class Spam:
2656 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002657 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002658 inspect.signature(Spam())
2659
2660 class Bar(Spam, Foo):
2661 pass
2662
2663 self.assertEqual(self.signature(Bar()),
2664 ((('a', ..., ..., "positional_or_keyword"),),
2665 ...))
2666
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002667 class Wrapped:
2668 pass
2669 Wrapped.__wrapped__ = lambda a: None
2670 self.assertEqual(self.signature(Wrapped),
2671 ((('a', ..., ..., "positional_or_keyword"),),
2672 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002673 # wrapper loop:
2674 Wrapped.__wrapped__ = Wrapped
2675 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2676 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002677
2678 def test_signature_on_lambdas(self):
2679 self.assertEqual(self.signature((lambda a=10: a)),
2680 ((('a', 10, ..., "positional_or_keyword"),),
2681 ...))
2682
2683 def test_signature_equality(self):
2684 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002685 self.assertFalse(inspect.signature(foo) == 42)
2686 self.assertTrue(inspect.signature(foo) != 42)
2687 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2688 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002689
2690 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002691 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2692 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002693 self.assertEqual(
2694 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002695
2696 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002697 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2698 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002699 self.assertNotEqual(
2700 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002701
2702 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002703 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2704 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002705 self.assertNotEqual(
2706 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002707
2708 def bar(a, *, b:int=42) -> float: 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, *, c) -> float: 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) -> 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 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002726 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
2727 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002728 self.assertNotEqual(
2729 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002730
2731 def foo(*, a, b, c): pass
2732 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002733 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2734 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002735 self.assertEqual(
2736 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002737
2738 def foo(*, a=1, b, c): pass
2739 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002740 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2741 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002742 self.assertEqual(
2743 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002744
2745 def foo(pos, *, a=1, b, c): pass
2746 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002747 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2748 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002749 self.assertEqual(
2750 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002751
2752 def foo(pos, *, a, b, c): pass
2753 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002754 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2755 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002756 self.assertNotEqual(
2757 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002758
2759 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2760 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002761 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2762 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002763 self.assertEqual(
2764 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002765
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002766 def test_signature_hashable(self):
2767 S = inspect.Signature
2768 P = inspect.Parameter
2769
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002770 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002771 foo_sig = inspect.signature(foo)
2772
2773 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2774
2775 self.assertEqual(hash(foo_sig), hash(manual_sig))
2776 self.assertNotEqual(hash(foo_sig),
2777 hash(manual_sig.replace(return_annotation='spam')))
2778
2779 def bar(a) -> 1: pass
2780 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2781
2782 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002783 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002784 hash(inspect.signature(foo))
2785
2786 def foo(a) -> {}: pass
2787 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2788 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002789
2790 def test_signature_str(self):
2791 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2792 pass
2793 self.assertEqual(str(inspect.signature(foo)),
2794 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2795
2796 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2797 pass
2798 self.assertEqual(str(inspect.signature(foo)),
2799 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2800
2801 def foo():
2802 pass
2803 self.assertEqual(str(inspect.signature(foo)), '()')
2804
2805 def test_signature_str_positional_only(self):
2806 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002807 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002808
2809 def test(a_po, *, b, **kwargs):
2810 return a_po, kwargs
2811
2812 sig = inspect.signature(test)
2813 new_params = list(sig.parameters.values())
2814 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2815 test.__signature__ = sig.replace(parameters=new_params)
2816
2817 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002818 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002819
Yury Selivanov2393dca2014-01-27 15:07:58 -05002820 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2821 '(foo, /)')
2822
2823 self.assertEqual(str(S(parameters=[
2824 P('foo', P.POSITIONAL_ONLY),
2825 P('bar', P.VAR_KEYWORD)])),
2826 '(foo, /, **bar)')
2827
2828 self.assertEqual(str(S(parameters=[
2829 P('foo', P.POSITIONAL_ONLY),
2830 P('bar', P.VAR_POSITIONAL)])),
2831 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002832
2833 def test_signature_replace_anno(self):
2834 def test() -> 42:
2835 pass
2836
2837 sig = inspect.signature(test)
2838 sig = sig.replace(return_annotation=None)
2839 self.assertIs(sig.return_annotation, None)
2840 sig = sig.replace(return_annotation=sig.empty)
2841 self.assertIs(sig.return_annotation, sig.empty)
2842 sig = sig.replace(return_annotation=42)
2843 self.assertEqual(sig.return_annotation, 42)
2844 self.assertEqual(sig, inspect.signature(test))
2845
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002846 def test_signature_on_mangled_parameters(self):
2847 class Spam:
2848 def foo(self, __p1:1=2, *, __p2:2=3):
2849 pass
2850 class Ham(Spam):
2851 pass
2852
2853 self.assertEqual(self.signature(Spam.foo),
2854 ((('self', ..., ..., "positional_or_keyword"),
2855 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2856 ('_Spam__p2', 3, 2, "keyword_only")),
2857 ...))
2858
2859 self.assertEqual(self.signature(Spam.foo),
2860 self.signature(Ham.foo))
2861
Yury Selivanovda396452014-03-27 12:09:24 -04002862 def test_signature_from_callable_python_obj(self):
2863 class MySignature(inspect.Signature): pass
2864 def foo(a, *, b:1): pass
2865 foo_sig = MySignature.from_callable(foo)
2866 self.assertTrue(isinstance(foo_sig, MySignature))
2867
2868 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2869 "Signature information for builtins requires docstrings")
2870 def test_signature_from_callable_builtin_obj(self):
2871 class MySignature(inspect.Signature): pass
2872 sig = MySignature.from_callable(_pickle.Pickler)
2873 self.assertTrue(isinstance(sig, MySignature))
2874
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002875
2876class TestParameterObject(unittest.TestCase):
2877 def test_signature_parameter_kinds(self):
2878 P = inspect.Parameter
2879 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2880 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2881
2882 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2883 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2884
2885 def test_signature_parameter_object(self):
2886 p = inspect.Parameter('foo', default=10,
2887 kind=inspect.Parameter.POSITIONAL_ONLY)
2888 self.assertEqual(p.name, 'foo')
2889 self.assertEqual(p.default, 10)
2890 self.assertIs(p.annotation, p.empty)
2891 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2892
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002893 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002894 inspect.Parameter('foo', default=10, kind='123')
2895
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002896 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002897 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2898
Yury Selivanov2393dca2014-01-27 15:07:58 -05002899 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002900 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2901
Yury Selivanov2393dca2014-01-27 15:07:58 -05002902 with self.assertRaisesRegex(ValueError,
2903 'is not a valid parameter name'):
2904 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2905
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002906 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002907 inspect.Parameter('a', default=42,
2908 kind=inspect.Parameter.VAR_KEYWORD)
2909
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002910 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002911 inspect.Parameter('a', default=42,
2912 kind=inspect.Parameter.VAR_POSITIONAL)
2913
2914 p = inspect.Parameter('a', default=42,
2915 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002916 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002917 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2918
2919 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002920 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002921
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002922 def test_signature_parameter_hashable(self):
2923 P = inspect.Parameter
2924 foo = P('foo', kind=P.POSITIONAL_ONLY)
2925 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
2926 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
2927 default=42)))
2928 self.assertNotEqual(hash(foo),
2929 hash(foo.replace(kind=P.VAR_POSITIONAL)))
2930
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002931 def test_signature_parameter_equality(self):
2932 P = inspect.Parameter
2933 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2934
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002935 self.assertTrue(p == p)
2936 self.assertFalse(p != p)
2937 self.assertFalse(p == 42)
2938 self.assertTrue(p != 42)
2939 self.assertTrue(p == EqualsToAll())
2940 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002941
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002942 self.assertTrue(p == P('foo', default=42,
2943 kind=inspect.Parameter.KEYWORD_ONLY))
2944 self.assertFalse(p != P('foo', default=42,
2945 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002946
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002947 def test_signature_parameter_replace(self):
2948 p = inspect.Parameter('foo', default=42,
2949 kind=inspect.Parameter.KEYWORD_ONLY)
2950
2951 self.assertIsNot(p, p.replace())
2952 self.assertEqual(p, p.replace())
2953
2954 p2 = p.replace(annotation=1)
2955 self.assertEqual(p2.annotation, 1)
2956 p2 = p2.replace(annotation=p2.empty)
2957 self.assertEqual(p, p2)
2958
2959 p2 = p2.replace(name='bar')
2960 self.assertEqual(p2.name, 'bar')
2961 self.assertNotEqual(p2, p)
2962
Yury Selivanov2393dca2014-01-27 15:07:58 -05002963 with self.assertRaisesRegex(ValueError,
2964 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002965 p2 = p2.replace(name=p2.empty)
2966
2967 p2 = p2.replace(name='foo', default=None)
2968 self.assertIs(p2.default, None)
2969 self.assertNotEqual(p2, p)
2970
2971 p2 = p2.replace(name='foo', default=p2.empty)
2972 self.assertIs(p2.default, p2.empty)
2973
2974
2975 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2976 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2977 self.assertNotEqual(p2, p)
2978
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002979 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002980 p2 = p2.replace(kind=p2.empty)
2981
2982 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2983 self.assertEqual(p2, p)
2984
2985 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002986 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2987 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002988
2989 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002990 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002991
2992 with self.assertRaises(AttributeError):
2993 p.foo = 'bar'
2994
2995 with self.assertRaises(AttributeError):
2996 p.kind = 123
2997
2998
2999class TestSignatureBind(unittest.TestCase):
3000 @staticmethod
3001 def call(func, *args, **kwargs):
3002 sig = inspect.signature(func)
3003 ba = sig.bind(*args, **kwargs)
3004 return func(*ba.args, **ba.kwargs)
3005
3006 def test_signature_bind_empty(self):
3007 def test():
3008 return 42
3009
3010 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003011 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003012 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003013 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003014 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003015 with self.assertRaisesRegex(
3016 TypeError, "got an unexpected keyword argument 'spam'"):
3017
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003018 self.call(test, spam=1)
3019
3020 def test_signature_bind_var(self):
3021 def test(*args, **kwargs):
3022 return args, kwargs
3023
3024 self.assertEqual(self.call(test), ((), {}))
3025 self.assertEqual(self.call(test, 1), ((1,), {}))
3026 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3027 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3028 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3029 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3030 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3031 ((1, 2), {'foo': 'bar'}))
3032
3033 def test_signature_bind_just_args(self):
3034 def test(a, b, c):
3035 return a, b, c
3036
3037 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3038
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003039 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003040 self.call(test, 1, 2, 3, 4)
3041
Yury Selivanov86872752015-05-19 00:27:49 -04003042 with self.assertRaisesRegex(TypeError,
3043 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003044 self.call(test, 1)
3045
Yury Selivanov86872752015-05-19 00:27:49 -04003046 with self.assertRaisesRegex(TypeError,
3047 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003048 self.call(test)
3049
3050 def test(a, b, c=10):
3051 return a, b, c
3052 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3053 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3054
3055 def test(a=1, b=2, c=3):
3056 return a, b, c
3057 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3058 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3059 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3060
3061 def test_signature_bind_varargs_order(self):
3062 def test(*args):
3063 return args
3064
3065 self.assertEqual(self.call(test), ())
3066 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3067
3068 def test_signature_bind_args_and_varargs(self):
3069 def test(a, b, c=3, *args):
3070 return a, b, c, args
3071
3072 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3073 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3074 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3075 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3076
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003077 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003078 "multiple values for argument 'c'"):
3079 self.call(test, 1, 2, 3, c=4)
3080
3081 def test_signature_bind_just_kwargs(self):
3082 def test(**kwargs):
3083 return kwargs
3084
3085 self.assertEqual(self.call(test), {})
3086 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3087 {'foo': 'bar', 'spam': 'ham'})
3088
3089 def test_signature_bind_args_and_kwargs(self):
3090 def test(a, b, c=3, **kwargs):
3091 return a, b, c, kwargs
3092
3093 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3094 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3095 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3096 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3097 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3098 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3099 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3100 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3101 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3102 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3103 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3104 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3105 (1, 2, 4, {'foo': 'bar'}))
3106 self.assertEqual(self.call(test, c=5, a=4, b=3),
3107 (4, 3, 5, {}))
3108
3109 def test_signature_bind_kwonly(self):
3110 def test(*, foo):
3111 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003112 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003113 'too many positional arguments'):
3114 self.call(test, 1)
3115 self.assertEqual(self.call(test, foo=1), 1)
3116
3117 def test(a, *, foo=1, bar):
3118 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003119 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003120 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003121 self.call(test, 1)
3122
3123 def test(foo, *, bar):
3124 return foo, bar
3125 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3126 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3127
Yury Selivanov86872752015-05-19 00:27:49 -04003128 with self.assertRaisesRegex(
3129 TypeError, "got an unexpected keyword argument 'spam'"):
3130
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003131 self.call(test, bar=2, foo=1, spam=10)
3132
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003133 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003134 'too many positional arguments'):
3135 self.call(test, 1, 2)
3136
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003137 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003138 'too many positional arguments'):
3139 self.call(test, 1, 2, bar=2)
3140
Yury Selivanov86872752015-05-19 00:27:49 -04003141 with self.assertRaisesRegex(
3142 TypeError, "got an unexpected keyword argument 'spam'"):
3143
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003144 self.call(test, 1, bar=2, spam='ham')
3145
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, **bin):
3151 return foo, bar, bin
3152 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3153 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3154 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3155 (1, 2, {'spam': 'ham'}))
3156 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3157 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003158 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003159 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003160 self.call(test, spam='ham', bar=2)
3161 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3162 (1, 2, {'bin': 1, 'spam': 10}))
3163
3164 def test_signature_bind_arguments(self):
3165 def test(a, *args, b, z=100, **kwargs):
3166 pass
3167 sig = inspect.signature(test)
3168 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3169 # we won't have 'z' argument in the bound arguments object, as we didn't
3170 # pass it to the 'bind'
3171 self.assertEqual(tuple(ba.arguments.items()),
3172 (('a', 10), ('args', (20,)), ('b', 30),
3173 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3174 self.assertEqual(ba.kwargs,
3175 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3176 self.assertEqual(ba.args, (10, 20))
3177
3178 def test_signature_bind_positional_only(self):
3179 P = inspect.Parameter
3180
3181 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3182 return a_po, b_po, c_po, foo, bar, kwargs
3183
3184 sig = inspect.signature(test)
3185 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3186 for name in ('a_po', 'b_po', 'c_po'):
3187 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3188 new_sig = sig.replace(parameters=new_params.values())
3189 test.__signature__ = new_sig
3190
3191 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3192 (1, 2, 4, 5, 6, {}))
3193
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003194 self.assertEqual(self.call(test, 1, 2),
3195 (1, 2, 3, 42, 50, {}))
3196
3197 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3198 (1, 2, 3, 4, 5, {}))
3199
3200 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3201 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3202
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003203 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003204 self.call(test, 1, 2, c_po=4)
3205
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003206 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003207 self.call(test, a_po=1, b_po=2)
3208
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003209 def test_signature_bind_with_self_arg(self):
3210 # Issue #17071: one of the parameters is named "self
3211 def test(a, self, b):
3212 pass
3213 sig = inspect.signature(test)
3214 ba = sig.bind(1, 2, 3)
3215 self.assertEqual(ba.args, (1, 2, 3))
3216 ba = sig.bind(1, self=2, b=3)
3217 self.assertEqual(ba.args, (1, 2, 3))
3218
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003219 def test_signature_bind_vararg_name(self):
3220 def test(a, *args):
3221 return a, args
3222 sig = inspect.signature(test)
3223
Yury Selivanov86872752015-05-19 00:27:49 -04003224 with self.assertRaisesRegex(
3225 TypeError, "got an unexpected keyword argument 'args'"):
3226
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003227 sig.bind(a=0, args=1)
3228
3229 def test(*args, **kwargs):
3230 return args, kwargs
3231 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3232
3233 sig = inspect.signature(test)
3234 ba = sig.bind(args=1)
3235 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3236
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003237
3238class TestBoundArguments(unittest.TestCase):
3239 def test_signature_bound_arguments_unhashable(self):
3240 def foo(a): pass
3241 ba = inspect.signature(foo).bind(1)
3242
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003243 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003244 hash(ba)
3245
3246 def test_signature_bound_arguments_equality(self):
3247 def foo(a): pass
3248 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003249 self.assertTrue(ba == ba)
3250 self.assertFalse(ba != ba)
3251 self.assertTrue(ba == EqualsToAll())
3252 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003253
3254 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003255 self.assertTrue(ba == ba2)
3256 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003257
3258 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003259 self.assertFalse(ba == ba3)
3260 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003261 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003262 self.assertTrue(ba == ba3)
3263 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003264
3265 def bar(b): pass
3266 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003267 self.assertFalse(ba == ba4)
3268 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003269
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003270 def foo(*, a, b): pass
3271 sig = inspect.signature(foo)
3272 ba1 = sig.bind(a=1, b=2)
3273 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003274 self.assertTrue(ba1 == ba2)
3275 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003276
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003277 def test_signature_bound_arguments_pickle(self):
3278 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3279 sig = inspect.signature(foo)
3280 ba = sig.bind(20, 30, z={})
3281
3282 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3283 with self.subTest(pickle_ver=ver):
3284 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3285 self.assertEqual(ba, ba_pickled)
3286
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003287 def test_signature_bound_arguments_repr(self):
3288 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3289 sig = inspect.signature(foo)
3290 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003291 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003292
Yury Selivanovb907a512015-05-16 13:45:09 -04003293 def test_signature_bound_arguments_apply_defaults(self):
3294 def foo(a, b=1, *args, c:1={}, **kw): pass
3295 sig = inspect.signature(foo)
3296
3297 ba = sig.bind(20)
3298 ba.apply_defaults()
3299 self.assertEqual(
3300 list(ba.arguments.items()),
3301 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3302
3303 # Make sure that we preserve the order:
3304 # i.e. 'c' should be *before* 'kw'.
3305 ba = sig.bind(10, 20, 30, d=1)
3306 ba.apply_defaults()
3307 self.assertEqual(
3308 list(ba.arguments.items()),
3309 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3310
3311 # Make sure that BoundArguments produced by bind_partial()
3312 # are supported.
3313 def foo(a, b): pass
3314 sig = inspect.signature(foo)
3315 ba = sig.bind_partial(20)
3316 ba.apply_defaults()
3317 self.assertEqual(
3318 list(ba.arguments.items()),
3319 [('a', 20)])
3320
3321 # Test no args
3322 def foo(): pass
3323 sig = inspect.signature(foo)
3324 ba = sig.bind()
3325 ba.apply_defaults()
3326 self.assertEqual(list(ba.arguments.items()), [])
3327
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003328
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003329class TestSignaturePrivateHelpers(unittest.TestCase):
3330 def test_signature_get_bound_param(self):
3331 getter = inspect._signature_get_bound_param
3332
3333 self.assertEqual(getter('($self)'), 'self')
3334 self.assertEqual(getter('($self, obj)'), 'self')
3335 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3336
Larry Hastings2623c8c2014-02-08 22:15:29 -08003337 def _strip_non_python_syntax(self, input,
3338 clean_signature, self_parameter, last_positional_only):
3339 computed_clean_signature, \
3340 computed_self_parameter, \
3341 computed_last_positional_only = \
3342 inspect._signature_strip_non_python_syntax(input)
3343 self.assertEqual(computed_clean_signature, clean_signature)
3344 self.assertEqual(computed_self_parameter, self_parameter)
3345 self.assertEqual(computed_last_positional_only, last_positional_only)
3346
3347 def test_signature_strip_non_python_syntax(self):
3348 self._strip_non_python_syntax(
3349 "($module, /, path, mode, *, dir_fd=None, " +
3350 "effective_ids=False,\n follow_symlinks=True)",
3351 "(module, path, mode, *, dir_fd=None, " +
3352 "effective_ids=False, follow_symlinks=True)",
3353 0,
3354 0)
3355
3356 self._strip_non_python_syntax(
3357 "($module, word, salt, /)",
3358 "(module, word, salt)",
3359 0,
3360 2)
3361
3362 self._strip_non_python_syntax(
3363 "(x, y=None, z=None, /)",
3364 "(x, y=None, z=None)",
3365 None,
3366 2)
3367
3368 self._strip_non_python_syntax(
3369 "(x, y=None, z=None)",
3370 "(x, y=None, z=None)",
3371 None,
3372 None)
3373
3374 self._strip_non_python_syntax(
3375 "(x,\n y=None,\n z = None )",
3376 "(x, y=None, z=None)",
3377 None,
3378 None)
3379
3380 self._strip_non_python_syntax(
3381 "",
3382 "",
3383 None,
3384 None)
3385
3386 self._strip_non_python_syntax(
3387 None,
3388 None,
3389 None,
3390 None)
3391
Nick Coghlan9c680b02015-04-13 12:54:54 -04003392class TestSignatureDefinitions(unittest.TestCase):
3393 # This test case provides a home for checking that particular APIs
3394 # have signatures available for introspection
3395
3396 @cpython_only
3397 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3398 "Signature information for builtins requires docstrings")
3399 def test_builtins_have_signatures(self):
3400 # This checks all builtin callables in CPython have signatures
3401 # A few have signatures Signature can't yet handle, so we skip those
3402 # since they will have to wait until PEP 457 adds the required
3403 # introspection support to the inspect module
3404 # Some others also haven't been converted yet for various other
3405 # reasons, so we also skip those for the time being, but design
3406 # the test to fail in order to indicate when it needs to be
3407 # updated.
3408 no_signature = set()
3409 # These need PEP 457 groups
3410 needs_groups = {"range", "slice", "dir", "getattr",
3411 "next", "iter", "vars"}
3412 no_signature |= needs_groups
3413 # These need PEP 457 groups or a signature change to accept None
3414 needs_semantic_update = {"round"}
3415 no_signature |= needs_semantic_update
3416 # These need *args support in Argument Clinic
3417 needs_varargs = {"min", "max", "print", "__build_class__"}
3418 no_signature |= needs_varargs
3419 # These simply weren't covered in the initial AC conversion
3420 # for builtin callables
3421 not_converted_yet = {"open", "__import__"}
3422 no_signature |= not_converted_yet
3423 # These builtin types are expected to provide introspection info
3424 types_with_signatures = set()
3425 # Check the signatures we expect to be there
3426 ns = vars(builtins)
3427 for name, obj in sorted(ns.items()):
3428 if not callable(obj):
3429 continue
3430 # The builtin types haven't been converted to AC yet
3431 if isinstance(obj, type) and (name not in types_with_signatures):
3432 # Note that this also skips all the exception types
3433 no_signature.add(name)
3434 if (name in no_signature):
3435 # Not yet converted
3436 continue
3437 with self.subTest(builtin=name):
3438 self.assertIsNotNone(inspect.signature(obj))
3439 # Check callables that haven't been converted don't claim a signature
3440 # This ensures this test will start failing as more signatures are
3441 # added, so the affected items can be moved into the scope of the
3442 # regression test above
3443 for name in no_signature:
3444 with self.subTest(builtin=name):
3445 self.assertIsNone(obj.__text_signature__)
3446
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003447
Nick Coghlane8c45d62013-07-28 20:00:01 +10003448class TestUnwrap(unittest.TestCase):
3449
3450 def test_unwrap_one(self):
3451 def func(a, b):
3452 return a + b
3453 wrapper = functools.lru_cache(maxsize=20)(func)
3454 self.assertIs(inspect.unwrap(wrapper), func)
3455
3456 def test_unwrap_several(self):
3457 def func(a, b):
3458 return a + b
3459 wrapper = func
3460 for __ in range(10):
3461 @functools.wraps(wrapper)
3462 def wrapper():
3463 pass
3464 self.assertIsNot(wrapper.__wrapped__, func)
3465 self.assertIs(inspect.unwrap(wrapper), func)
3466
3467 def test_stop(self):
3468 def func1(a, b):
3469 return a + b
3470 @functools.wraps(func1)
3471 def func2():
3472 pass
3473 @functools.wraps(func2)
3474 def wrapper():
3475 pass
3476 func2.stop_here = 1
3477 unwrapped = inspect.unwrap(wrapper,
3478 stop=(lambda f: hasattr(f, "stop_here")))
3479 self.assertIs(unwrapped, func2)
3480
3481 def test_cycle(self):
3482 def func1(): pass
3483 func1.__wrapped__ = func1
3484 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3485 inspect.unwrap(func1)
3486
3487 def func2(): pass
3488 func2.__wrapped__ = func1
3489 func1.__wrapped__ = func2
3490 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3491 inspect.unwrap(func1)
3492 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3493 inspect.unwrap(func2)
3494
3495 def test_unhashable(self):
3496 def func(): pass
3497 func.__wrapped__ = None
3498 class C:
3499 __hash__ = None
3500 __wrapped__ = func
3501 self.assertIsNone(inspect.unwrap(C()))
3502
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003503class TestMain(unittest.TestCase):
3504 def test_only_source(self):
3505 module = importlib.import_module('unittest')
3506 rc, out, err = assert_python_ok('-m', 'inspect',
3507 'unittest')
3508 lines = out.decode().splitlines()
3509 # ignore the final newline
3510 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3511 self.assertEqual(err, b'')
3512
Yury Selivanov42407ab2014-06-23 10:23:50 -07003513 def test_custom_getattr(self):
3514 def foo():
3515 pass
3516 foo.__signature__ = 42
3517 with self.assertRaises(TypeError):
3518 inspect.signature(foo)
3519
Brett Cannon634a8fc2013-10-02 10:25:42 -04003520 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003521 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003522 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003523 rc, out, err = assert_python_ok('-m', 'inspect',
3524 'concurrent.futures:ThreadPoolExecutor')
3525 lines = out.decode().splitlines()
3526 # ignore the final newline
3527 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003528 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003529 self.assertEqual(err, b'')
3530
3531 def test_builtins(self):
3532 module = importlib.import_module('unittest')
3533 _, out, err = assert_python_failure('-m', 'inspect',
3534 'sys')
3535 lines = err.decode().splitlines()
3536 self.assertEqual(lines, ["Can't get info for builtin modules."])
3537
3538 def test_details(self):
3539 module = importlib.import_module('unittest')
3540 rc, out, err = assert_python_ok('-m', 'inspect',
3541 'unittest', '--details')
3542 output = out.decode()
3543 # Just a quick sanity check on the output
3544 self.assertIn(module.__name__, output)
3545 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003546 if not sys.flags.optimize:
3547 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003548 self.assertEqual(err, b'')
3549
3550
Yury Selivanovef1e7502014-12-08 16:05:34 -05003551class TestReload(unittest.TestCase):
3552
3553 src_before = textwrap.dedent("""\
3554def foo():
3555 print("Bla")
3556 """)
3557
3558 src_after = textwrap.dedent("""\
3559def foo():
3560 print("Oh no!")
3561 """)
3562
3563 def assertInspectEqual(self, path, source):
3564 inspected_src = inspect.getsource(source)
3565 with open(path) as src:
3566 self.assertEqual(
3567 src.read().splitlines(True),
3568 inspected_src.splitlines(True)
3569 )
3570
3571 def test_getsource_reload(self):
3572 # see issue 1218234
3573 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3574 module = importlib.import_module(name)
3575 self.assertInspectEqual(path, module)
3576 with open(path, 'w') as src:
3577 src.write(self.src_after)
3578 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003579
Nick Coghlane8c45d62013-07-28 20:00:01 +10003580
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003581def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003582 run_unittest(
3583 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3584 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3585 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003586 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003587 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003588 TestBoundArguments, TestSignaturePrivateHelpers,
3589 TestSignatureDefinitions,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003590 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
3591 TestGetCoroutineState
Michael Foord95fc51d2010-11-20 15:07:30 +00003592 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003593
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003594if __name__ == "__main__":
3595 test_main()