blob: 671e05a7b5b73b988c2d5ec85c44f711bc08ae49 [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 Storchaka5cf2b722015-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 Storchakaac4bdcc2015-10-29 08:15:50 +0200396 self.assertSourceEqual(mod.StupidGit, 21, 51)
397 self.assertSourceEqual(mod.lobbest, 75, 76)
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
467 def test_decorator_with_lambda(self):
468 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400469
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000470class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000471 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000472 def test_oneline_lambda(self):
473 # Test inspect.getsource with a one-line lambda function.
474 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000475
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000476 def test_threeline_lambda(self):
477 # Test inspect.getsource with a three-line lambda function,
478 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000479 self.assertSourceEqual(mod2.tll, 28, 30)
480
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000481 def test_twoline_indented_lambda(self):
482 # Test inspect.getsource with a two-line lambda function,
483 # where the second line _is_ indented.
484 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000485
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000486 def test_onelinefunc(self):
487 # Test inspect.getsource with a regular one-line function.
488 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000489
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000490 def test_manyargs(self):
491 # Test inspect.getsource with a regular function where
492 # the arguments are on two lines and _not_ indented and
493 # the body on the second line with the last arguments.
494 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000495
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000496 def test_twolinefunc(self):
497 # Test inspect.getsource with a regular function where
498 # the body is on two lines, following the argument list and
499 # continued on the next line by a \\.
500 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000501
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000502 def test_lambda_in_list(self):
503 # Test inspect.getsource with a one-line lambda function
504 # defined in a list, indented.
505 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000506
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000507 def test_anonymous(self):
508 # Test inspect.getsource with a lambda function defined
509 # as argument to another function.
510 self.assertSourceEqual(mod2.anonymous, 55, 55)
511
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000512class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000513 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000514
515 def test_with_comment(self):
516 self.assertSourceEqual(mod2.with_comment, 58, 59)
517
518 def test_multiline_sig(self):
519 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
520
Armin Rigodd5c0232005-09-25 11:45:45 +0000521 def test_nested_class(self):
522 self.assertSourceEqual(mod2.func69().func71, 71, 72)
523
524 def test_one_liner_followed_by_non_name(self):
525 self.assertSourceEqual(mod2.func77, 77, 77)
526
527 def test_one_liner_dedent_non_name(self):
528 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
529
530 def test_with_comment_instead_of_docstring(self):
531 self.assertSourceEqual(mod2.func88, 88, 90)
532
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000533 def test_method_in_dynamic_class(self):
534 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
535
R David Murray32562d72014-10-03 11:15:38 -0400536 # This should not skip for CPython, but might on a repackaged python where
537 # unicodedata is not an external module, or on pypy.
538 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
539 unicodedata.__file__.endswith('.py'),
540 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000541 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200542 self.assertRaises(OSError, inspect.getsource, unicodedata)
543 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000544
R. David Murraya1b37402010-06-17 02:04:29 +0000545 def test_findsource_code_in_linecache(self):
546 lines = ["x=1"]
547 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200548 self.assertRaises(OSError, inspect.findsource, co)
549 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000550 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200551 try:
552 self.assertEqual(inspect.findsource(co), (lines,0))
553 self.assertEqual(inspect.getsource(co), lines[0])
554 finally:
555 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000556
Ezio Melotti1b145922013-03-30 05:17:24 +0200557 def test_findsource_without_filename(self):
558 for fname in ['', '<string>']:
559 co = compile('x=1', fname, "exec")
560 self.assertRaises(IOError, inspect.findsource, co)
561 self.assertRaises(IOError, inspect.getsource, co)
562
Antoine Pitroua8723a02015-04-15 00:41:29 +0200563 def test_getsource_on_method(self):
564 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
565
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300566 def test_nested_func(self):
567 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
568
569
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000570class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400571 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000572 self.tempdir = TESTFN + '_dir'
573 os.mkdir(self.tempdir)
574 with open(os.path.join(self.tempdir,
575 'inspect_fodder3%spy' % os.extsep), 'w') as f:
576 f.write("class X:\n pass # No EOL")
577 with DirsOnSysPath(self.tempdir):
578 import inspect_fodder3 as mod3
579 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400580 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000581
582 def tearDown(self):
583 shutil.rmtree(self.tempdir)
584
585 def test_class(self):
586 self.assertSourceEqual(self.fodderModule.X, 1, 2)
587
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100588
589class _BrokenDataDescriptor(object):
590 """
591 A broken data descriptor. See bug #1785.
592 """
593 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700594 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100595
596 def __set__(*args):
597 raise RuntimeError
598
599 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700600 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100601
602
603class _BrokenMethodDescriptor(object):
604 """
605 A broken method descriptor. See bug #1785.
606 """
607 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700608 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100609
610 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700611 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100612
613
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000614# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000615def attrs_wo_objs(cls):
616 return [t[:3] for t in inspect.classify_class_attrs(cls)]
617
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100618
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000619class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000620 def test_newstyle_mro(self):
621 # The same w/ new-class MRO.
622 class A(object): pass
623 class B(A): pass
624 class C(A): pass
625 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000626
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000627 expected = (D, B, C, A, object)
628 got = inspect.getmro(D)
629 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000630
Christian Heimes3795b532007-11-08 13:48:53 +0000631 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
632 varkw_e=None, defaults_e=None, formatted=None):
Yury Selivanov3cfec2e2015-05-22 11:38:38 -0400633 with self.assertWarns(DeprecationWarning):
634 args, varargs, varkw, defaults = inspect.getargspec(routine)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000635 self.assertEqual(args, args_e)
636 self.assertEqual(varargs, varargs_e)
637 self.assertEqual(varkw, varkw_e)
638 self.assertEqual(defaults, defaults_e)
639 if formatted is not None:
640 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
641 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000642
Christian Heimes3795b532007-11-08 13:48:53 +0000643 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
644 varkw_e=None, defaults_e=None,
645 kwonlyargs_e=[], kwonlydefaults_e=None,
646 ann_e={}, formatted=None):
647 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
648 inspect.getfullargspec(routine)
649 self.assertEqual(args, args_e)
650 self.assertEqual(varargs, varargs_e)
651 self.assertEqual(varkw, varkw_e)
652 self.assertEqual(defaults, defaults_e)
653 self.assertEqual(kwonlyargs, kwonlyargs_e)
654 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
655 self.assertEqual(ann, ann_e)
656 if formatted is not None:
657 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
658 kwonlyargs, kwonlydefaults, ann),
659 formatted)
660
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000661 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000662 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000663
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000664 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000665 ['a', 'b', 'c', 'd', 'e', 'f'],
666 'g', 'h', (3, 4, 5),
667 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000668
Christian Heimes3795b532007-11-08 13:48:53 +0000669 self.assertRaises(ValueError, self.assertArgSpecEquals,
670 mod2.keyworded, [])
671
672 self.assertRaises(ValueError, self.assertArgSpecEquals,
673 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000674 self.assertRaises(ValueError, self.assertArgSpecEquals,
675 mod2.keyword_only_arg, [])
676
Christian Heimes3795b532007-11-08 13:48:53 +0000677
678 def test_getfullargspec(self):
679 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
680 kwonlyargs_e=['arg2'],
681 kwonlydefaults_e={'arg2':1},
682 formatted='(*arg1, arg2=1)')
683
684 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000685 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000686 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000687 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
688 kwonlyargs_e=['arg'],
689 formatted='(*, arg)')
690
Yury Selivanov57d240e2014-02-19 16:27:23 -0500691 def test_argspec_api_ignores_wrapped(self):
692 # Issue 20684: low level introspection API must ignore __wrapped__
693 @functools.wraps(mod.spam)
694 def ham(x, y):
695 pass
696 # Basic check
697 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
698 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
699 self.assertFullArgSpecEquals(functools.partial(ham),
700 ['x', 'y'], formatted='(x, y)')
701 # Other variants
702 def check_method(f):
703 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
704 formatted='(self, x, y)')
705 class C:
706 @functools.wraps(mod.spam)
707 def ham(self, x, y):
708 pass
709 pham = functools.partialmethod(ham)
710 @functools.wraps(mod.spam)
711 def __call__(self, x, y):
712 pass
713 check_method(C())
714 check_method(C.ham)
715 check_method(C().ham)
716 check_method(C.pham)
717 check_method(C().pham)
718
719 class C_new:
720 @functools.wraps(mod.spam)
721 def __new__(self, x, y):
722 pass
723 check_method(C_new)
724
725 class C_init:
726 @functools.wraps(mod.spam)
727 def __init__(self, x, y):
728 pass
729 check_method(C_init)
730
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500731 def test_getfullargspec_signature_attr(self):
732 def test():
733 pass
734 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
735 test.__signature__ = inspect.Signature(parameters=(spam_param,))
736
737 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
738
Yury Selivanov4cb93912014-01-29 11:54:12 -0500739 def test_getfullargspec_signature_annos(self):
740 def test(a:'spam') -> 'ham': pass
741 spec = inspect.getfullargspec(test)
742 self.assertEqual(test.__annotations__, spec.annotations)
743
744 def test(): pass
745 spec = inspect.getfullargspec(test)
746 self.assertEqual(test.__annotations__, spec.annotations)
747
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500748 @unittest.skipIf(MISSING_C_DOCSTRINGS,
749 "Signature information for builtins requires docstrings")
750 def test_getfullargspec_builtin_methods(self):
751 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
752 args_e=['self', 'obj'], formatted='(self, obj)')
753
754 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
755 args_e=['self', 'obj'], formatted='(self, obj)')
756
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500757 self.assertFullArgSpecEquals(
758 os.stat,
759 args_e=['path'],
760 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
761 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
762 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
763
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200764 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500765 @unittest.skipIf(MISSING_C_DOCSTRINGS,
766 "Signature information for builtins requires docstrings")
767 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200768 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500769 builtin = _testcapi.docstring_with_signature_with_defaults
770 spec = inspect.getfullargspec(builtin)
771 self.assertEqual(spec.defaults[0], 'avocado')
772
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200773 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500774 @unittest.skipIf(MISSING_C_DOCSTRINGS,
775 "Signature information for builtins requires docstrings")
776 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200777 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500778 builtin = _testcapi.docstring_no_signature
779 with self.assertRaises(TypeError):
780 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000781
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000782 def test_getargspec_method(self):
783 class A(object):
784 def m(self):
785 pass
786 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000787
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000788 def test_classify_newstyle(self):
789 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000790
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000791 def s(): pass
792 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000793
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000794 def c(cls): pass
795 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000796
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000797 def getp(self): pass
798 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000799
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000800 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000801
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000802 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000803
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000804 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000805
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100806 dd = _BrokenDataDescriptor()
807 md = _BrokenMethodDescriptor()
808
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000809 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500810
811 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
812 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
813
Benjamin Peterson577473f2010-01-19 00:09:57 +0000814 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
815 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
816 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000817 self.assertIn(('m', 'method', A), attrs,
818 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000819 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
820 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100821 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
822 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000823
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000824 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000825
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000826 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000827
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000828 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000829 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
830 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
831 self.assertIn(('p', 'property', A), attrs, 'missing property')
832 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
833 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
834 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100835 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
836 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000837
838
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000839 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000840
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000841 def m(self): pass
842 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000843
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000844 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000845 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
846 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
847 self.assertIn(('p', 'property', A), attrs, 'missing property')
848 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
849 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
850 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100851 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
852 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000853
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000854 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000855
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000856 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000857
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000858 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000859 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
860 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
861 self.assertIn(('p', 'property', A), attrs, 'missing property')
862 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
863 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
864 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100865 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
866 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
867
868 def test_classify_builtin_types(self):
869 # Simple sanity check that all built-in types can have their
870 # attributes classified.
871 for name in dir(__builtins__):
872 builtin = getattr(__builtins__, name)
873 if isinstance(builtin, type):
874 inspect.classify_class_attrs(builtin)
875
Ethan Furman63c141c2013-10-18 00:27:39 -0700876 def test_classify_DynamicClassAttribute(self):
877 class Meta(type):
878 def __getattr__(self, name):
879 if name == 'ham':
880 return 'spam'
881 return super().__getattr__(name)
882 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700883 @types.DynamicClassAttribute
884 def ham(self):
885 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700886 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
887 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700888 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700889 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
890
Yury Selivanovbf341fb2015-05-21 15:41:57 -0400891 def test_classify_overrides_bool(self):
892 class NoBool(object):
893 def __eq__(self, other):
894 return NoBool()
895
896 def __bool__(self):
897 raise NotImplementedError(
898 "This object does not specify a boolean value")
899
900 class HasNB(object):
901 dd = NoBool()
902
903 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
904 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
905
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700906 def test_classify_metaclass_class_attribute(self):
907 class Meta(type):
908 fish = 'slap'
909 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200910 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700911 class Class(metaclass=Meta):
912 pass
913 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
914 self.assertIn(should_find, inspect.classify_class_attrs(Class))
915
Ethan Furman63c141c2013-10-18 00:27:39 -0700916 def test_classify_VirtualAttribute(self):
917 class Meta(type):
918 def __dir__(cls):
919 return ['__class__', '__module__', '__name__', 'BOOM']
920 def __getattr__(self, name):
921 if name =='BOOM':
922 return 42
923 return super().__getattr(name)
924 class Class(metaclass=Meta):
925 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700926 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700927 self.assertIn(should_find, inspect.classify_class_attrs(Class))
928
929 def test_classify_VirtualAttribute_multi_classes(self):
930 class Meta1(type):
931 def __dir__(cls):
932 return ['__class__', '__module__', '__name__', 'one']
933 def __getattr__(self, name):
934 if name =='one':
935 return 1
936 return super().__getattr__(name)
937 class Meta2(type):
938 def __dir__(cls):
939 return ['__class__', '__module__', '__name__', 'two']
940 def __getattr__(self, name):
941 if name =='two':
942 return 2
943 return super().__getattr__(name)
944 class Meta3(Meta1, Meta2):
945 def __dir__(cls):
946 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
947 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
948 def __getattr__(self, name):
949 if name =='three':
950 return 3
951 return super().__getattr__(name)
952 class Class1(metaclass=Meta1):
953 pass
954 class Class2(Class1, metaclass=Meta3):
955 pass
956
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700957 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
958 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
959 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700960 cca = inspect.classify_class_attrs(Class2)
961 for sf in (should_find1, should_find2, should_find3):
962 self.assertIn(sf, cca)
963
964 def test_classify_class_attrs_with_buggy_dir(self):
965 class M(type):
966 def __dir__(cls):
967 return ['__class__', '__name__', 'missing']
968 class C(metaclass=M):
969 pass
970 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
971 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700972
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100973 def test_getmembers_descriptors(self):
974 class A(object):
975 dd = _BrokenDataDescriptor()
976 md = _BrokenMethodDescriptor()
977
978 def pred_wrapper(pred):
979 # A quick'n'dirty way to discard standard attributes of new-style
980 # classes.
981 class Empty(object):
982 pass
983 def wrapped(x):
984 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
985 return False
986 return pred(x)
987 return wrapped
988
989 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
990 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
991
992 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
993 [('md', A.__dict__['md'])])
994 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
995 [('dd', A.__dict__['dd'])])
996
997 class B(A):
998 pass
999
1000 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1001 [('md', A.__dict__['md'])])
1002 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1003 [('dd', A.__dict__['dd'])])
1004
Antoine Pitrou0c603812012-01-18 17:40:18 +01001005 def test_getmembers_method(self):
1006 class B:
1007 def f(self):
1008 pass
1009
1010 self.assertIn(('f', B.f), inspect.getmembers(B))
1011 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1012 b = B()
1013 self.assertIn(('f', b.f), inspect.getmembers(b))
1014 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1015
Ethan Furmane03ea372013-09-25 07:14:41 -07001016 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001017 class M(type):
1018 def __getattr__(cls, name):
1019 if name == 'eggs':
1020 return 'scrambled'
1021 return super().__getattr__(name)
1022 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001023 @types.DynamicClassAttribute
1024 def eggs(self):
1025 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001026 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1027 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1028
1029 def test_getmembers_with_buggy_dir(self):
1030 class M(type):
1031 def __dir__(cls):
1032 return ['__class__', '__name__', 'missing']
1033 class C(metaclass=M):
1034 pass
1035 attrs = [a[0] for a in inspect.getmembers(C)]
1036 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001037
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001038
Nick Coghlan2f92e542012-06-23 19:39:55 +10001039_global_ref = object()
1040class TestGetClosureVars(unittest.TestCase):
1041
1042 def test_name_resolution(self):
1043 # Basic test of the 4 different resolution mechanisms
1044 def f(nonlocal_ref):
1045 def g(local_ref):
1046 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1047 return g
1048 _arg = object()
1049 nonlocal_vars = {"nonlocal_ref": _arg}
1050 global_vars = {"_global_ref": _global_ref}
1051 builtin_vars = {"print": print}
1052 unbound_names = {"unbound_ref"}
1053 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1054 builtin_vars, unbound_names)
1055 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1056
1057 def test_generator_closure(self):
1058 def f(nonlocal_ref):
1059 def g(local_ref):
1060 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1061 yield
1062 return g
1063 _arg = object()
1064 nonlocal_vars = {"nonlocal_ref": _arg}
1065 global_vars = {"_global_ref": _global_ref}
1066 builtin_vars = {"print": print}
1067 unbound_names = {"unbound_ref"}
1068 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1069 builtin_vars, unbound_names)
1070 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1071
1072 def test_method_closure(self):
1073 class C:
1074 def f(self, nonlocal_ref):
1075 def g(local_ref):
1076 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1077 return g
1078 _arg = object()
1079 nonlocal_vars = {"nonlocal_ref": _arg}
1080 global_vars = {"_global_ref": _global_ref}
1081 builtin_vars = {"print": print}
1082 unbound_names = {"unbound_ref"}
1083 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1084 builtin_vars, unbound_names)
1085 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1086
1087 def test_nonlocal_vars(self):
1088 # More complex tests of nonlocal resolution
1089 def _nonlocal_vars(f):
1090 return inspect.getclosurevars(f).nonlocals
1091
1092 def make_adder(x):
1093 def add(y):
1094 return x + y
1095 return add
1096
1097 def curry(func, arg1):
1098 return lambda arg2: func(arg1, arg2)
1099
1100 def less_than(a, b):
1101 return a < b
1102
1103 # The infamous Y combinator.
1104 def Y(le):
1105 def g(f):
1106 return le(lambda x: f(f)(x))
1107 Y.g_ref = g
1108 return g(g)
1109
1110 def check_y_combinator(func):
1111 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1112
1113 inc = make_adder(1)
1114 add_two = make_adder(2)
1115 greater_than_five = curry(less_than, 5)
1116
1117 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1118 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1119 self.assertEqual(_nonlocal_vars(greater_than_five),
1120 {'arg1': 5, 'func': less_than})
1121 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1122 {'x': 3})
1123 Y(check_y_combinator)
1124
1125 def test_getclosurevars_empty(self):
1126 def foo(): pass
1127 _empty = inspect.ClosureVars({}, {}, {}, set())
1128 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1129 self.assertEqual(inspect.getclosurevars(foo), _empty)
1130
1131 def test_getclosurevars_error(self):
1132 class T: pass
1133 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1134 self.assertRaises(TypeError, inspect.getclosurevars, list)
1135 self.assertRaises(TypeError, inspect.getclosurevars, {})
1136
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001137 def _private_globals(self):
1138 code = """def f(): print(path)"""
1139 ns = {}
1140 exec(code, ns)
1141 return ns["f"], ns
1142
1143 def test_builtins_fallback(self):
1144 f, ns = self._private_globals()
1145 ns.pop("__builtins__", None)
1146 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1147 self.assertEqual(inspect.getclosurevars(f), expected)
1148
1149 def test_builtins_as_dict(self):
1150 f, ns = self._private_globals()
1151 ns["__builtins__"] = {"path":1}
1152 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1153 self.assertEqual(inspect.getclosurevars(f), expected)
1154
1155 def test_builtins_as_module(self):
1156 f, ns = self._private_globals()
1157 ns["__builtins__"] = os
1158 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1159 self.assertEqual(inspect.getclosurevars(f), expected)
1160
Nick Coghlan2f92e542012-06-23 19:39:55 +10001161
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001162class TestGetcallargsFunctions(unittest.TestCase):
1163
1164 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1165 locs = dict(locs or {}, func=func)
1166 r1 = eval('func(%s)' % call_params_string, None, locs)
1167 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1168 locs)
1169 self.assertEqual(r1, r2)
1170
1171 def assertEqualException(self, func, call_param_string, locs=None):
1172 locs = dict(locs or {}, func=func)
1173 try:
1174 eval('func(%s)' % call_param_string, None, locs)
1175 except Exception as e:
1176 ex1 = e
1177 else:
1178 self.fail('Exception not raised')
1179 try:
1180 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1181 locs)
1182 except Exception as e:
1183 ex2 = e
1184 else:
1185 self.fail('Exception not raised')
1186 self.assertIs(type(ex1), type(ex2))
1187 self.assertEqual(str(ex1), str(ex2))
1188 del ex1, ex2
1189
1190 def makeCallable(self, signature):
1191 """Create a function that returns its locals()"""
1192 code = "lambda %s: locals()"
1193 return eval(code % signature)
1194
1195 def test_plain(self):
1196 f = self.makeCallable('a, b=1')
1197 self.assertEqualCallArgs(f, '2')
1198 self.assertEqualCallArgs(f, '2, 3')
1199 self.assertEqualCallArgs(f, 'a=2')
1200 self.assertEqualCallArgs(f, 'b=3, a=2')
1201 self.assertEqualCallArgs(f, '2, b=3')
1202 # expand *iterable / **mapping
1203 self.assertEqualCallArgs(f, '*(2,)')
1204 self.assertEqualCallArgs(f, '*[2]')
1205 self.assertEqualCallArgs(f, '*(2, 3)')
1206 self.assertEqualCallArgs(f, '*[2, 3]')
1207 self.assertEqualCallArgs(f, '**{"a":2}')
1208 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1209 self.assertEqualCallArgs(f, '2, **{"b":3}')
1210 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1211 # expand UserList / UserDict
1212 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1213 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1214 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1215 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1216 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1217
1218 def test_varargs(self):
1219 f = self.makeCallable('a, b=1, *c')
1220 self.assertEqualCallArgs(f, '2')
1221 self.assertEqualCallArgs(f, '2, 3')
1222 self.assertEqualCallArgs(f, '2, 3, 4')
1223 self.assertEqualCallArgs(f, '*(2,3,4)')
1224 self.assertEqualCallArgs(f, '2, *[3,4]')
1225 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1226
1227 def test_varkw(self):
1228 f = self.makeCallable('a, b=1, **c')
1229 self.assertEqualCallArgs(f, 'a=2')
1230 self.assertEqualCallArgs(f, '2, b=3, c=4')
1231 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1232 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1233 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1234 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1235 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1236 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1237 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1238
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001239 def test_varkw_only(self):
1240 # issue11256:
1241 f = self.makeCallable('**c')
1242 self.assertEqualCallArgs(f, '')
1243 self.assertEqualCallArgs(f, 'a=1')
1244 self.assertEqualCallArgs(f, 'a=1, b=2')
1245 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1246 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1247 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1248
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001249 def test_keyword_only(self):
1250 f = self.makeCallable('a=3, *, c, d=2')
1251 self.assertEqualCallArgs(f, 'c=3')
1252 self.assertEqualCallArgs(f, 'c=3, a=3')
1253 self.assertEqualCallArgs(f, 'a=2, c=4')
1254 self.assertEqualCallArgs(f, '4, c=4')
1255 self.assertEqualException(f, '')
1256 self.assertEqualException(f, '3')
1257 self.assertEqualException(f, 'a=3')
1258 self.assertEqualException(f, 'd=4')
1259
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001260 f = self.makeCallable('*, c, d=2')
1261 self.assertEqualCallArgs(f, 'c=3')
1262 self.assertEqualCallArgs(f, 'c=3, d=4')
1263 self.assertEqualCallArgs(f, 'd=4, c=3')
1264
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001265 def test_multiple_features(self):
1266 f = self.makeCallable('a, b=2, *f, **g')
1267 self.assertEqualCallArgs(f, '2, 3, 7')
1268 self.assertEqualCallArgs(f, '2, 3, x=8')
1269 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1270 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1271 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1272 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1273 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1274 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1275 '(4,[5,6])]), **collections.UserDict('
1276 'y=9, z=10)')
1277
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001278 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1279 self.assertEqualCallArgs(f, '2, 3, x=8')
1280 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1281 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1282 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1283 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1284 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1285 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1286 '(4,[5,6])]), q=0, **collections.UserDict('
1287 'y=9, z=10)')
1288
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001289 def test_errors(self):
1290 f0 = self.makeCallable('')
1291 f1 = self.makeCallable('a, b')
1292 f2 = self.makeCallable('a, b=1')
1293 # f0 takes no arguments
1294 self.assertEqualException(f0, '1')
1295 self.assertEqualException(f0, 'x=1')
1296 self.assertEqualException(f0, '1,x=1')
1297 # f1 takes exactly 2 arguments
1298 self.assertEqualException(f1, '')
1299 self.assertEqualException(f1, '1')
1300 self.assertEqualException(f1, 'a=2')
1301 self.assertEqualException(f1, 'b=3')
1302 # f2 takes at least 1 argument
1303 self.assertEqualException(f2, '')
1304 self.assertEqualException(f2, 'b=3')
1305 for f in f1, f2:
1306 # f1/f2 takes exactly/at most 2 arguments
1307 self.assertEqualException(f, '2, 3, 4')
1308 self.assertEqualException(f, '1, 2, 3, a=1')
1309 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001310 # XXX: success of this one depends on dict order
1311 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001312 # f got an unexpected keyword argument
1313 self.assertEqualException(f, 'c=2')
1314 self.assertEqualException(f, '2, c=3')
1315 self.assertEqualException(f, '2, 3, c=4')
1316 self.assertEqualException(f, '2, c=4, b=3')
1317 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1318 # f got multiple values for keyword argument
1319 self.assertEqualException(f, '1, a=2')
1320 self.assertEqualException(f, '1, **{"a":2}')
1321 self.assertEqualException(f, '1, 2, b=3')
1322 # XXX: Python inconsistency
1323 # - for functions and bound methods: unexpected keyword 'c'
1324 # - for unbound methods: multiple values for keyword 'a'
1325 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001326 # issue11256:
1327 f3 = self.makeCallable('**c')
1328 self.assertEqualException(f3, '1, 2')
1329 self.assertEqualException(f3, '1, 2, a=1, b=2')
1330 f4 = self.makeCallable('*, a, b=0')
1331 self.assertEqualException(f3, '1, 2')
1332 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001333
Yury Selivanov875df202014-03-27 18:23:03 -04001334 # issue #20816: getcallargs() fails to iterate over non-existent
1335 # kwonlydefaults and raises a wrong TypeError
1336 def f5(*, a): pass
1337 with self.assertRaisesRegex(TypeError,
1338 'missing 1 required keyword-only'):
1339 inspect.getcallargs(f5)
1340
1341
Yury Selivanovdccfa132014-03-27 18:42:52 -04001342 # issue20817:
1343 def f6(a, b, c):
1344 pass
1345 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1346 inspect.getcallargs(f6)
1347
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001348class TestGetcallargsMethods(TestGetcallargsFunctions):
1349
1350 def setUp(self):
1351 class Foo(object):
1352 pass
1353 self.cls = Foo
1354 self.inst = Foo()
1355
1356 def makeCallable(self, signature):
1357 assert 'self' not in signature
1358 mk = super(TestGetcallargsMethods, self).makeCallable
1359 self.cls.method = mk('self, ' + signature)
1360 return self.inst.method
1361
1362class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1363
1364 def makeCallable(self, signature):
1365 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1366 return self.cls.method
1367
1368 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1369 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1370 *self._getAssertEqualParams(func, call_params_string, locs))
1371
1372 def assertEqualException(self, func, call_params_string, locs=None):
1373 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1374 *self._getAssertEqualParams(func, call_params_string, locs))
1375
1376 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1377 assert 'inst' not in call_params_string
1378 locs = dict(locs or {}, inst=self.inst)
1379 return (func, 'inst,' + call_params_string, locs)
1380
Michael Foord95fc51d2010-11-20 15:07:30 +00001381
1382class TestGetattrStatic(unittest.TestCase):
1383
1384 def test_basic(self):
1385 class Thing(object):
1386 x = object()
1387
1388 thing = Thing()
1389 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1390 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1391 with self.assertRaises(AttributeError):
1392 inspect.getattr_static(thing, 'y')
1393
1394 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1395
1396 def test_inherited(self):
1397 class Thing(object):
1398 x = object()
1399 class OtherThing(Thing):
1400 pass
1401
1402 something = OtherThing()
1403 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1404
1405 def test_instance_attr(self):
1406 class Thing(object):
1407 x = 2
1408 def __init__(self, x):
1409 self.x = x
1410 thing = Thing(3)
1411 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1412 del thing.x
1413 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1414
1415 def test_property(self):
1416 class Thing(object):
1417 @property
1418 def x(self):
1419 raise AttributeError("I'm pretending not to exist")
1420 thing = Thing()
1421 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1422
Ezio Melotti75cbd732011-04-28 00:59:29 +03001423 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001424 class descriptor(object):
1425 def __get__(*_):
1426 raise AttributeError("I'm pretending not to exist")
1427 desc = descriptor()
1428 class Thing(object):
1429 x = desc
1430 thing = Thing()
1431 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1432
1433 def test_classAttribute(self):
1434 class Thing(object):
1435 x = object()
1436
1437 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1438
Ethan Furmane03ea372013-09-25 07:14:41 -07001439 def test_classVirtualAttribute(self):
1440 class Thing(object):
1441 @types.DynamicClassAttribute
1442 def x(self):
1443 return self._x
1444 _x = object()
1445
1446 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1447
Michael Foord95fc51d2010-11-20 15:07:30 +00001448 def test_inherited_classattribute(self):
1449 class Thing(object):
1450 x = object()
1451 class OtherThing(Thing):
1452 pass
1453
1454 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1455
1456 def test_slots(self):
1457 class Thing(object):
1458 y = 'bar'
1459 __slots__ = ['x']
1460 def __init__(self):
1461 self.x = 'foo'
1462 thing = Thing()
1463 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1464 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1465
1466 del thing.x
1467 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1468
1469 def test_metaclass(self):
1470 class meta(type):
1471 attr = 'foo'
1472 class Thing(object, metaclass=meta):
1473 pass
1474 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1475
1476 class sub(meta):
1477 pass
1478 class OtherThing(object, metaclass=sub):
1479 x = 3
1480 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1481
1482 class OtherOtherThing(OtherThing):
1483 pass
1484 # this test is odd, but it was added as it exposed a bug
1485 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1486
1487 def test_no_dict_no_slots(self):
1488 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1489 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1490
1491 def test_no_dict_no_slots_instance_member(self):
1492 # returns descriptor
1493 with open(__file__) as handle:
1494 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1495
1496 def test_inherited_slots(self):
1497 # returns descriptor
1498 class Thing(object):
1499 __slots__ = ['x']
1500 def __init__(self):
1501 self.x = 'foo'
1502
1503 class OtherThing(Thing):
1504 pass
1505 # it would be nice if this worked...
1506 # we get the descriptor instead of the instance attribute
1507 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1508
1509 def test_descriptor(self):
1510 class descriptor(object):
1511 def __get__(self, instance, owner):
1512 return 3
1513 class Foo(object):
1514 d = descriptor()
1515
1516 foo = Foo()
1517
1518 # for a non data descriptor we return the instance attribute
1519 foo.__dict__['d'] = 1
1520 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1521
1522 # if the descriptor is a data-desciptor we should return the
1523 # descriptor
1524 descriptor.__set__ = lambda s, i, v: None
1525 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1526
1527
1528 def test_metaclass_with_descriptor(self):
1529 class descriptor(object):
1530 def __get__(self, instance, owner):
1531 return 3
1532 class meta(type):
1533 d = descriptor()
1534 class Thing(object, metaclass=meta):
1535 pass
1536 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1537
1538
Michael Foordcc7ebb82010-11-20 16:20:16 +00001539 def test_class_as_property(self):
1540 class Base(object):
1541 foo = 3
1542
1543 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001544 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001545 @property
1546 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001547 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001548 return object
1549
Michael Foord35184ed2010-11-20 16:58:30 +00001550 instance = Something()
1551 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1552 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001553 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1554
Michael Foorde5162652010-11-20 16:40:44 +00001555 def test_mro_as_property(self):
1556 class Meta(type):
1557 @property
1558 def __mro__(self):
1559 return (object,)
1560
1561 class Base(object):
1562 foo = 3
1563
1564 class Something(Base, metaclass=Meta):
1565 pass
1566
1567 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1568 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1569
Michael Foorddcebe0f2011-03-15 19:20:44 -04001570 def test_dict_as_property(self):
1571 test = self
1572 test.called = False
1573
1574 class Foo(dict):
1575 a = 3
1576 @property
1577 def __dict__(self):
1578 test.called = True
1579 return {}
1580
1581 foo = Foo()
1582 foo.a = 4
1583 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1584 self.assertFalse(test.called)
1585
1586 def test_custom_object_dict(self):
1587 test = self
1588 test.called = False
1589
1590 class Custom(dict):
1591 def get(self, key, default=None):
1592 test.called = True
1593 super().get(key, default)
1594
1595 class Foo(object):
1596 a = 3
1597 foo = Foo()
1598 foo.__dict__ = Custom()
1599 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1600 self.assertFalse(test.called)
1601
1602 def test_metaclass_dict_as_property(self):
1603 class Meta(type):
1604 @property
1605 def __dict__(self):
1606 self.executed = True
1607
1608 class Thing(metaclass=Meta):
1609 executed = False
1610
1611 def __init__(self):
1612 self.spam = 42
1613
1614 instance = Thing()
1615 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1616 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001617
Michael Foorda51623b2011-12-18 22:01:40 +00001618 def test_module(self):
1619 sentinel = object()
1620 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1621 sentinel)
1622
Michael Foord3ba95f82011-12-22 01:13:37 +00001623 def test_metaclass_with_metaclass_with_dict_as_property(self):
1624 class MetaMeta(type):
1625 @property
1626 def __dict__(self):
1627 self.executed = True
1628 return dict(spam=42)
1629
1630 class Meta(type, metaclass=MetaMeta):
1631 executed = False
1632
1633 class Thing(metaclass=Meta):
1634 pass
1635
1636 with self.assertRaises(AttributeError):
1637 inspect.getattr_static(Thing, "spam")
1638 self.assertFalse(Thing.executed)
1639
Nick Coghlane0f04652010-11-21 03:44:04 +00001640class TestGetGeneratorState(unittest.TestCase):
1641
1642 def setUp(self):
1643 def number_generator():
1644 for number in range(5):
1645 yield number
1646 self.generator = number_generator()
1647
1648 def _generatorstate(self):
1649 return inspect.getgeneratorstate(self.generator)
1650
1651 def test_created(self):
1652 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1653
1654 def test_suspended(self):
1655 next(self.generator)
1656 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1657
1658 def test_closed_after_exhaustion(self):
1659 for i in self.generator:
1660 pass
1661 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1662
1663 def test_closed_after_immediate_exception(self):
1664 with self.assertRaises(RuntimeError):
1665 self.generator.throw(RuntimeError)
1666 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1667
1668 def test_running(self):
1669 # As mentioned on issue #10220, checking for the RUNNING state only
1670 # makes sense inside the generator itself.
1671 # The following generator checks for this by using the closure's
1672 # reference to self and the generator state checking helper method
1673 def running_check_generator():
1674 for number in range(5):
1675 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1676 yield number
1677 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1678 self.generator = running_check_generator()
1679 # Running up to the first yield
1680 next(self.generator)
1681 # Running after the first yield
1682 next(self.generator)
1683
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001684 def test_easy_debugging(self):
1685 # repr() and str() of a generator state should contain the state name
1686 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1687 for name in names:
1688 state = getattr(inspect, name)
1689 self.assertIn(name, repr(state))
1690 self.assertIn(name, str(state))
1691
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001692 def test_getgeneratorlocals(self):
1693 def each(lst, a=None):
1694 b=(1, 2, 3)
1695 for v in lst:
1696 if v == 3:
1697 c = 12
1698 yield v
1699
1700 numbers = each([1, 2, 3])
1701 self.assertEqual(inspect.getgeneratorlocals(numbers),
1702 {'a': None, 'lst': [1, 2, 3]})
1703 next(numbers)
1704 self.assertEqual(inspect.getgeneratorlocals(numbers),
1705 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1706 'b': (1, 2, 3)})
1707 next(numbers)
1708 self.assertEqual(inspect.getgeneratorlocals(numbers),
1709 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1710 'b': (1, 2, 3)})
1711 next(numbers)
1712 self.assertEqual(inspect.getgeneratorlocals(numbers),
1713 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1714 'b': (1, 2, 3), 'c': 12})
1715 try:
1716 next(numbers)
1717 except StopIteration:
1718 pass
1719 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1720
1721 def test_getgeneratorlocals_empty(self):
1722 def yield_one():
1723 yield 1
1724 one = yield_one()
1725 self.assertEqual(inspect.getgeneratorlocals(one), {})
1726 try:
1727 next(one)
1728 except StopIteration:
1729 pass
1730 self.assertEqual(inspect.getgeneratorlocals(one), {})
1731
1732 def test_getgeneratorlocals_error(self):
1733 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1734 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1735 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1736 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1737
Nick Coghlane0f04652010-11-21 03:44:04 +00001738
Yury Selivanov5376ba92015-06-22 12:19:30 -04001739class TestGetCoroutineState(unittest.TestCase):
1740
1741 def setUp(self):
1742 @types.coroutine
1743 def number_coroutine():
1744 for number in range(5):
1745 yield number
1746 async def coroutine():
1747 await number_coroutine()
1748 self.coroutine = coroutine()
1749
1750 def tearDown(self):
1751 self.coroutine.close()
1752
1753 def _coroutinestate(self):
1754 return inspect.getcoroutinestate(self.coroutine)
1755
1756 def test_created(self):
1757 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1758
1759 def test_suspended(self):
1760 self.coroutine.send(None)
1761 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1762
1763 def test_closed_after_exhaustion(self):
1764 while True:
1765 try:
1766 self.coroutine.send(None)
1767 except StopIteration:
1768 break
1769
1770 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1771
1772 def test_closed_after_immediate_exception(self):
1773 with self.assertRaises(RuntimeError):
1774 self.coroutine.throw(RuntimeError)
1775 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1776
1777 def test_easy_debugging(self):
1778 # repr() and str() of a coroutine state should contain the state name
1779 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1780 for name in names:
1781 state = getattr(inspect, name)
1782 self.assertIn(name, repr(state))
1783 self.assertIn(name, str(state))
1784
1785 def test_getcoroutinelocals(self):
1786 @types.coroutine
1787 def gencoro():
1788 yield
1789
1790 gencoro = gencoro()
1791 async def func(a=None):
1792 b = 'spam'
1793 await gencoro
1794
1795 coro = func()
1796 self.assertEqual(inspect.getcoroutinelocals(coro),
1797 {'a': None, 'gencoro': gencoro})
1798 coro.send(None)
1799 self.assertEqual(inspect.getcoroutinelocals(coro),
1800 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
1801
1802
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001803class MySignature(inspect.Signature):
1804 # Top-level to make it picklable;
1805 # used in test_signature_object_pickle
1806 pass
1807
1808class MyParameter(inspect.Parameter):
1809 # Top-level to make it picklable;
1810 # used in test_signature_object_pickle
1811 pass
1812
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001813
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001814
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001815class TestSignatureObject(unittest.TestCase):
1816 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04001817 def signature(func, **kw):
1818 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001819 return (tuple((param.name,
1820 (... if param.default is param.empty else param.default),
1821 (... if param.annotation is param.empty
1822 else param.annotation),
1823 str(param.kind).lower())
1824 for param in sig.parameters.values()),
1825 (... if sig.return_annotation is sig.empty
1826 else sig.return_annotation))
1827
1828 def test_signature_object(self):
1829 S = inspect.Signature
1830 P = inspect.Parameter
1831
1832 self.assertEqual(str(S()), '()')
1833
Yury Selivanov07a9e452014-01-29 10:58:16 -05001834 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001835 pass
1836 sig = inspect.signature(test)
1837 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001838 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001839 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001840 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001841 args = sig.parameters['args']
1842 ko = sig.parameters['ko']
1843 kwargs = sig.parameters['kwargs']
1844
1845 S((po, pk, args, ko, kwargs))
1846
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001847 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001848 S((pk, po, args, ko, kwargs))
1849
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001850 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001851 S((po, args, pk, ko, kwargs))
1852
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001853 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001854 S((args, po, pk, ko, kwargs))
1855
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001856 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001857 S((po, pk, args, kwargs, ko))
1858
1859 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001860 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001861 S((po, pk, args, kwargs2, ko))
1862
Yury Selivanov07a9e452014-01-29 10:58:16 -05001863 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1864 S((pod, po))
1865
1866 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1867 S((po, pkd, pk))
1868
1869 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1870 S((pkd, pk))
1871
Yury Selivanov374375d2014-03-27 12:41:53 -04001872 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04001873 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04001874
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001875 def test_signature_object_pickle(self):
1876 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1877 foo_partial = functools.partial(foo, a=1)
1878
1879 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001880
1881 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1882 with self.subTest(pickle_ver=ver, subclass=False):
1883 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1884 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001885
1886 # Test that basic sub-classing works
1887 sig = inspect.signature(foo)
1888 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1889 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1890 mysig = MySignature().replace(parameters=myparams.values(),
1891 return_annotation=sig.return_annotation)
1892 self.assertTrue(isinstance(mysig, MySignature))
1893 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1894
1895 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1896 with self.subTest(pickle_ver=ver, subclass=True):
1897 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1898 self.assertEqual(mysig, sig_pickled)
1899 self.assertTrue(isinstance(sig_pickled, MySignature))
1900 self.assertTrue(isinstance(sig_pickled.parameters['z'],
1901 MyParameter))
1902
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001903 def test_signature_immutability(self):
1904 def test(a):
1905 pass
1906 sig = inspect.signature(test)
1907
1908 with self.assertRaises(AttributeError):
1909 sig.foo = 'bar'
1910
1911 with self.assertRaises(TypeError):
1912 sig.parameters['a'] = None
1913
1914 def test_signature_on_noarg(self):
1915 def test():
1916 pass
1917 self.assertEqual(self.signature(test), ((), ...))
1918
1919 def test_signature_on_wargs(self):
1920 def test(a, b:'foo') -> 123:
1921 pass
1922 self.assertEqual(self.signature(test),
1923 ((('a', ..., ..., "positional_or_keyword"),
1924 ('b', ..., 'foo', "positional_or_keyword")),
1925 123))
1926
1927 def test_signature_on_wkwonly(self):
1928 def test(*, a:float, b:str) -> int:
1929 pass
1930 self.assertEqual(self.signature(test),
1931 ((('a', ..., float, "keyword_only"),
1932 ('b', ..., str, "keyword_only")),
1933 int))
1934
1935 def test_signature_on_complex_args(self):
1936 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1937 pass
1938 self.assertEqual(self.signature(test),
1939 ((('a', ..., ..., "positional_or_keyword"),
1940 ('b', 10, 'foo', "positional_or_keyword"),
1941 ('args', ..., 'bar', "var_positional"),
1942 ('spam', ..., 'baz', "keyword_only"),
1943 ('ham', 123, ..., "keyword_only"),
1944 ('kwargs', ..., int, "var_keyword")),
1945 ...))
1946
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001947 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001948 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1949 "Signature information for builtins requires docstrings")
1950 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001951 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001952
Larry Hastings5c661892014-01-24 06:17:25 -08001953 def test_unbound_method(o):
1954 """Use this to test unbound methods (things that should have a self)"""
1955 signature = inspect.signature(o)
1956 self.assertTrue(isinstance(signature, inspect.Signature))
1957 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1958 return signature
1959
1960 def test_callable(o):
1961 """Use this to test bound methods or normal callables (things that don't expect self)"""
1962 signature = inspect.signature(o)
1963 self.assertTrue(isinstance(signature, inspect.Signature))
1964 if signature.parameters:
1965 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1966 return signature
1967
1968 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001969 def p(name): return signature.parameters[name].default
1970 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001971 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001972 self.assertEqual(p('d'), 3.14)
1973 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001974 self.assertEqual(p('n'), None)
1975 self.assertEqual(p('t'), True)
1976 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001977 self.assertEqual(p('local'), 3)
1978 self.assertEqual(p('sys'), sys.maxsize)
1979 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001980
Larry Hastings5c661892014-01-24 06:17:25 -08001981 test_callable(object)
1982
1983 # normal method
1984 # (PyMethodDescr_Type, "method_descriptor")
1985 test_unbound_method(_pickle.Pickler.dump)
1986 d = _pickle.Pickler(io.StringIO())
1987 test_callable(d.dump)
1988
1989 # static method
1990 test_callable(str.maketrans)
1991 test_callable('abc'.maketrans)
1992
1993 # class method
1994 test_callable(dict.fromkeys)
1995 test_callable({}.fromkeys)
1996
1997 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1998 test_unbound_method(type.__call__)
1999 test_unbound_method(int.__add__)
2000 test_callable((3).__add__)
2001
2002 # _PyMethodWrapper_Type
2003 # support for 'method-wrapper'
2004 test_callable(min.__call__)
2005
Larry Hastings2623c8c2014-02-08 22:15:29 -08002006 # This doesn't work now.
2007 # (We don't have a valid signature for "type" in 3.4)
2008 with self.assertRaisesRegex(ValueError, "no signature found"):
2009 class ThisWorksNow:
2010 __call__ = type
2011 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002012
Yury Selivanov056e2652014-03-02 12:25:27 -05002013 # Regression test for issue #20786
2014 test_unbound_method(dict.__delitem__)
2015 test_unbound_method(property.__delete__)
2016
Zachary Ware8ef887c2015-04-13 18:22:35 -05002017 # Regression test for issue #20586
2018 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2019
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002020 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002021 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2022 "Signature information for builtins requires docstrings")
2023 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002024 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002025 func = _testcapi.docstring_with_signature_with_defaults
2026
2027 def decorator(func):
2028 @functools.wraps(func)
2029 def wrapper(*args, **kwargs) -> int:
2030 return func(*args, **kwargs)
2031 return wrapper
2032
2033 decorated_func = decorator(func)
2034
2035 self.assertEqual(inspect.signature(func),
2036 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002037
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002038 def wrapper_like(*args, **kwargs) -> int: pass
2039 self.assertEqual(inspect.signature(decorated_func,
2040 follow_wrapped=False),
2041 inspect.signature(wrapper_like))
2042
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002043 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002044 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002045 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002046 with self.assertRaisesRegex(ValueError,
2047 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002048 inspect.signature(_testcapi.docstring_no_signature)
2049
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002050 with self.assertRaisesRegex(ValueError,
2051 'no signature found for builtin'):
2052 inspect.signature(str)
2053
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002054 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002055 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002056 inspect.signature(42)
2057
Yury Selivanov63da7c72014-01-31 14:48:37 -05002058 def test_signature_from_functionlike_object(self):
2059 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2060 pass
2061
2062 class funclike:
2063 # Has to be callable, and have correct
2064 # __code__, __annotations__, __defaults__, __name__,
2065 # and __kwdefaults__ attributes
2066
2067 def __init__(self, func):
2068 self.__name__ = func.__name__
2069 self.__code__ = func.__code__
2070 self.__annotations__ = func.__annotations__
2071 self.__defaults__ = func.__defaults__
2072 self.__kwdefaults__ = func.__kwdefaults__
2073 self.func = func
2074
2075 def __call__(self, *args, **kwargs):
2076 return self.func(*args, **kwargs)
2077
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002078 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002079
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002080 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002081 self.assertEqual(sig_funclike, sig_func)
2082
2083 sig_funclike = inspect.signature(funclike(func))
2084 self.assertEqual(sig_funclike, sig_func)
2085
2086 # If object is not a duck type of function, then
2087 # signature will try to get a signature for its '__call__'
2088 # method
2089 fl = funclike(func)
2090 del fl.__defaults__
2091 self.assertEqual(self.signature(fl),
2092 ((('args', ..., ..., "var_positional"),
2093 ('kwargs', ..., ..., "var_keyword")),
2094 ...))
2095
Yury Selivanova773de02014-02-21 18:30:53 -05002096 # Test with cython-like builtins:
2097 _orig_isdesc = inspect.ismethoddescriptor
2098 def _isdesc(obj):
2099 if hasattr(obj, '_builtinmock'):
2100 return True
2101 return _orig_isdesc(obj)
2102
2103 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2104 builtin_func = funclike(func)
2105 # Make sure that our mock setup is working
2106 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2107 builtin_func._builtinmock = True
2108 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2109 self.assertEqual(inspect.signature(builtin_func), sig_func)
2110
Yury Selivanov63da7c72014-01-31 14:48:37 -05002111 def test_signature_functionlike_class(self):
2112 # We only want to duck type function-like objects,
2113 # not classes.
2114
2115 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2116 pass
2117
2118 class funclike:
2119 def __init__(self, marker):
2120 pass
2121
2122 __name__ = func.__name__
2123 __code__ = func.__code__
2124 __annotations__ = func.__annotations__
2125 __defaults__ = func.__defaults__
2126 __kwdefaults__ = func.__kwdefaults__
2127
Yury Selivanov63da7c72014-01-31 14:48:37 -05002128 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2129
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002130 def test_signature_on_method(self):
2131 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002132 def __init__(*args):
2133 pass
2134 def m1(self, arg1, arg2=1) -> int:
2135 pass
2136 def m2(*args):
2137 pass
2138 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002139 pass
2140
Yury Selivanov62560fb2014-01-28 12:26:24 -05002141 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002142 ((('arg1', ..., ..., "positional_or_keyword"),
2143 ('arg2', 1, ..., "positional_or_keyword")),
2144 int))
2145
Yury Selivanov62560fb2014-01-28 12:26:24 -05002146 self.assertEqual(self.signature(Test().m2),
2147 ((('args', ..., ..., "var_positional"),),
2148 ...))
2149
2150 self.assertEqual(self.signature(Test),
2151 ((('args', ..., ..., "var_positional"),),
2152 ...))
2153
2154 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2155 self.signature(Test())
2156
Yury Selivanov46c759d2015-05-27 21:56:53 -04002157 def test_signature_wrapped_bound_method(self):
2158 # Issue 24298
2159 class Test:
2160 def m1(self, arg1, arg2=1) -> int:
2161 pass
2162 @functools.wraps(Test().m1)
2163 def m1d(*args, **kwargs):
2164 pass
2165 self.assertEqual(self.signature(m1d),
2166 ((('arg1', ..., ..., "positional_or_keyword"),
2167 ('arg2', 1, ..., "positional_or_keyword")),
2168 int))
2169
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002170 def test_signature_on_classmethod(self):
2171 class Test:
2172 @classmethod
2173 def foo(cls, arg1, *, arg2=1):
2174 pass
2175
2176 meth = Test().foo
2177 self.assertEqual(self.signature(meth),
2178 ((('arg1', ..., ..., "positional_or_keyword"),
2179 ('arg2', 1, ..., "keyword_only")),
2180 ...))
2181
2182 meth = Test.foo
2183 self.assertEqual(self.signature(meth),
2184 ((('arg1', ..., ..., "positional_or_keyword"),
2185 ('arg2', 1, ..., "keyword_only")),
2186 ...))
2187
2188 def test_signature_on_staticmethod(self):
2189 class Test:
2190 @staticmethod
2191 def foo(cls, *, arg):
2192 pass
2193
2194 meth = Test().foo
2195 self.assertEqual(self.signature(meth),
2196 ((('cls', ..., ..., "positional_or_keyword"),
2197 ('arg', ..., ..., "keyword_only")),
2198 ...))
2199
2200 meth = Test.foo
2201 self.assertEqual(self.signature(meth),
2202 ((('cls', ..., ..., "positional_or_keyword"),
2203 ('arg', ..., ..., "keyword_only")),
2204 ...))
2205
2206 def test_signature_on_partial(self):
2207 from functools import partial
2208
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002209 Parameter = inspect.Parameter
2210
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002211 def test():
2212 pass
2213
2214 self.assertEqual(self.signature(partial(test)), ((), ...))
2215
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002216 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002217 inspect.signature(partial(test, 1))
2218
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002219 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002220 inspect.signature(partial(test, a=1))
2221
2222 def test(a, b, *, c, d):
2223 pass
2224
2225 self.assertEqual(self.signature(partial(test)),
2226 ((('a', ..., ..., "positional_or_keyword"),
2227 ('b', ..., ..., "positional_or_keyword"),
2228 ('c', ..., ..., "keyword_only"),
2229 ('d', ..., ..., "keyword_only")),
2230 ...))
2231
2232 self.assertEqual(self.signature(partial(test, 1)),
2233 ((('b', ..., ..., "positional_or_keyword"),
2234 ('c', ..., ..., "keyword_only"),
2235 ('d', ..., ..., "keyword_only")),
2236 ...))
2237
2238 self.assertEqual(self.signature(partial(test, 1, c=2)),
2239 ((('b', ..., ..., "positional_or_keyword"),
2240 ('c', 2, ..., "keyword_only"),
2241 ('d', ..., ..., "keyword_only")),
2242 ...))
2243
2244 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2245 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002246 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002247 ('c', 2, ..., "keyword_only"),
2248 ('d', ..., ..., "keyword_only")),
2249 ...))
2250
2251 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002252 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002253 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002254 ('d', ..., ..., "keyword_only")),
2255 ...))
2256
2257 self.assertEqual(self.signature(partial(test, a=1)),
2258 ((('a', 1, ..., "keyword_only"),
2259 ('b', ..., ..., "keyword_only"),
2260 ('c', ..., ..., "keyword_only"),
2261 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002262 ...))
2263
2264 def test(a, *args, b, **kwargs):
2265 pass
2266
2267 self.assertEqual(self.signature(partial(test, 1)),
2268 ((('args', ..., ..., "var_positional"),
2269 ('b', ..., ..., "keyword_only"),
2270 ('kwargs', ..., ..., "var_keyword")),
2271 ...))
2272
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002273 self.assertEqual(self.signature(partial(test, a=1)),
2274 ((('a', 1, ..., "keyword_only"),
2275 ('b', ..., ..., "keyword_only"),
2276 ('kwargs', ..., ..., "var_keyword")),
2277 ...))
2278
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002279 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2280 ((('args', ..., ..., "var_positional"),
2281 ('b', ..., ..., "keyword_only"),
2282 ('kwargs', ..., ..., "var_keyword")),
2283 ...))
2284
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002285 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2286 ((('args', ..., ..., "var_positional"),
2287 ('b', ..., ..., "keyword_only"),
2288 ('kwargs', ..., ..., "var_keyword")),
2289 ...))
2290
2291 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2292 ((('args', ..., ..., "var_positional"),
2293 ('b', 0, ..., "keyword_only"),
2294 ('kwargs', ..., ..., "var_keyword")),
2295 ...))
2296
2297 self.assertEqual(self.signature(partial(test, b=0)),
2298 ((('a', ..., ..., "positional_or_keyword"),
2299 ('args', ..., ..., "var_positional"),
2300 ('b', 0, ..., "keyword_only"),
2301 ('kwargs', ..., ..., "var_keyword")),
2302 ...))
2303
2304 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2305 ((('a', ..., ..., "positional_or_keyword"),
2306 ('args', ..., ..., "var_positional"),
2307 ('b', 0, ..., "keyword_only"),
2308 ('kwargs', ..., ..., "var_keyword")),
2309 ...))
2310
2311 def test(a, b, c:int) -> 42:
2312 pass
2313
2314 sig = test.__signature__ = inspect.signature(test)
2315
2316 self.assertEqual(self.signature(partial(partial(test, 1))),
2317 ((('b', ..., ..., "positional_or_keyword"),
2318 ('c', ..., int, "positional_or_keyword")),
2319 42))
2320
2321 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2322 ((('c', ..., int, "positional_or_keyword"),),
2323 42))
2324
2325 psig = inspect.signature(partial(partial(test, 1), 2))
2326
2327 def foo(a):
2328 return a
2329 _foo = partial(partial(foo, a=10), a=20)
2330 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002331 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002332 ...))
2333 # check that we don't have any side-effects in signature(),
2334 # and the partial object is still functioning
2335 self.assertEqual(_foo(), 20)
2336
2337 def foo(a, b, c):
2338 return a, b, c
2339 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002340
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002341 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002342 ((('b', 30, ..., "keyword_only"),
2343 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002344 ...))
2345 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002346
2347 def foo(a, b, c, *, d):
2348 return a, b, c, d
2349 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2350 self.assertEqual(self.signature(_foo),
2351 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002352 ('b', 10, ..., "keyword_only"),
2353 ('c', 20, ..., "keyword_only"),
2354 ('d', 30, ..., "keyword_only"),
2355 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002356 ...))
2357 ba = inspect.signature(_foo).bind(a=200, b=11)
2358 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2359
2360 def foo(a=1, b=2, c=3):
2361 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002362 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2363
2364 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002365 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002366
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002367 ba = inspect.signature(_foo).bind(11, 12)
2368 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002369
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002370 ba = inspect.signature(_foo).bind(11, b=12)
2371 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002372
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002373 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002374 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2375
2376 _foo = partial(_foo, b=10, c=20)
2377 ba = inspect.signature(_foo).bind(12)
2378 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2379
2380
2381 def foo(a, b, c, d, **kwargs):
2382 pass
2383 sig = inspect.signature(foo)
2384 params = sig.parameters.copy()
2385 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2386 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2387 foo.__signature__ = inspect.Signature(params.values())
2388 sig = inspect.signature(foo)
2389 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2390
2391 self.assertEqual(self.signature(partial(foo, 1)),
2392 ((('b', ..., ..., 'positional_only'),
2393 ('c', ..., ..., 'positional_or_keyword'),
2394 ('d', ..., ..., 'positional_or_keyword'),
2395 ('kwargs', ..., ..., 'var_keyword')),
2396 ...))
2397
2398 self.assertEqual(self.signature(partial(foo, 1, 2)),
2399 ((('c', ..., ..., 'positional_or_keyword'),
2400 ('d', ..., ..., 'positional_or_keyword'),
2401 ('kwargs', ..., ..., 'var_keyword')),
2402 ...))
2403
2404 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2405 ((('d', ..., ..., 'positional_or_keyword'),
2406 ('kwargs', ..., ..., 'var_keyword')),
2407 ...))
2408
2409 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2410 ((('c', 3, ..., 'keyword_only'),
2411 ('d', ..., ..., 'keyword_only'),
2412 ('kwargs', ..., ..., 'var_keyword')),
2413 ...))
2414
2415 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2416 ((('b', ..., ..., 'positional_only'),
2417 ('c', 3, ..., 'keyword_only'),
2418 ('d', ..., ..., 'keyword_only'),
2419 ('kwargs', ..., ..., 'var_keyword')),
2420 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002421
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002422 def test_signature_on_partialmethod(self):
2423 from functools import partialmethod
2424
2425 class Spam:
2426 def test():
2427 pass
2428 ham = partialmethod(test)
2429
2430 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2431 inspect.signature(Spam.ham)
2432
2433 class Spam:
2434 def test(it, a, *, c) -> 'spam':
2435 pass
2436 ham = partialmethod(test, c=1)
2437
2438 self.assertEqual(self.signature(Spam.ham),
2439 ((('it', ..., ..., 'positional_or_keyword'),
2440 ('a', ..., ..., 'positional_or_keyword'),
2441 ('c', 1, ..., 'keyword_only')),
2442 'spam'))
2443
2444 self.assertEqual(self.signature(Spam().ham),
2445 ((('a', ..., ..., 'positional_or_keyword'),
2446 ('c', 1, ..., 'keyword_only')),
2447 'spam'))
2448
Yury Selivanov0486f812014-01-29 12:18:59 -05002449 def test_signature_on_fake_partialmethod(self):
2450 def foo(a): pass
2451 foo._partialmethod = 'spam'
2452 self.assertEqual(str(inspect.signature(foo)), '(a)')
2453
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002454 def test_signature_on_decorated(self):
2455 import functools
2456
2457 def decorator(func):
2458 @functools.wraps(func)
2459 def wrapper(*args, **kwargs) -> int:
2460 return func(*args, **kwargs)
2461 return wrapper
2462
2463 class Foo:
2464 @decorator
2465 def bar(self, a, b):
2466 pass
2467
2468 self.assertEqual(self.signature(Foo.bar),
2469 ((('self', ..., ..., "positional_or_keyword"),
2470 ('a', ..., ..., "positional_or_keyword"),
2471 ('b', ..., ..., "positional_or_keyword")),
2472 ...))
2473
2474 self.assertEqual(self.signature(Foo().bar),
2475 ((('a', ..., ..., "positional_or_keyword"),
2476 ('b', ..., ..., "positional_or_keyword")),
2477 ...))
2478
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002479 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2480 ((('args', ..., ..., "var_positional"),
2481 ('kwargs', ..., ..., "var_keyword")),
2482 ...)) # functools.wraps will copy __annotations__
2483 # from "func" to "wrapper", hence no
2484 # return_annotation
2485
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002486 # Test that we handle method wrappers correctly
2487 def decorator(func):
2488 @functools.wraps(func)
2489 def wrapper(*args, **kwargs) -> int:
2490 return func(42, *args, **kwargs)
2491 sig = inspect.signature(func)
2492 new_params = tuple(sig.parameters.values())[1:]
2493 wrapper.__signature__ = sig.replace(parameters=new_params)
2494 return wrapper
2495
2496 class Foo:
2497 @decorator
2498 def __call__(self, a, b):
2499 pass
2500
2501 self.assertEqual(self.signature(Foo.__call__),
2502 ((('a', ..., ..., "positional_or_keyword"),
2503 ('b', ..., ..., "positional_or_keyword")),
2504 ...))
2505
2506 self.assertEqual(self.signature(Foo().__call__),
2507 ((('b', ..., ..., "positional_or_keyword"),),
2508 ...))
2509
Nick Coghlane8c45d62013-07-28 20:00:01 +10002510 # Test we handle __signature__ partway down the wrapper stack
2511 def wrapped_foo_call():
2512 pass
2513 wrapped_foo_call.__wrapped__ = Foo.__call__
2514
2515 self.assertEqual(self.signature(wrapped_foo_call),
2516 ((('a', ..., ..., "positional_or_keyword"),
2517 ('b', ..., ..., "positional_or_keyword")),
2518 ...))
2519
2520
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002521 def test_signature_on_class(self):
2522 class C:
2523 def __init__(self, a):
2524 pass
2525
2526 self.assertEqual(self.signature(C),
2527 ((('a', ..., ..., "positional_or_keyword"),),
2528 ...))
2529
2530 class CM(type):
2531 def __call__(cls, a):
2532 pass
2533 class C(metaclass=CM):
2534 def __init__(self, b):
2535 pass
2536
2537 self.assertEqual(self.signature(C),
2538 ((('a', ..., ..., "positional_or_keyword"),),
2539 ...))
2540
2541 class CM(type):
2542 def __new__(mcls, name, bases, dct, *, foo=1):
2543 return super().__new__(mcls, name, bases, dct)
2544 class C(metaclass=CM):
2545 def __init__(self, b):
2546 pass
2547
2548 self.assertEqual(self.signature(C),
2549 ((('b', ..., ..., "positional_or_keyword"),),
2550 ...))
2551
2552 self.assertEqual(self.signature(CM),
2553 ((('name', ..., ..., "positional_or_keyword"),
2554 ('bases', ..., ..., "positional_or_keyword"),
2555 ('dct', ..., ..., "positional_or_keyword"),
2556 ('foo', 1, ..., "keyword_only")),
2557 ...))
2558
2559 class CMM(type):
2560 def __new__(mcls, name, bases, dct, *, foo=1):
2561 return super().__new__(mcls, name, bases, dct)
2562 def __call__(cls, nm, bs, dt):
2563 return type(nm, bs, dt)
2564 class CM(type, metaclass=CMM):
2565 def __new__(mcls, name, bases, dct, *, bar=2):
2566 return super().__new__(mcls, name, bases, dct)
2567 class C(metaclass=CM):
2568 def __init__(self, b):
2569 pass
2570
2571 self.assertEqual(self.signature(CMM),
2572 ((('name', ..., ..., "positional_or_keyword"),
2573 ('bases', ..., ..., "positional_or_keyword"),
2574 ('dct', ..., ..., "positional_or_keyword"),
2575 ('foo', 1, ..., "keyword_only")),
2576 ...))
2577
2578 self.assertEqual(self.signature(CM),
2579 ((('nm', ..., ..., "positional_or_keyword"),
2580 ('bs', ..., ..., "positional_or_keyword"),
2581 ('dt', ..., ..., "positional_or_keyword")),
2582 ...))
2583
2584 self.assertEqual(self.signature(C),
2585 ((('b', ..., ..., "positional_or_keyword"),),
2586 ...))
2587
2588 class CM(type):
2589 def __init__(cls, name, bases, dct, *, bar=2):
2590 return super().__init__(name, bases, dct)
2591 class C(metaclass=CM):
2592 def __init__(self, b):
2593 pass
2594
2595 self.assertEqual(self.signature(CM),
2596 ((('name', ..., ..., "positional_or_keyword"),
2597 ('bases', ..., ..., "positional_or_keyword"),
2598 ('dct', ..., ..., "positional_or_keyword"),
2599 ('bar', 2, ..., "keyword_only")),
2600 ...))
2601
Yury Selivanov145dff82014-02-01 13:49:29 -05002602 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2603 "Signature information for builtins requires docstrings")
2604 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002605 # Test classes without user-defined __init__ or __new__
2606 class C: pass
2607 self.assertEqual(str(inspect.signature(C)), '()')
2608 class D(C): pass
2609 self.assertEqual(str(inspect.signature(D)), '()')
2610
2611 # Test meta-classes without user-defined __init__ or __new__
2612 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002613 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002614 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2615 self.assertEqual(inspect.signature(C), None)
2616 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2617 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002618
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002619 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2620 "Signature information for builtins requires docstrings")
2621 def test_signature_on_builtin_class(self):
2622 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2623 '(file, protocol=None, fix_imports=True)')
2624
2625 class P(_pickle.Pickler): pass
2626 class EmptyTrait: pass
2627 class P2(EmptyTrait, P): pass
2628 self.assertEqual(str(inspect.signature(P)),
2629 '(file, protocol=None, fix_imports=True)')
2630 self.assertEqual(str(inspect.signature(P2)),
2631 '(file, protocol=None, fix_imports=True)')
2632
2633 class P3(P2):
2634 def __init__(self, spam):
2635 pass
2636 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2637
2638 class MetaP(type):
2639 def __call__(cls, foo, bar):
2640 pass
2641 class P4(P2, metaclass=MetaP):
2642 pass
2643 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2644
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002645 def test_signature_on_callable_objects(self):
2646 class Foo:
2647 def __call__(self, a):
2648 pass
2649
2650 self.assertEqual(self.signature(Foo()),
2651 ((('a', ..., ..., "positional_or_keyword"),),
2652 ...))
2653
2654 class Spam:
2655 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002656 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002657 inspect.signature(Spam())
2658
2659 class Bar(Spam, Foo):
2660 pass
2661
2662 self.assertEqual(self.signature(Bar()),
2663 ((('a', ..., ..., "positional_or_keyword"),),
2664 ...))
2665
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002666 class Wrapped:
2667 pass
2668 Wrapped.__wrapped__ = lambda a: None
2669 self.assertEqual(self.signature(Wrapped),
2670 ((('a', ..., ..., "positional_or_keyword"),),
2671 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002672 # wrapper loop:
2673 Wrapped.__wrapped__ = Wrapped
2674 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2675 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002676
2677 def test_signature_on_lambdas(self):
2678 self.assertEqual(self.signature((lambda a=10: a)),
2679 ((('a', 10, ..., "positional_or_keyword"),),
2680 ...))
2681
2682 def test_signature_equality(self):
2683 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002684 self.assertFalse(inspect.signature(foo) == 42)
2685 self.assertTrue(inspect.signature(foo) != 42)
2686 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2687 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002688
2689 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002690 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2691 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002692 self.assertEqual(
2693 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002694
2695 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002696 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2697 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002698 self.assertNotEqual(
2699 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002700
2701 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002702 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2703 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002704 self.assertNotEqual(
2705 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002706
2707 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002708 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2709 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002710 self.assertNotEqual(
2711 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002712
2713 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002714 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2715 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002716 self.assertNotEqual(
2717 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002718
2719 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002720 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2721 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002722 self.assertNotEqual(
2723 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002724 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002725 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
2726 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002727 self.assertNotEqual(
2728 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002729
2730 def foo(*, a, b, c): pass
2731 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002732 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2733 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002734 self.assertEqual(
2735 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002736
2737 def foo(*, a=1, b, c): pass
2738 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002739 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2740 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002741 self.assertEqual(
2742 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002743
2744 def foo(pos, *, a=1, b, c): pass
2745 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002746 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2747 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002748 self.assertEqual(
2749 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002750
2751 def foo(pos, *, a, b, c): pass
2752 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002753 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2754 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002755 self.assertNotEqual(
2756 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002757
2758 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2759 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002760 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2761 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002762 self.assertEqual(
2763 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002764
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002765 def test_signature_hashable(self):
2766 S = inspect.Signature
2767 P = inspect.Parameter
2768
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002769 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002770 foo_sig = inspect.signature(foo)
2771
2772 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2773
2774 self.assertEqual(hash(foo_sig), hash(manual_sig))
2775 self.assertNotEqual(hash(foo_sig),
2776 hash(manual_sig.replace(return_annotation='spam')))
2777
2778 def bar(a) -> 1: pass
2779 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2780
2781 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002782 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002783 hash(inspect.signature(foo))
2784
2785 def foo(a) -> {}: pass
2786 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2787 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002788
2789 def test_signature_str(self):
2790 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2791 pass
2792 self.assertEqual(str(inspect.signature(foo)),
2793 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2794
2795 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2796 pass
2797 self.assertEqual(str(inspect.signature(foo)),
2798 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2799
2800 def foo():
2801 pass
2802 self.assertEqual(str(inspect.signature(foo)), '()')
2803
2804 def test_signature_str_positional_only(self):
2805 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002806 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002807
2808 def test(a_po, *, b, **kwargs):
2809 return a_po, kwargs
2810
2811 sig = inspect.signature(test)
2812 new_params = list(sig.parameters.values())
2813 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2814 test.__signature__ = sig.replace(parameters=new_params)
2815
2816 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002817 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002818
Yury Selivanov2393dca2014-01-27 15:07:58 -05002819 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2820 '(foo, /)')
2821
2822 self.assertEqual(str(S(parameters=[
2823 P('foo', P.POSITIONAL_ONLY),
2824 P('bar', P.VAR_KEYWORD)])),
2825 '(foo, /, **bar)')
2826
2827 self.assertEqual(str(S(parameters=[
2828 P('foo', P.POSITIONAL_ONLY),
2829 P('bar', P.VAR_POSITIONAL)])),
2830 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002831
2832 def test_signature_replace_anno(self):
2833 def test() -> 42:
2834 pass
2835
2836 sig = inspect.signature(test)
2837 sig = sig.replace(return_annotation=None)
2838 self.assertIs(sig.return_annotation, None)
2839 sig = sig.replace(return_annotation=sig.empty)
2840 self.assertIs(sig.return_annotation, sig.empty)
2841 sig = sig.replace(return_annotation=42)
2842 self.assertEqual(sig.return_annotation, 42)
2843 self.assertEqual(sig, inspect.signature(test))
2844
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002845 def test_signature_on_mangled_parameters(self):
2846 class Spam:
2847 def foo(self, __p1:1=2, *, __p2:2=3):
2848 pass
2849 class Ham(Spam):
2850 pass
2851
2852 self.assertEqual(self.signature(Spam.foo),
2853 ((('self', ..., ..., "positional_or_keyword"),
2854 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2855 ('_Spam__p2', 3, 2, "keyword_only")),
2856 ...))
2857
2858 self.assertEqual(self.signature(Spam.foo),
2859 self.signature(Ham.foo))
2860
Yury Selivanovda396452014-03-27 12:09:24 -04002861 def test_signature_from_callable_python_obj(self):
2862 class MySignature(inspect.Signature): pass
2863 def foo(a, *, b:1): pass
2864 foo_sig = MySignature.from_callable(foo)
2865 self.assertTrue(isinstance(foo_sig, MySignature))
2866
2867 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2868 "Signature information for builtins requires docstrings")
2869 def test_signature_from_callable_builtin_obj(self):
2870 class MySignature(inspect.Signature): pass
2871 sig = MySignature.from_callable(_pickle.Pickler)
2872 self.assertTrue(isinstance(sig, MySignature))
2873
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002874
2875class TestParameterObject(unittest.TestCase):
2876 def test_signature_parameter_kinds(self):
2877 P = inspect.Parameter
2878 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2879 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2880
2881 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2882 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2883
2884 def test_signature_parameter_object(self):
2885 p = inspect.Parameter('foo', default=10,
2886 kind=inspect.Parameter.POSITIONAL_ONLY)
2887 self.assertEqual(p.name, 'foo')
2888 self.assertEqual(p.default, 10)
2889 self.assertIs(p.annotation, p.empty)
2890 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2891
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002892 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002893 inspect.Parameter('foo', default=10, kind='123')
2894
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002895 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002896 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2897
Yury Selivanov2393dca2014-01-27 15:07:58 -05002898 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002899 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2900
Yury Selivanov2393dca2014-01-27 15:07:58 -05002901 with self.assertRaisesRegex(ValueError,
2902 'is not a valid parameter name'):
2903 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2904
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002905 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002906 inspect.Parameter('a', default=42,
2907 kind=inspect.Parameter.VAR_KEYWORD)
2908
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002909 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002910 inspect.Parameter('a', default=42,
2911 kind=inspect.Parameter.VAR_POSITIONAL)
2912
2913 p = inspect.Parameter('a', default=42,
2914 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002915 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002916 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2917
2918 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002919 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002920
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002921 def test_signature_parameter_hashable(self):
2922 P = inspect.Parameter
2923 foo = P('foo', kind=P.POSITIONAL_ONLY)
2924 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
2925 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
2926 default=42)))
2927 self.assertNotEqual(hash(foo),
2928 hash(foo.replace(kind=P.VAR_POSITIONAL)))
2929
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002930 def test_signature_parameter_equality(self):
2931 P = inspect.Parameter
2932 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2933
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002934 self.assertTrue(p == p)
2935 self.assertFalse(p != p)
2936 self.assertFalse(p == 42)
2937 self.assertTrue(p != 42)
2938 self.assertTrue(p == EqualsToAll())
2939 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002940
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002941 self.assertTrue(p == P('foo', default=42,
2942 kind=inspect.Parameter.KEYWORD_ONLY))
2943 self.assertFalse(p != P('foo', default=42,
2944 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002945
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002946 def test_signature_parameter_replace(self):
2947 p = inspect.Parameter('foo', default=42,
2948 kind=inspect.Parameter.KEYWORD_ONLY)
2949
2950 self.assertIsNot(p, p.replace())
2951 self.assertEqual(p, p.replace())
2952
2953 p2 = p.replace(annotation=1)
2954 self.assertEqual(p2.annotation, 1)
2955 p2 = p2.replace(annotation=p2.empty)
2956 self.assertEqual(p, p2)
2957
2958 p2 = p2.replace(name='bar')
2959 self.assertEqual(p2.name, 'bar')
2960 self.assertNotEqual(p2, p)
2961
Yury Selivanov2393dca2014-01-27 15:07:58 -05002962 with self.assertRaisesRegex(ValueError,
2963 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002964 p2 = p2.replace(name=p2.empty)
2965
2966 p2 = p2.replace(name='foo', default=None)
2967 self.assertIs(p2.default, None)
2968 self.assertNotEqual(p2, p)
2969
2970 p2 = p2.replace(name='foo', default=p2.empty)
2971 self.assertIs(p2.default, p2.empty)
2972
2973
2974 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2975 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2976 self.assertNotEqual(p2, p)
2977
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002978 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002979 p2 = p2.replace(kind=p2.empty)
2980
2981 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2982 self.assertEqual(p2, p)
2983
2984 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002985 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2986 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002987
2988 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002989 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002990
2991 with self.assertRaises(AttributeError):
2992 p.foo = 'bar'
2993
2994 with self.assertRaises(AttributeError):
2995 p.kind = 123
2996
2997
2998class TestSignatureBind(unittest.TestCase):
2999 @staticmethod
3000 def call(func, *args, **kwargs):
3001 sig = inspect.signature(func)
3002 ba = sig.bind(*args, **kwargs)
3003 return func(*ba.args, **ba.kwargs)
3004
3005 def test_signature_bind_empty(self):
3006 def test():
3007 return 42
3008
3009 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003010 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003011 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003012 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003013 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003014 with self.assertRaisesRegex(
3015 TypeError, "got an unexpected keyword argument 'spam'"):
3016
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003017 self.call(test, spam=1)
3018
3019 def test_signature_bind_var(self):
3020 def test(*args, **kwargs):
3021 return args, kwargs
3022
3023 self.assertEqual(self.call(test), ((), {}))
3024 self.assertEqual(self.call(test, 1), ((1,), {}))
3025 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3026 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3027 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3028 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3029 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3030 ((1, 2), {'foo': 'bar'}))
3031
3032 def test_signature_bind_just_args(self):
3033 def test(a, b, c):
3034 return a, b, c
3035
3036 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3037
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003038 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003039 self.call(test, 1, 2, 3, 4)
3040
Yury Selivanov86872752015-05-19 00:27:49 -04003041 with self.assertRaisesRegex(TypeError,
3042 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003043 self.call(test, 1)
3044
Yury Selivanov86872752015-05-19 00:27:49 -04003045 with self.assertRaisesRegex(TypeError,
3046 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003047 self.call(test)
3048
3049 def test(a, b, c=10):
3050 return a, b, c
3051 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3052 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3053
3054 def test(a=1, b=2, c=3):
3055 return a, b, c
3056 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3057 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3058 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3059
3060 def test_signature_bind_varargs_order(self):
3061 def test(*args):
3062 return args
3063
3064 self.assertEqual(self.call(test), ())
3065 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3066
3067 def test_signature_bind_args_and_varargs(self):
3068 def test(a, b, c=3, *args):
3069 return a, b, c, args
3070
3071 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3072 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3073 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3074 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3075
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003076 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003077 "multiple values for argument 'c'"):
3078 self.call(test, 1, 2, 3, c=4)
3079
3080 def test_signature_bind_just_kwargs(self):
3081 def test(**kwargs):
3082 return kwargs
3083
3084 self.assertEqual(self.call(test), {})
3085 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3086 {'foo': 'bar', 'spam': 'ham'})
3087
3088 def test_signature_bind_args_and_kwargs(self):
3089 def test(a, b, c=3, **kwargs):
3090 return a, b, c, kwargs
3091
3092 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3093 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3094 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3095 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3096 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3097 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3098 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3099 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3100 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3101 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3102 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3103 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3104 (1, 2, 4, {'foo': 'bar'}))
3105 self.assertEqual(self.call(test, c=5, a=4, b=3),
3106 (4, 3, 5, {}))
3107
3108 def test_signature_bind_kwonly(self):
3109 def test(*, foo):
3110 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003111 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003112 'too many positional arguments'):
3113 self.call(test, 1)
3114 self.assertEqual(self.call(test, foo=1), 1)
3115
3116 def test(a, *, foo=1, bar):
3117 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003118 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003119 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003120 self.call(test, 1)
3121
3122 def test(foo, *, bar):
3123 return foo, bar
3124 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3125 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3126
Yury Selivanov86872752015-05-19 00:27:49 -04003127 with self.assertRaisesRegex(
3128 TypeError, "got an unexpected keyword argument 'spam'"):
3129
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003130 self.call(test, bar=2, foo=1, spam=10)
3131
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003132 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003133 'too many positional arguments'):
3134 self.call(test, 1, 2)
3135
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003136 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003137 'too many positional arguments'):
3138 self.call(test, 1, 2, bar=2)
3139
Yury Selivanov86872752015-05-19 00:27:49 -04003140 with self.assertRaisesRegex(
3141 TypeError, "got an unexpected keyword argument 'spam'"):
3142
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003143 self.call(test, 1, bar=2, spam='ham')
3144
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003145 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003146 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003147 self.call(test, 1)
3148
3149 def test(foo, *, bar, **bin):
3150 return foo, bar, bin
3151 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3152 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3153 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3154 (1, 2, {'spam': 'ham'}))
3155 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3156 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003157 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003158 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003159 self.call(test, spam='ham', bar=2)
3160 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3161 (1, 2, {'bin': 1, 'spam': 10}))
3162
3163 def test_signature_bind_arguments(self):
3164 def test(a, *args, b, z=100, **kwargs):
3165 pass
3166 sig = inspect.signature(test)
3167 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3168 # we won't have 'z' argument in the bound arguments object, as we didn't
3169 # pass it to the 'bind'
3170 self.assertEqual(tuple(ba.arguments.items()),
3171 (('a', 10), ('args', (20,)), ('b', 30),
3172 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3173 self.assertEqual(ba.kwargs,
3174 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3175 self.assertEqual(ba.args, (10, 20))
3176
3177 def test_signature_bind_positional_only(self):
3178 P = inspect.Parameter
3179
3180 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3181 return a_po, b_po, c_po, foo, bar, kwargs
3182
3183 sig = inspect.signature(test)
3184 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3185 for name in ('a_po', 'b_po', 'c_po'):
3186 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3187 new_sig = sig.replace(parameters=new_params.values())
3188 test.__signature__ = new_sig
3189
3190 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3191 (1, 2, 4, 5, 6, {}))
3192
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003193 self.assertEqual(self.call(test, 1, 2),
3194 (1, 2, 3, 42, 50, {}))
3195
3196 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3197 (1, 2, 3, 4, 5, {}))
3198
3199 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3200 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3201
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003202 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003203 self.call(test, 1, 2, c_po=4)
3204
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003205 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003206 self.call(test, a_po=1, b_po=2)
3207
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003208 def test_signature_bind_with_self_arg(self):
3209 # Issue #17071: one of the parameters is named "self
3210 def test(a, self, b):
3211 pass
3212 sig = inspect.signature(test)
3213 ba = sig.bind(1, 2, 3)
3214 self.assertEqual(ba.args, (1, 2, 3))
3215 ba = sig.bind(1, self=2, b=3)
3216 self.assertEqual(ba.args, (1, 2, 3))
3217
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003218 def test_signature_bind_vararg_name(self):
3219 def test(a, *args):
3220 return a, args
3221 sig = inspect.signature(test)
3222
Yury Selivanov86872752015-05-19 00:27:49 -04003223 with self.assertRaisesRegex(
3224 TypeError, "got an unexpected keyword argument 'args'"):
3225
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003226 sig.bind(a=0, args=1)
3227
3228 def test(*args, **kwargs):
3229 return args, kwargs
3230 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3231
3232 sig = inspect.signature(test)
3233 ba = sig.bind(args=1)
3234 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3235
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003236
3237class TestBoundArguments(unittest.TestCase):
3238 def test_signature_bound_arguments_unhashable(self):
3239 def foo(a): pass
3240 ba = inspect.signature(foo).bind(1)
3241
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003242 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003243 hash(ba)
3244
3245 def test_signature_bound_arguments_equality(self):
3246 def foo(a): pass
3247 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003248 self.assertTrue(ba == ba)
3249 self.assertFalse(ba != ba)
3250 self.assertTrue(ba == EqualsToAll())
3251 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003252
3253 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003254 self.assertTrue(ba == ba2)
3255 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003256
3257 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003258 self.assertFalse(ba == ba3)
3259 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003260 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003261 self.assertTrue(ba == ba3)
3262 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003263
3264 def bar(b): pass
3265 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003266 self.assertFalse(ba == ba4)
3267 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003268
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003269 def foo(*, a, b): pass
3270 sig = inspect.signature(foo)
3271 ba1 = sig.bind(a=1, b=2)
3272 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003273 self.assertTrue(ba1 == ba2)
3274 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003275
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003276 def test_signature_bound_arguments_pickle(self):
3277 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3278 sig = inspect.signature(foo)
3279 ba = sig.bind(20, 30, z={})
3280
3281 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3282 with self.subTest(pickle_ver=ver):
3283 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3284 self.assertEqual(ba, ba_pickled)
3285
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003286 def test_signature_bound_arguments_repr(self):
3287 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3288 sig = inspect.signature(foo)
3289 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003290 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003291
Yury Selivanovb907a512015-05-16 13:45:09 -04003292 def test_signature_bound_arguments_apply_defaults(self):
3293 def foo(a, b=1, *args, c:1={}, **kw): pass
3294 sig = inspect.signature(foo)
3295
3296 ba = sig.bind(20)
3297 ba.apply_defaults()
3298 self.assertEqual(
3299 list(ba.arguments.items()),
3300 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3301
3302 # Make sure that we preserve the order:
3303 # i.e. 'c' should be *before* 'kw'.
3304 ba = sig.bind(10, 20, 30, d=1)
3305 ba.apply_defaults()
3306 self.assertEqual(
3307 list(ba.arguments.items()),
3308 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3309
3310 # Make sure that BoundArguments produced by bind_partial()
3311 # are supported.
3312 def foo(a, b): pass
3313 sig = inspect.signature(foo)
3314 ba = sig.bind_partial(20)
3315 ba.apply_defaults()
3316 self.assertEqual(
3317 list(ba.arguments.items()),
3318 [('a', 20)])
3319
3320 # Test no args
3321 def foo(): pass
3322 sig = inspect.signature(foo)
3323 ba = sig.bind()
3324 ba.apply_defaults()
3325 self.assertEqual(list(ba.arguments.items()), [])
3326
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003327 # Make sure a no-args binding still acquires proper defaults.
3328 def foo(a='spam'): pass
3329 sig = inspect.signature(foo)
3330 ba = sig.bind()
3331 ba.apply_defaults()
3332 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3333
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003334
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003335class TestSignaturePrivateHelpers(unittest.TestCase):
3336 def test_signature_get_bound_param(self):
3337 getter = inspect._signature_get_bound_param
3338
3339 self.assertEqual(getter('($self)'), 'self')
3340 self.assertEqual(getter('($self, obj)'), 'self')
3341 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3342
Larry Hastings2623c8c2014-02-08 22:15:29 -08003343 def _strip_non_python_syntax(self, input,
3344 clean_signature, self_parameter, last_positional_only):
3345 computed_clean_signature, \
3346 computed_self_parameter, \
3347 computed_last_positional_only = \
3348 inspect._signature_strip_non_python_syntax(input)
3349 self.assertEqual(computed_clean_signature, clean_signature)
3350 self.assertEqual(computed_self_parameter, self_parameter)
3351 self.assertEqual(computed_last_positional_only, last_positional_only)
3352
3353 def test_signature_strip_non_python_syntax(self):
3354 self._strip_non_python_syntax(
3355 "($module, /, path, mode, *, dir_fd=None, " +
3356 "effective_ids=False,\n follow_symlinks=True)",
3357 "(module, path, mode, *, dir_fd=None, " +
3358 "effective_ids=False, follow_symlinks=True)",
3359 0,
3360 0)
3361
3362 self._strip_non_python_syntax(
3363 "($module, word, salt, /)",
3364 "(module, word, salt)",
3365 0,
3366 2)
3367
3368 self._strip_non_python_syntax(
3369 "(x, y=None, z=None, /)",
3370 "(x, y=None, z=None)",
3371 None,
3372 2)
3373
3374 self._strip_non_python_syntax(
3375 "(x, y=None, z=None)",
3376 "(x, y=None, z=None)",
3377 None,
3378 None)
3379
3380 self._strip_non_python_syntax(
3381 "(x,\n y=None,\n z = None )",
3382 "(x, y=None, z=None)",
3383 None,
3384 None)
3385
3386 self._strip_non_python_syntax(
3387 "",
3388 "",
3389 None,
3390 None)
3391
3392 self._strip_non_python_syntax(
3393 None,
3394 None,
3395 None,
3396 None)
3397
Nick Coghlan9c680b02015-04-13 12:54:54 -04003398class TestSignatureDefinitions(unittest.TestCase):
3399 # This test case provides a home for checking that particular APIs
3400 # have signatures available for introspection
3401
3402 @cpython_only
3403 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3404 "Signature information for builtins requires docstrings")
3405 def test_builtins_have_signatures(self):
3406 # This checks all builtin callables in CPython have signatures
3407 # A few have signatures Signature can't yet handle, so we skip those
3408 # since they will have to wait until PEP 457 adds the required
3409 # introspection support to the inspect module
3410 # Some others also haven't been converted yet for various other
3411 # reasons, so we also skip those for the time being, but design
3412 # the test to fail in order to indicate when it needs to be
3413 # updated.
3414 no_signature = set()
3415 # These need PEP 457 groups
3416 needs_groups = {"range", "slice", "dir", "getattr",
3417 "next", "iter", "vars"}
3418 no_signature |= needs_groups
3419 # These need PEP 457 groups or a signature change to accept None
3420 needs_semantic_update = {"round"}
3421 no_signature |= needs_semantic_update
3422 # These need *args support in Argument Clinic
3423 needs_varargs = {"min", "max", "print", "__build_class__"}
3424 no_signature |= needs_varargs
3425 # These simply weren't covered in the initial AC conversion
3426 # for builtin callables
3427 not_converted_yet = {"open", "__import__"}
3428 no_signature |= not_converted_yet
3429 # These builtin types are expected to provide introspection info
3430 types_with_signatures = set()
3431 # Check the signatures we expect to be there
3432 ns = vars(builtins)
3433 for name, obj in sorted(ns.items()):
3434 if not callable(obj):
3435 continue
3436 # The builtin types haven't been converted to AC yet
3437 if isinstance(obj, type) and (name not in types_with_signatures):
3438 # Note that this also skips all the exception types
3439 no_signature.add(name)
3440 if (name in no_signature):
3441 # Not yet converted
3442 continue
3443 with self.subTest(builtin=name):
3444 self.assertIsNotNone(inspect.signature(obj))
3445 # Check callables that haven't been converted don't claim a signature
3446 # This ensures this test will start failing as more signatures are
3447 # added, so the affected items can be moved into the scope of the
3448 # regression test above
3449 for name in no_signature:
3450 with self.subTest(builtin=name):
3451 self.assertIsNone(obj.__text_signature__)
3452
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003453
Nick Coghlane8c45d62013-07-28 20:00:01 +10003454class TestUnwrap(unittest.TestCase):
3455
3456 def test_unwrap_one(self):
3457 def func(a, b):
3458 return a + b
3459 wrapper = functools.lru_cache(maxsize=20)(func)
3460 self.assertIs(inspect.unwrap(wrapper), func)
3461
3462 def test_unwrap_several(self):
3463 def func(a, b):
3464 return a + b
3465 wrapper = func
3466 for __ in range(10):
3467 @functools.wraps(wrapper)
3468 def wrapper():
3469 pass
3470 self.assertIsNot(wrapper.__wrapped__, func)
3471 self.assertIs(inspect.unwrap(wrapper), func)
3472
3473 def test_stop(self):
3474 def func1(a, b):
3475 return a + b
3476 @functools.wraps(func1)
3477 def func2():
3478 pass
3479 @functools.wraps(func2)
3480 def wrapper():
3481 pass
3482 func2.stop_here = 1
3483 unwrapped = inspect.unwrap(wrapper,
3484 stop=(lambda f: hasattr(f, "stop_here")))
3485 self.assertIs(unwrapped, func2)
3486
3487 def test_cycle(self):
3488 def func1(): pass
3489 func1.__wrapped__ = func1
3490 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3491 inspect.unwrap(func1)
3492
3493 def func2(): pass
3494 func2.__wrapped__ = func1
3495 func1.__wrapped__ = func2
3496 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3497 inspect.unwrap(func1)
3498 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3499 inspect.unwrap(func2)
3500
3501 def test_unhashable(self):
3502 def func(): pass
3503 func.__wrapped__ = None
3504 class C:
3505 __hash__ = None
3506 __wrapped__ = func
3507 self.assertIsNone(inspect.unwrap(C()))
3508
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003509class TestMain(unittest.TestCase):
3510 def test_only_source(self):
3511 module = importlib.import_module('unittest')
3512 rc, out, err = assert_python_ok('-m', 'inspect',
3513 'unittest')
3514 lines = out.decode().splitlines()
3515 # ignore the final newline
3516 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3517 self.assertEqual(err, b'')
3518
Yury Selivanov42407ab2014-06-23 10:23:50 -07003519 def test_custom_getattr(self):
3520 def foo():
3521 pass
3522 foo.__signature__ = 42
3523 with self.assertRaises(TypeError):
3524 inspect.signature(foo)
3525
Brett Cannon634a8fc2013-10-02 10:25:42 -04003526 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003527 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003528 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003529 rc, out, err = assert_python_ok('-m', 'inspect',
3530 'concurrent.futures:ThreadPoolExecutor')
3531 lines = out.decode().splitlines()
3532 # ignore the final newline
3533 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003534 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003535 self.assertEqual(err, b'')
3536
3537 def test_builtins(self):
3538 module = importlib.import_module('unittest')
3539 _, out, err = assert_python_failure('-m', 'inspect',
3540 'sys')
3541 lines = err.decode().splitlines()
3542 self.assertEqual(lines, ["Can't get info for builtin modules."])
3543
3544 def test_details(self):
3545 module = importlib.import_module('unittest')
3546 rc, out, err = assert_python_ok('-m', 'inspect',
3547 'unittest', '--details')
3548 output = out.decode()
3549 # Just a quick sanity check on the output
3550 self.assertIn(module.__name__, output)
3551 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003552 if not sys.flags.optimize:
3553 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003554 self.assertEqual(err, b'')
3555
3556
Yury Selivanovef1e7502014-12-08 16:05:34 -05003557class TestReload(unittest.TestCase):
3558
3559 src_before = textwrap.dedent("""\
3560def foo():
3561 print("Bla")
3562 """)
3563
3564 src_after = textwrap.dedent("""\
3565def foo():
3566 print("Oh no!")
3567 """)
3568
3569 def assertInspectEqual(self, path, source):
3570 inspected_src = inspect.getsource(source)
3571 with open(path) as src:
3572 self.assertEqual(
3573 src.read().splitlines(True),
3574 inspected_src.splitlines(True)
3575 )
3576
3577 def test_getsource_reload(self):
3578 # see issue 1218234
3579 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3580 module = importlib.import_module(name)
3581 self.assertInspectEqual(path, module)
3582 with open(path, 'w') as src:
3583 src.write(self.src_after)
3584 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003585
Nick Coghlane8c45d62013-07-28 20:00:01 +10003586
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003587def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003588 run_unittest(
3589 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3590 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3591 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003592 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003593 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003594 TestBoundArguments, TestSignaturePrivateHelpers,
3595 TestSignatureDefinitions,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003596 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
3597 TestGetCoroutineState
Michael Foord95fc51d2010-11-20 15:07:30 +00003598 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003599
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003600if __name__ == "__main__":
3601 test_main()