blob: a02f2e1b6069f2e91d8301495be3b9f5e3c97b70 [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
Yury Selivanova5d63dd2014-03-27 11:31:43 -040092
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000093class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +000094
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000095 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020096 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000097 self.istest(inspect.isbuiltin, 'sys.exit')
98 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +000099 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200100 try:
101 1/0
102 except:
103 tb = sys.exc_info()[2]
104 self.istest(inspect.isframe, 'tb.tb_frame')
105 self.istest(inspect.istraceback, 'tb')
106 if hasattr(types, 'GetSetDescriptorType'):
107 self.istest(inspect.isgetsetdescriptor,
108 'type(tb.tb_frame).f_locals')
109 else:
110 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
111 finally:
112 # Clear traceback and all the frames and local variables hanging to it.
113 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000114 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000115 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000116 self.istest(inspect.ismethod, 'git.argue')
117 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000118 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000119 self.istest(inspect.isgenerator, '(x for x in range(2))')
120 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400121
122 with warnings.catch_warnings():
123 warnings.simplefilter("ignore")
124 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
125 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
126
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000127 if hasattr(types, 'MemberDescriptorType'):
128 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
129 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000130 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000131
Yury Selivanov75445082015-05-11 22:57:16 -0400132 def test_iscoroutine(self):
133 gen_coro = gen_coroutine_function_example(1)
134 coro = coroutine_function_example(1)
135
Yury Selivanov5376ba92015-06-22 12:19:30 -0400136 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400137 inspect.iscoroutinefunction(gen_coroutine_function_example))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400138 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400139
140 self.assertTrue(
141 inspect.isgeneratorfunction(gen_coroutine_function_example))
142 self.assertTrue(inspect.isgenerator(gen_coro))
143
144 self.assertTrue(
145 inspect.iscoroutinefunction(coroutine_function_example))
146 self.assertTrue(inspect.iscoroutine(coro))
147
148 self.assertFalse(
149 inspect.isgeneratorfunction(coroutine_function_example))
150 self.assertFalse(inspect.isgenerator(coro))
151
152 coro.close(); gen_coro.close() # silence warnings
153
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400154 def test_isawaitable(self):
155 def gen(): yield
156 self.assertFalse(inspect.isawaitable(gen()))
157
158 coro = coroutine_function_example(1)
159 gen_coro = gen_coroutine_function_example(1)
160
161 self.assertTrue(inspect.isawaitable(coro))
162 self.assertTrue(inspect.isawaitable(gen_coro))
163
164 class Future:
165 def __await__():
166 pass
167 self.assertTrue(inspect.isawaitable(Future()))
168 self.assertFalse(inspect.isawaitable(Future))
169
170 class NotFuture: pass
171 not_fut = NotFuture()
172 not_fut.__await__ = lambda: None
173 self.assertFalse(inspect.isawaitable(not_fut))
174
175 coro.close(); gen_coro.close() # silence warnings
176
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000177 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000178 self.assertTrue(inspect.isroutine(mod.spam))
179 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000180
Benjamin Petersonc4656002009-01-17 22:41:18 +0000181 def test_isclass(self):
182 self.istest(inspect.isclass, 'mod.StupidGit')
183 self.assertTrue(inspect.isclass(list))
184
185 class CustomGetattr(object):
186 def __getattr__(self, attr):
187 return None
188 self.assertFalse(inspect.isclass(CustomGetattr()))
189
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000190 def test_get_slot_members(self):
191 class C(object):
192 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000193 x = C()
194 x.a = 42
195 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000196 self.assertIn('a', members)
197 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000198
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000199 def test_isabstract(self):
200 from abc import ABCMeta, abstractmethod
201
202 class AbstractClassExample(metaclass=ABCMeta):
203
204 @abstractmethod
205 def foo(self):
206 pass
207
208 class ClassExample(AbstractClassExample):
209 def foo(self):
210 pass
211
212 a = ClassExample()
213
214 # Test general behaviour.
215 self.assertTrue(inspect.isabstract(AbstractClassExample))
216 self.assertFalse(inspect.isabstract(ClassExample))
217 self.assertFalse(inspect.isabstract(a))
218 self.assertFalse(inspect.isabstract(int))
219 self.assertFalse(inspect.isabstract(5))
220
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000221
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000222class TestInterpreterStack(IsTestBase):
223 def __init__(self, *args, **kwargs):
224 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000225
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000226 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000227
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000228 def test_abuse_done(self):
229 self.istest(inspect.istraceback, 'git.ex[2]')
230 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000231
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000232 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000233 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000234 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000235 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000236 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000237 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000238 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000239 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000240 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000241 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400242 # Test named tuple fields
243 record = mod.st[0]
244 self.assertIs(record.frame, mod.fr)
245 self.assertEqual(record.lineno, 16)
246 self.assertEqual(record.filename, mod.__file__)
247 self.assertEqual(record.function, 'eggs')
248 self.assertIn('inspect.stack()', record.code_context[0])
249 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000250
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000251 def test_trace(self):
252 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000253 self.assertEqual(revise(*git.tr[0][1:]),
254 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
255 self.assertEqual(revise(*git.tr[1][1:]),
256 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
257 self.assertEqual(revise(*git.tr[2][1:]),
258 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000259
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000260 def test_frame(self):
261 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
262 self.assertEqual(args, ['x', 'y'])
263 self.assertEqual(varargs, None)
264 self.assertEqual(varkw, None)
265 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
266 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
267 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000268
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000269 def test_previous_frame(self):
270 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000271 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000272 self.assertEqual(varargs, 'g')
273 self.assertEqual(varkw, 'h')
274 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000275 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000276
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000277class GetSourceBase(unittest.TestCase):
278 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000279 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000280
Yury Selivanov6738b112015-05-16 10:10:21 -0400281 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000282 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000283 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000284
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000285 def sourcerange(self, top, bottom):
286 lines = self.source.split("\n")
287 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000288
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000289 def assertSourceEqual(self, obj, top, bottom):
290 self.assertEqual(inspect.getsource(obj),
291 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000292
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000293class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000294 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000295
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000296 def test_getclasses(self):
297 classes = inspect.getmembers(mod, inspect.isclass)
298 self.assertEqual(classes,
299 [('FesteringGob', mod.FesteringGob),
300 ('MalodorousPervert', mod.MalodorousPervert),
301 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300302 ('StupidGit', mod.StupidGit),
303 ('Tit', mod.MalodorousPervert),
304 ])
305 tree = inspect.getclasstree([cls[1] for cls in classes])
306 self.assertEqual(tree,
307 [(object, ()),
308 [(mod.ParrotDroppings, (object,)),
309 [(mod.FesteringGob, (mod.MalodorousPervert,
310 mod.ParrotDroppings))
311 ],
312 (mod.StupidGit, (object,)),
313 [(mod.MalodorousPervert, (mod.StupidGit,)),
314 [(mod.FesteringGob, (mod.MalodorousPervert,
315 mod.ParrotDroppings))
316 ]
317 ]
318 ]
319 ])
320 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000321 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000322 [(object, ()),
323 [(mod.ParrotDroppings, (object,)),
324 (mod.StupidGit, (object,)),
325 [(mod.MalodorousPervert, (mod.StupidGit,)),
326 [(mod.FesteringGob, (mod.MalodorousPervert,
327 mod.ParrotDroppings))
328 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000329 ]
330 ]
331 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000332
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000333 def test_getfunctions(self):
334 functions = inspect.getmembers(mod, inspect.isfunction)
335 self.assertEqual(functions, [('eggs', mod.eggs),
336 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000337
R. David Murray378c0cf2010-02-24 01:46:21 +0000338 @unittest.skipIf(sys.flags.optimize >= 2,
339 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000340 def test_getdoc(self):
341 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
342 self.assertEqual(inspect.getdoc(mod.StupidGit),
343 'A longer,\n\nindented\n\ndocstring.')
344 self.assertEqual(inspect.getdoc(git.abuse),
345 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000346
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300347 @unittest.skipIf(sys.flags.optimize >= 2,
348 "Docstrings are omitted with -O2 and above")
349 def test_getdoc_inherited(self):
350 self.assertEqual(inspect.getdoc(mod.FesteringGob),
351 'A longer,\n\nindented\n\ndocstring.')
352 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
353 'Another\n\ndocstring\n\ncontaining\n\ntabs')
354 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
355 'Another\n\ndocstring\n\ncontaining\n\ntabs')
356 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
357 'The automatic gainsaying.')
358
359 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
360 def test_finddoc(self):
361 finddoc = inspect._finddoc
362 self.assertEqual(finddoc(int), int.__doc__)
363 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
364 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
365 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
366 self.assertEqual(finddoc(int.real), int.real.__doc__)
367
Georg Brandl0c77a822008-06-10 16:37:50 +0000368 def test_cleandoc(self):
369 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
370 'An\nindented\ndocstring.')
371
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000372 def test_getcomments(self):
373 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
374 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000375
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000376 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000377 # Check actual module
378 self.assertEqual(inspect.getmodule(mod), mod)
379 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000380 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000381 # Check a method (no __module__ attribute, falls back to filename)
382 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
383 # Do it again (check the caching isn't broken)
384 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
385 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000386 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000387 # Check filename override
388 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000389
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000390 def test_getsource(self):
391 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300392 self.assertSourceEqual(mod.StupidGit, 21, 50)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000393
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000394 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000395 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
396 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000397 fn = "_non_existing_filename_used_for_sourcefile_test.py"
398 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000399 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000400 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200401 try:
402 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
403 finally:
404 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000405
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000406 def test_getfile(self):
407 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000408
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500409 def test_getfile_class_without_module(self):
410 class CM(type):
411 @property
412 def __module__(cls):
413 raise AttributeError
414 class C(metaclass=CM):
415 pass
416 with self.assertRaises(TypeError):
417 inspect.getfile(C)
418
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000419 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000420 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000421 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000422 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000423 m.__file__ = "<string>" # hopefully not a real filename...
424 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000425 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000426 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000427 del sys.modules[name]
428 inspect.getmodule(compile('a=10','','single'))
429
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500430 def test_proceed_with_fake_filename(self):
431 '''doctest monkeypatches linecache to enable inspection'''
432 fn, source = '<test>', 'def x(): pass\n'
433 getlines = linecache.getlines
434 def monkey(filename, module_globals=None):
435 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300436 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500437 else:
438 return getlines(filename, module_globals)
439 linecache.getlines = monkey
440 try:
441 ns = {}
442 exec(compile(source, fn, 'single'), ns)
443 inspect.getsource(ns["x"])
444 finally:
445 linecache.getlines = getlines
446
Antoine Pitroua8723a02015-04-15 00:41:29 +0200447 def test_getsource_on_code_object(self):
448 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
449
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000450class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000451 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000452
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000453 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000454 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000455
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000456 def test_replacing_decorator(self):
457 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000458
Yury Selivanov081bbf62014-09-26 17:34:54 -0400459 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200460 self.assertSourceEqual(mod2.real, 130, 132)
461
462 def test_decorator_with_lambda(self):
463 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400464
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000465class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000466 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000467 def test_oneline_lambda(self):
468 # Test inspect.getsource with a one-line lambda function.
469 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000470
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000471 def test_threeline_lambda(self):
472 # Test inspect.getsource with a three-line lambda function,
473 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000474 self.assertSourceEqual(mod2.tll, 28, 30)
475
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000476 def test_twoline_indented_lambda(self):
477 # Test inspect.getsource with a two-line lambda function,
478 # where the second line _is_ indented.
479 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000480
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000481 def test_onelinefunc(self):
482 # Test inspect.getsource with a regular one-line function.
483 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000484
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000485 def test_manyargs(self):
486 # Test inspect.getsource with a regular function where
487 # the arguments are on two lines and _not_ indented and
488 # the body on the second line with the last arguments.
489 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000490
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000491 def test_twolinefunc(self):
492 # Test inspect.getsource with a regular function where
493 # the body is on two lines, following the argument list and
494 # continued on the next line by a \\.
495 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000496
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000497 def test_lambda_in_list(self):
498 # Test inspect.getsource with a one-line lambda function
499 # defined in a list, indented.
500 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000501
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000502 def test_anonymous(self):
503 # Test inspect.getsource with a lambda function defined
504 # as argument to another function.
505 self.assertSourceEqual(mod2.anonymous, 55, 55)
506
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000507class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000508 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000509
510 def test_with_comment(self):
511 self.assertSourceEqual(mod2.with_comment, 58, 59)
512
513 def test_multiline_sig(self):
514 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
515
Armin Rigodd5c0232005-09-25 11:45:45 +0000516 def test_nested_class(self):
517 self.assertSourceEqual(mod2.func69().func71, 71, 72)
518
519 def test_one_liner_followed_by_non_name(self):
520 self.assertSourceEqual(mod2.func77, 77, 77)
521
522 def test_one_liner_dedent_non_name(self):
523 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
524
525 def test_with_comment_instead_of_docstring(self):
526 self.assertSourceEqual(mod2.func88, 88, 90)
527
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000528 def test_method_in_dynamic_class(self):
529 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
530
R David Murray32562d72014-10-03 11:15:38 -0400531 # This should not skip for CPython, but might on a repackaged python where
532 # unicodedata is not an external module, or on pypy.
533 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
534 unicodedata.__file__.endswith('.py'),
535 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000536 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200537 self.assertRaises(OSError, inspect.getsource, unicodedata)
538 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000539
R. David Murraya1b37402010-06-17 02:04:29 +0000540 def test_findsource_code_in_linecache(self):
541 lines = ["x=1"]
542 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200543 self.assertRaises(OSError, inspect.findsource, co)
544 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000545 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200546 try:
547 self.assertEqual(inspect.findsource(co), (lines,0))
548 self.assertEqual(inspect.getsource(co), lines[0])
549 finally:
550 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000551
Ezio Melotti1b145922013-03-30 05:17:24 +0200552 def test_findsource_without_filename(self):
553 for fname in ['', '<string>']:
554 co = compile('x=1', fname, "exec")
555 self.assertRaises(IOError, inspect.findsource, co)
556 self.assertRaises(IOError, inspect.getsource, co)
557
Antoine Pitroua8723a02015-04-15 00:41:29 +0200558 def test_getsource_on_method(self):
559 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
560
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000561class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400562 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000563 self.tempdir = TESTFN + '_dir'
564 os.mkdir(self.tempdir)
565 with open(os.path.join(self.tempdir,
566 'inspect_fodder3%spy' % os.extsep), 'w') as f:
567 f.write("class X:\n pass # No EOL")
568 with DirsOnSysPath(self.tempdir):
569 import inspect_fodder3 as mod3
570 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400571 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000572
573 def tearDown(self):
574 shutil.rmtree(self.tempdir)
575
576 def test_class(self):
577 self.assertSourceEqual(self.fodderModule.X, 1, 2)
578
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100579
580class _BrokenDataDescriptor(object):
581 """
582 A broken data descriptor. See bug #1785.
583 """
584 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700585 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100586
587 def __set__(*args):
588 raise RuntimeError
589
590 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700591 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100592
593
594class _BrokenMethodDescriptor(object):
595 """
596 A broken method descriptor. See bug #1785.
597 """
598 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700599 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100600
601 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700602 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100603
604
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000605# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000606def attrs_wo_objs(cls):
607 return [t[:3] for t in inspect.classify_class_attrs(cls)]
608
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100609
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000610class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000611 def test_newstyle_mro(self):
612 # The same w/ new-class MRO.
613 class A(object): pass
614 class B(A): pass
615 class C(A): pass
616 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000617
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000618 expected = (D, B, C, A, object)
619 got = inspect.getmro(D)
620 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000621
Christian Heimes3795b532007-11-08 13:48:53 +0000622 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
623 varkw_e=None, defaults_e=None, formatted=None):
Yury Selivanov3cfec2e2015-05-22 11:38:38 -0400624 with self.assertWarns(DeprecationWarning):
625 args, varargs, varkw, defaults = inspect.getargspec(routine)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000626 self.assertEqual(args, args_e)
627 self.assertEqual(varargs, varargs_e)
628 self.assertEqual(varkw, varkw_e)
629 self.assertEqual(defaults, defaults_e)
630 if formatted is not None:
631 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
632 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000633
Christian Heimes3795b532007-11-08 13:48:53 +0000634 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
635 varkw_e=None, defaults_e=None,
636 kwonlyargs_e=[], kwonlydefaults_e=None,
637 ann_e={}, formatted=None):
638 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
639 inspect.getfullargspec(routine)
640 self.assertEqual(args, args_e)
641 self.assertEqual(varargs, varargs_e)
642 self.assertEqual(varkw, varkw_e)
643 self.assertEqual(defaults, defaults_e)
644 self.assertEqual(kwonlyargs, kwonlyargs_e)
645 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
646 self.assertEqual(ann, ann_e)
647 if formatted is not None:
648 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
649 kwonlyargs, kwonlydefaults, ann),
650 formatted)
651
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000652 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000653 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000654
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000655 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000656 ['a', 'b', 'c', 'd', 'e', 'f'],
657 'g', 'h', (3, 4, 5),
658 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000659
Christian Heimes3795b532007-11-08 13:48:53 +0000660 self.assertRaises(ValueError, self.assertArgSpecEquals,
661 mod2.keyworded, [])
662
663 self.assertRaises(ValueError, self.assertArgSpecEquals,
664 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000665 self.assertRaises(ValueError, self.assertArgSpecEquals,
666 mod2.keyword_only_arg, [])
667
Christian Heimes3795b532007-11-08 13:48:53 +0000668
669 def test_getfullargspec(self):
670 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
671 kwonlyargs_e=['arg2'],
672 kwonlydefaults_e={'arg2':1},
673 formatted='(*arg1, arg2=1)')
674
675 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000676 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000677 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000678 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
679 kwonlyargs_e=['arg'],
680 formatted='(*, arg)')
681
Yury Selivanov57d240e2014-02-19 16:27:23 -0500682 def test_argspec_api_ignores_wrapped(self):
683 # Issue 20684: low level introspection API must ignore __wrapped__
684 @functools.wraps(mod.spam)
685 def ham(x, y):
686 pass
687 # Basic check
688 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
689 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
690 self.assertFullArgSpecEquals(functools.partial(ham),
691 ['x', 'y'], formatted='(x, y)')
692 # Other variants
693 def check_method(f):
694 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
695 formatted='(self, x, y)')
696 class C:
697 @functools.wraps(mod.spam)
698 def ham(self, x, y):
699 pass
700 pham = functools.partialmethod(ham)
701 @functools.wraps(mod.spam)
702 def __call__(self, x, y):
703 pass
704 check_method(C())
705 check_method(C.ham)
706 check_method(C().ham)
707 check_method(C.pham)
708 check_method(C().pham)
709
710 class C_new:
711 @functools.wraps(mod.spam)
712 def __new__(self, x, y):
713 pass
714 check_method(C_new)
715
716 class C_init:
717 @functools.wraps(mod.spam)
718 def __init__(self, x, y):
719 pass
720 check_method(C_init)
721
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500722 def test_getfullargspec_signature_attr(self):
723 def test():
724 pass
725 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
726 test.__signature__ = inspect.Signature(parameters=(spam_param,))
727
728 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
729
Yury Selivanov4cb93912014-01-29 11:54:12 -0500730 def test_getfullargspec_signature_annos(self):
731 def test(a:'spam') -> 'ham': pass
732 spec = inspect.getfullargspec(test)
733 self.assertEqual(test.__annotations__, spec.annotations)
734
735 def test(): pass
736 spec = inspect.getfullargspec(test)
737 self.assertEqual(test.__annotations__, spec.annotations)
738
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500739 @unittest.skipIf(MISSING_C_DOCSTRINGS,
740 "Signature information for builtins requires docstrings")
741 def test_getfullargspec_builtin_methods(self):
742 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
743 args_e=['self', 'obj'], formatted='(self, obj)')
744
745 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
746 args_e=['self', 'obj'], formatted='(self, obj)')
747
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500748 self.assertFullArgSpecEquals(
749 os.stat,
750 args_e=['path'],
751 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
752 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
753 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
754
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200755 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500756 @unittest.skipIf(MISSING_C_DOCSTRINGS,
757 "Signature information for builtins requires docstrings")
758 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200759 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500760 builtin = _testcapi.docstring_with_signature_with_defaults
761 spec = inspect.getfullargspec(builtin)
762 self.assertEqual(spec.defaults[0], 'avocado')
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_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200768 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500769 builtin = _testcapi.docstring_no_signature
770 with self.assertRaises(TypeError):
771 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000772
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000773 def test_getargspec_method(self):
774 class A(object):
775 def m(self):
776 pass
777 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000778
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000779 def test_classify_newstyle(self):
780 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000781
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000782 def s(): pass
783 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000784
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000785 def c(cls): pass
786 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000787
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000788 def getp(self): pass
789 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000790
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000791 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000792
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000793 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000794
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000795 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000796
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100797 dd = _BrokenDataDescriptor()
798 md = _BrokenMethodDescriptor()
799
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000800 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500801
802 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
803 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
804
Benjamin Peterson577473f2010-01-19 00:09:57 +0000805 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
806 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
807 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000808 self.assertIn(('m', 'method', A), attrs,
809 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000810 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
811 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100812 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
813 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000814
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000815 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000816
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000817 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000818
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000819 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000820 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
821 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
822 self.assertIn(('p', 'property', A), attrs, 'missing property')
823 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
824 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
825 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100826 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
827 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000828
829
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000830 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000831
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000832 def m(self): pass
833 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000834
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000835 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000836 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
837 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
838 self.assertIn(('p', 'property', A), attrs, 'missing property')
839 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
840 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
841 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100842 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
843 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000844
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000845 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000846
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000847 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000848
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000849 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000850 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
851 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
852 self.assertIn(('p', 'property', A), attrs, 'missing property')
853 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
854 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
855 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100856 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
857 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
858
859 def test_classify_builtin_types(self):
860 # Simple sanity check that all built-in types can have their
861 # attributes classified.
862 for name in dir(__builtins__):
863 builtin = getattr(__builtins__, name)
864 if isinstance(builtin, type):
865 inspect.classify_class_attrs(builtin)
866
Ethan Furman63c141c2013-10-18 00:27:39 -0700867 def test_classify_DynamicClassAttribute(self):
868 class Meta(type):
869 def __getattr__(self, name):
870 if name == 'ham':
871 return 'spam'
872 return super().__getattr__(name)
873 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700874 @types.DynamicClassAttribute
875 def ham(self):
876 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700877 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
878 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700879 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700880 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
881
Yury Selivanovbf341fb2015-05-21 15:41:57 -0400882 def test_classify_overrides_bool(self):
883 class NoBool(object):
884 def __eq__(self, other):
885 return NoBool()
886
887 def __bool__(self):
888 raise NotImplementedError(
889 "This object does not specify a boolean value")
890
891 class HasNB(object):
892 dd = NoBool()
893
894 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
895 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
896
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700897 def test_classify_metaclass_class_attribute(self):
898 class Meta(type):
899 fish = 'slap'
900 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200901 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700902 class Class(metaclass=Meta):
903 pass
904 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
905 self.assertIn(should_find, inspect.classify_class_attrs(Class))
906
Ethan Furman63c141c2013-10-18 00:27:39 -0700907 def test_classify_VirtualAttribute(self):
908 class Meta(type):
909 def __dir__(cls):
910 return ['__class__', '__module__', '__name__', 'BOOM']
911 def __getattr__(self, name):
912 if name =='BOOM':
913 return 42
914 return super().__getattr(name)
915 class Class(metaclass=Meta):
916 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700917 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700918 self.assertIn(should_find, inspect.classify_class_attrs(Class))
919
920 def test_classify_VirtualAttribute_multi_classes(self):
921 class Meta1(type):
922 def __dir__(cls):
923 return ['__class__', '__module__', '__name__', 'one']
924 def __getattr__(self, name):
925 if name =='one':
926 return 1
927 return super().__getattr__(name)
928 class Meta2(type):
929 def __dir__(cls):
930 return ['__class__', '__module__', '__name__', 'two']
931 def __getattr__(self, name):
932 if name =='two':
933 return 2
934 return super().__getattr__(name)
935 class Meta3(Meta1, Meta2):
936 def __dir__(cls):
937 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
938 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
939 def __getattr__(self, name):
940 if name =='three':
941 return 3
942 return super().__getattr__(name)
943 class Class1(metaclass=Meta1):
944 pass
945 class Class2(Class1, metaclass=Meta3):
946 pass
947
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700948 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
949 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
950 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700951 cca = inspect.classify_class_attrs(Class2)
952 for sf in (should_find1, should_find2, should_find3):
953 self.assertIn(sf, cca)
954
955 def test_classify_class_attrs_with_buggy_dir(self):
956 class M(type):
957 def __dir__(cls):
958 return ['__class__', '__name__', 'missing']
959 class C(metaclass=M):
960 pass
961 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
962 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700963
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100964 def test_getmembers_descriptors(self):
965 class A(object):
966 dd = _BrokenDataDescriptor()
967 md = _BrokenMethodDescriptor()
968
969 def pred_wrapper(pred):
970 # A quick'n'dirty way to discard standard attributes of new-style
971 # classes.
972 class Empty(object):
973 pass
974 def wrapped(x):
975 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
976 return False
977 return pred(x)
978 return wrapped
979
980 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
981 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
982
983 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
984 [('md', A.__dict__['md'])])
985 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
986 [('dd', A.__dict__['dd'])])
987
988 class B(A):
989 pass
990
991 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
992 [('md', A.__dict__['md'])])
993 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
994 [('dd', A.__dict__['dd'])])
995
Antoine Pitrou0c603812012-01-18 17:40:18 +0100996 def test_getmembers_method(self):
997 class B:
998 def f(self):
999 pass
1000
1001 self.assertIn(('f', B.f), inspect.getmembers(B))
1002 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1003 b = B()
1004 self.assertIn(('f', b.f), inspect.getmembers(b))
1005 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1006
Ethan Furmane03ea372013-09-25 07:14:41 -07001007 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001008 class M(type):
1009 def __getattr__(cls, name):
1010 if name == 'eggs':
1011 return 'scrambled'
1012 return super().__getattr__(name)
1013 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001014 @types.DynamicClassAttribute
1015 def eggs(self):
1016 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001017 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1018 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1019
1020 def test_getmembers_with_buggy_dir(self):
1021 class M(type):
1022 def __dir__(cls):
1023 return ['__class__', '__name__', 'missing']
1024 class C(metaclass=M):
1025 pass
1026 attrs = [a[0] for a in inspect.getmembers(C)]
1027 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001028
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001029
Nick Coghlan2f92e542012-06-23 19:39:55 +10001030_global_ref = object()
1031class TestGetClosureVars(unittest.TestCase):
1032
1033 def test_name_resolution(self):
1034 # Basic test of the 4 different resolution mechanisms
1035 def f(nonlocal_ref):
1036 def g(local_ref):
1037 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1038 return g
1039 _arg = object()
1040 nonlocal_vars = {"nonlocal_ref": _arg}
1041 global_vars = {"_global_ref": _global_ref}
1042 builtin_vars = {"print": print}
1043 unbound_names = {"unbound_ref"}
1044 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1045 builtin_vars, unbound_names)
1046 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1047
1048 def test_generator_closure(self):
1049 def f(nonlocal_ref):
1050 def g(local_ref):
1051 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1052 yield
1053 return g
1054 _arg = object()
1055 nonlocal_vars = {"nonlocal_ref": _arg}
1056 global_vars = {"_global_ref": _global_ref}
1057 builtin_vars = {"print": print}
1058 unbound_names = {"unbound_ref"}
1059 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1060 builtin_vars, unbound_names)
1061 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1062
1063 def test_method_closure(self):
1064 class C:
1065 def f(self, nonlocal_ref):
1066 def g(local_ref):
1067 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1068 return g
1069 _arg = object()
1070 nonlocal_vars = {"nonlocal_ref": _arg}
1071 global_vars = {"_global_ref": _global_ref}
1072 builtin_vars = {"print": print}
1073 unbound_names = {"unbound_ref"}
1074 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1075 builtin_vars, unbound_names)
1076 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1077
1078 def test_nonlocal_vars(self):
1079 # More complex tests of nonlocal resolution
1080 def _nonlocal_vars(f):
1081 return inspect.getclosurevars(f).nonlocals
1082
1083 def make_adder(x):
1084 def add(y):
1085 return x + y
1086 return add
1087
1088 def curry(func, arg1):
1089 return lambda arg2: func(arg1, arg2)
1090
1091 def less_than(a, b):
1092 return a < b
1093
1094 # The infamous Y combinator.
1095 def Y(le):
1096 def g(f):
1097 return le(lambda x: f(f)(x))
1098 Y.g_ref = g
1099 return g(g)
1100
1101 def check_y_combinator(func):
1102 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1103
1104 inc = make_adder(1)
1105 add_two = make_adder(2)
1106 greater_than_five = curry(less_than, 5)
1107
1108 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1109 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1110 self.assertEqual(_nonlocal_vars(greater_than_five),
1111 {'arg1': 5, 'func': less_than})
1112 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1113 {'x': 3})
1114 Y(check_y_combinator)
1115
1116 def test_getclosurevars_empty(self):
1117 def foo(): pass
1118 _empty = inspect.ClosureVars({}, {}, {}, set())
1119 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1120 self.assertEqual(inspect.getclosurevars(foo), _empty)
1121
1122 def test_getclosurevars_error(self):
1123 class T: pass
1124 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1125 self.assertRaises(TypeError, inspect.getclosurevars, list)
1126 self.assertRaises(TypeError, inspect.getclosurevars, {})
1127
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001128 def _private_globals(self):
1129 code = """def f(): print(path)"""
1130 ns = {}
1131 exec(code, ns)
1132 return ns["f"], ns
1133
1134 def test_builtins_fallback(self):
1135 f, ns = self._private_globals()
1136 ns.pop("__builtins__", None)
1137 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1138 self.assertEqual(inspect.getclosurevars(f), expected)
1139
1140 def test_builtins_as_dict(self):
1141 f, ns = self._private_globals()
1142 ns["__builtins__"] = {"path":1}
1143 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1144 self.assertEqual(inspect.getclosurevars(f), expected)
1145
1146 def test_builtins_as_module(self):
1147 f, ns = self._private_globals()
1148 ns["__builtins__"] = os
1149 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1150 self.assertEqual(inspect.getclosurevars(f), expected)
1151
Nick Coghlan2f92e542012-06-23 19:39:55 +10001152
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001153class TestGetcallargsFunctions(unittest.TestCase):
1154
1155 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1156 locs = dict(locs or {}, func=func)
1157 r1 = eval('func(%s)' % call_params_string, None, locs)
1158 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1159 locs)
1160 self.assertEqual(r1, r2)
1161
1162 def assertEqualException(self, func, call_param_string, locs=None):
1163 locs = dict(locs or {}, func=func)
1164 try:
1165 eval('func(%s)' % call_param_string, None, locs)
1166 except Exception as e:
1167 ex1 = e
1168 else:
1169 self.fail('Exception not raised')
1170 try:
1171 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1172 locs)
1173 except Exception as e:
1174 ex2 = e
1175 else:
1176 self.fail('Exception not raised')
1177 self.assertIs(type(ex1), type(ex2))
1178 self.assertEqual(str(ex1), str(ex2))
1179 del ex1, ex2
1180
1181 def makeCallable(self, signature):
1182 """Create a function that returns its locals()"""
1183 code = "lambda %s: locals()"
1184 return eval(code % signature)
1185
1186 def test_plain(self):
1187 f = self.makeCallable('a, b=1')
1188 self.assertEqualCallArgs(f, '2')
1189 self.assertEqualCallArgs(f, '2, 3')
1190 self.assertEqualCallArgs(f, 'a=2')
1191 self.assertEqualCallArgs(f, 'b=3, a=2')
1192 self.assertEqualCallArgs(f, '2, b=3')
1193 # expand *iterable / **mapping
1194 self.assertEqualCallArgs(f, '*(2,)')
1195 self.assertEqualCallArgs(f, '*[2]')
1196 self.assertEqualCallArgs(f, '*(2, 3)')
1197 self.assertEqualCallArgs(f, '*[2, 3]')
1198 self.assertEqualCallArgs(f, '**{"a":2}')
1199 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1200 self.assertEqualCallArgs(f, '2, **{"b":3}')
1201 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1202 # expand UserList / UserDict
1203 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1204 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1205 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1206 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1207 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1208
1209 def test_varargs(self):
1210 f = self.makeCallable('a, b=1, *c')
1211 self.assertEqualCallArgs(f, '2')
1212 self.assertEqualCallArgs(f, '2, 3')
1213 self.assertEqualCallArgs(f, '2, 3, 4')
1214 self.assertEqualCallArgs(f, '*(2,3,4)')
1215 self.assertEqualCallArgs(f, '2, *[3,4]')
1216 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1217
1218 def test_varkw(self):
1219 f = self.makeCallable('a, b=1, **c')
1220 self.assertEqualCallArgs(f, 'a=2')
1221 self.assertEqualCallArgs(f, '2, b=3, c=4')
1222 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1223 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1224 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1225 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1226 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1227 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1228 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1229
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001230 def test_varkw_only(self):
1231 # issue11256:
1232 f = self.makeCallable('**c')
1233 self.assertEqualCallArgs(f, '')
1234 self.assertEqualCallArgs(f, 'a=1')
1235 self.assertEqualCallArgs(f, 'a=1, b=2')
1236 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1237 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1238 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1239
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001240 def test_keyword_only(self):
1241 f = self.makeCallable('a=3, *, c, d=2')
1242 self.assertEqualCallArgs(f, 'c=3')
1243 self.assertEqualCallArgs(f, 'c=3, a=3')
1244 self.assertEqualCallArgs(f, 'a=2, c=4')
1245 self.assertEqualCallArgs(f, '4, c=4')
1246 self.assertEqualException(f, '')
1247 self.assertEqualException(f, '3')
1248 self.assertEqualException(f, 'a=3')
1249 self.assertEqualException(f, 'd=4')
1250
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001251 f = self.makeCallable('*, c, d=2')
1252 self.assertEqualCallArgs(f, 'c=3')
1253 self.assertEqualCallArgs(f, 'c=3, d=4')
1254 self.assertEqualCallArgs(f, 'd=4, c=3')
1255
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001256 def test_multiple_features(self):
1257 f = self.makeCallable('a, b=2, *f, **g')
1258 self.assertEqualCallArgs(f, '2, 3, 7')
1259 self.assertEqualCallArgs(f, '2, 3, x=8')
1260 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1261 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1262 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1263 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1264 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1265 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1266 '(4,[5,6])]), **collections.UserDict('
1267 'y=9, z=10)')
1268
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001269 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1270 self.assertEqualCallArgs(f, '2, 3, x=8')
1271 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1272 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1273 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1274 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1275 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1276 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1277 '(4,[5,6])]), q=0, **collections.UserDict('
1278 'y=9, z=10)')
1279
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001280 def test_errors(self):
1281 f0 = self.makeCallable('')
1282 f1 = self.makeCallable('a, b')
1283 f2 = self.makeCallable('a, b=1')
1284 # f0 takes no arguments
1285 self.assertEqualException(f0, '1')
1286 self.assertEqualException(f0, 'x=1')
1287 self.assertEqualException(f0, '1,x=1')
1288 # f1 takes exactly 2 arguments
1289 self.assertEqualException(f1, '')
1290 self.assertEqualException(f1, '1')
1291 self.assertEqualException(f1, 'a=2')
1292 self.assertEqualException(f1, 'b=3')
1293 # f2 takes at least 1 argument
1294 self.assertEqualException(f2, '')
1295 self.assertEqualException(f2, 'b=3')
1296 for f in f1, f2:
1297 # f1/f2 takes exactly/at most 2 arguments
1298 self.assertEqualException(f, '2, 3, 4')
1299 self.assertEqualException(f, '1, 2, 3, a=1')
1300 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001301 # XXX: success of this one depends on dict order
1302 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001303 # f got an unexpected keyword argument
1304 self.assertEqualException(f, 'c=2')
1305 self.assertEqualException(f, '2, c=3')
1306 self.assertEqualException(f, '2, 3, c=4')
1307 self.assertEqualException(f, '2, c=4, b=3')
1308 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1309 # f got multiple values for keyword argument
1310 self.assertEqualException(f, '1, a=2')
1311 self.assertEqualException(f, '1, **{"a":2}')
1312 self.assertEqualException(f, '1, 2, b=3')
1313 # XXX: Python inconsistency
1314 # - for functions and bound methods: unexpected keyword 'c'
1315 # - for unbound methods: multiple values for keyword 'a'
1316 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001317 # issue11256:
1318 f3 = self.makeCallable('**c')
1319 self.assertEqualException(f3, '1, 2')
1320 self.assertEqualException(f3, '1, 2, a=1, b=2')
1321 f4 = self.makeCallable('*, a, b=0')
1322 self.assertEqualException(f3, '1, 2')
1323 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001324
Yury Selivanov875df202014-03-27 18:23:03 -04001325 # issue #20816: getcallargs() fails to iterate over non-existent
1326 # kwonlydefaults and raises a wrong TypeError
1327 def f5(*, a): pass
1328 with self.assertRaisesRegex(TypeError,
1329 'missing 1 required keyword-only'):
1330 inspect.getcallargs(f5)
1331
1332
Yury Selivanovdccfa132014-03-27 18:42:52 -04001333 # issue20817:
1334 def f6(a, b, c):
1335 pass
1336 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1337 inspect.getcallargs(f6)
1338
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001339class TestGetcallargsMethods(TestGetcallargsFunctions):
1340
1341 def setUp(self):
1342 class Foo(object):
1343 pass
1344 self.cls = Foo
1345 self.inst = Foo()
1346
1347 def makeCallable(self, signature):
1348 assert 'self' not in signature
1349 mk = super(TestGetcallargsMethods, self).makeCallable
1350 self.cls.method = mk('self, ' + signature)
1351 return self.inst.method
1352
1353class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1354
1355 def makeCallable(self, signature):
1356 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1357 return self.cls.method
1358
1359 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1360 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1361 *self._getAssertEqualParams(func, call_params_string, locs))
1362
1363 def assertEqualException(self, func, call_params_string, locs=None):
1364 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1365 *self._getAssertEqualParams(func, call_params_string, locs))
1366
1367 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1368 assert 'inst' not in call_params_string
1369 locs = dict(locs or {}, inst=self.inst)
1370 return (func, 'inst,' + call_params_string, locs)
1371
Michael Foord95fc51d2010-11-20 15:07:30 +00001372
1373class TestGetattrStatic(unittest.TestCase):
1374
1375 def test_basic(self):
1376 class Thing(object):
1377 x = object()
1378
1379 thing = Thing()
1380 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1381 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1382 with self.assertRaises(AttributeError):
1383 inspect.getattr_static(thing, 'y')
1384
1385 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1386
1387 def test_inherited(self):
1388 class Thing(object):
1389 x = object()
1390 class OtherThing(Thing):
1391 pass
1392
1393 something = OtherThing()
1394 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1395
1396 def test_instance_attr(self):
1397 class Thing(object):
1398 x = 2
1399 def __init__(self, x):
1400 self.x = x
1401 thing = Thing(3)
1402 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1403 del thing.x
1404 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1405
1406 def test_property(self):
1407 class Thing(object):
1408 @property
1409 def x(self):
1410 raise AttributeError("I'm pretending not to exist")
1411 thing = Thing()
1412 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1413
Ezio Melotti75cbd732011-04-28 00:59:29 +03001414 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001415 class descriptor(object):
1416 def __get__(*_):
1417 raise AttributeError("I'm pretending not to exist")
1418 desc = descriptor()
1419 class Thing(object):
1420 x = desc
1421 thing = Thing()
1422 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1423
1424 def test_classAttribute(self):
1425 class Thing(object):
1426 x = object()
1427
1428 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1429
Ethan Furmane03ea372013-09-25 07:14:41 -07001430 def test_classVirtualAttribute(self):
1431 class Thing(object):
1432 @types.DynamicClassAttribute
1433 def x(self):
1434 return self._x
1435 _x = object()
1436
1437 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1438
Michael Foord95fc51d2010-11-20 15:07:30 +00001439 def test_inherited_classattribute(self):
1440 class Thing(object):
1441 x = object()
1442 class OtherThing(Thing):
1443 pass
1444
1445 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1446
1447 def test_slots(self):
1448 class Thing(object):
1449 y = 'bar'
1450 __slots__ = ['x']
1451 def __init__(self):
1452 self.x = 'foo'
1453 thing = Thing()
1454 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1455 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1456
1457 del thing.x
1458 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1459
1460 def test_metaclass(self):
1461 class meta(type):
1462 attr = 'foo'
1463 class Thing(object, metaclass=meta):
1464 pass
1465 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1466
1467 class sub(meta):
1468 pass
1469 class OtherThing(object, metaclass=sub):
1470 x = 3
1471 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1472
1473 class OtherOtherThing(OtherThing):
1474 pass
1475 # this test is odd, but it was added as it exposed a bug
1476 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1477
1478 def test_no_dict_no_slots(self):
1479 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1480 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1481
1482 def test_no_dict_no_slots_instance_member(self):
1483 # returns descriptor
1484 with open(__file__) as handle:
1485 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1486
1487 def test_inherited_slots(self):
1488 # returns descriptor
1489 class Thing(object):
1490 __slots__ = ['x']
1491 def __init__(self):
1492 self.x = 'foo'
1493
1494 class OtherThing(Thing):
1495 pass
1496 # it would be nice if this worked...
1497 # we get the descriptor instead of the instance attribute
1498 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1499
1500 def test_descriptor(self):
1501 class descriptor(object):
1502 def __get__(self, instance, owner):
1503 return 3
1504 class Foo(object):
1505 d = descriptor()
1506
1507 foo = Foo()
1508
1509 # for a non data descriptor we return the instance attribute
1510 foo.__dict__['d'] = 1
1511 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1512
1513 # if the descriptor is a data-desciptor we should return the
1514 # descriptor
1515 descriptor.__set__ = lambda s, i, v: None
1516 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1517
1518
1519 def test_metaclass_with_descriptor(self):
1520 class descriptor(object):
1521 def __get__(self, instance, owner):
1522 return 3
1523 class meta(type):
1524 d = descriptor()
1525 class Thing(object, metaclass=meta):
1526 pass
1527 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1528
1529
Michael Foordcc7ebb82010-11-20 16:20:16 +00001530 def test_class_as_property(self):
1531 class Base(object):
1532 foo = 3
1533
1534 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001535 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001536 @property
1537 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001538 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001539 return object
1540
Michael Foord35184ed2010-11-20 16:58:30 +00001541 instance = Something()
1542 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1543 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001544 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1545
Michael Foorde5162652010-11-20 16:40:44 +00001546 def test_mro_as_property(self):
1547 class Meta(type):
1548 @property
1549 def __mro__(self):
1550 return (object,)
1551
1552 class Base(object):
1553 foo = 3
1554
1555 class Something(Base, metaclass=Meta):
1556 pass
1557
1558 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1559 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1560
Michael Foorddcebe0f2011-03-15 19:20:44 -04001561 def test_dict_as_property(self):
1562 test = self
1563 test.called = False
1564
1565 class Foo(dict):
1566 a = 3
1567 @property
1568 def __dict__(self):
1569 test.called = True
1570 return {}
1571
1572 foo = Foo()
1573 foo.a = 4
1574 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1575 self.assertFalse(test.called)
1576
1577 def test_custom_object_dict(self):
1578 test = self
1579 test.called = False
1580
1581 class Custom(dict):
1582 def get(self, key, default=None):
1583 test.called = True
1584 super().get(key, default)
1585
1586 class Foo(object):
1587 a = 3
1588 foo = Foo()
1589 foo.__dict__ = Custom()
1590 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1591 self.assertFalse(test.called)
1592
1593 def test_metaclass_dict_as_property(self):
1594 class Meta(type):
1595 @property
1596 def __dict__(self):
1597 self.executed = True
1598
1599 class Thing(metaclass=Meta):
1600 executed = False
1601
1602 def __init__(self):
1603 self.spam = 42
1604
1605 instance = Thing()
1606 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1607 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001608
Michael Foorda51623b2011-12-18 22:01:40 +00001609 def test_module(self):
1610 sentinel = object()
1611 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1612 sentinel)
1613
Michael Foord3ba95f82011-12-22 01:13:37 +00001614 def test_metaclass_with_metaclass_with_dict_as_property(self):
1615 class MetaMeta(type):
1616 @property
1617 def __dict__(self):
1618 self.executed = True
1619 return dict(spam=42)
1620
1621 class Meta(type, metaclass=MetaMeta):
1622 executed = False
1623
1624 class Thing(metaclass=Meta):
1625 pass
1626
1627 with self.assertRaises(AttributeError):
1628 inspect.getattr_static(Thing, "spam")
1629 self.assertFalse(Thing.executed)
1630
Nick Coghlane0f04652010-11-21 03:44:04 +00001631class TestGetGeneratorState(unittest.TestCase):
1632
1633 def setUp(self):
1634 def number_generator():
1635 for number in range(5):
1636 yield number
1637 self.generator = number_generator()
1638
1639 def _generatorstate(self):
1640 return inspect.getgeneratorstate(self.generator)
1641
1642 def test_created(self):
1643 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1644
1645 def test_suspended(self):
1646 next(self.generator)
1647 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1648
1649 def test_closed_after_exhaustion(self):
1650 for i in self.generator:
1651 pass
1652 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1653
1654 def test_closed_after_immediate_exception(self):
1655 with self.assertRaises(RuntimeError):
1656 self.generator.throw(RuntimeError)
1657 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1658
1659 def test_running(self):
1660 # As mentioned on issue #10220, checking for the RUNNING state only
1661 # makes sense inside the generator itself.
1662 # The following generator checks for this by using the closure's
1663 # reference to self and the generator state checking helper method
1664 def running_check_generator():
1665 for number in range(5):
1666 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1667 yield number
1668 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1669 self.generator = running_check_generator()
1670 # Running up to the first yield
1671 next(self.generator)
1672 # Running after the first yield
1673 next(self.generator)
1674
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001675 def test_easy_debugging(self):
1676 # repr() and str() of a generator state should contain the state name
1677 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1678 for name in names:
1679 state = getattr(inspect, name)
1680 self.assertIn(name, repr(state))
1681 self.assertIn(name, str(state))
1682
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001683 def test_getgeneratorlocals(self):
1684 def each(lst, a=None):
1685 b=(1, 2, 3)
1686 for v in lst:
1687 if v == 3:
1688 c = 12
1689 yield v
1690
1691 numbers = each([1, 2, 3])
1692 self.assertEqual(inspect.getgeneratorlocals(numbers),
1693 {'a': None, 'lst': [1, 2, 3]})
1694 next(numbers)
1695 self.assertEqual(inspect.getgeneratorlocals(numbers),
1696 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1697 'b': (1, 2, 3)})
1698 next(numbers)
1699 self.assertEqual(inspect.getgeneratorlocals(numbers),
1700 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1701 'b': (1, 2, 3)})
1702 next(numbers)
1703 self.assertEqual(inspect.getgeneratorlocals(numbers),
1704 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1705 'b': (1, 2, 3), 'c': 12})
1706 try:
1707 next(numbers)
1708 except StopIteration:
1709 pass
1710 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1711
1712 def test_getgeneratorlocals_empty(self):
1713 def yield_one():
1714 yield 1
1715 one = yield_one()
1716 self.assertEqual(inspect.getgeneratorlocals(one), {})
1717 try:
1718 next(one)
1719 except StopIteration:
1720 pass
1721 self.assertEqual(inspect.getgeneratorlocals(one), {})
1722
1723 def test_getgeneratorlocals_error(self):
1724 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1725 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1726 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1727 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1728
Nick Coghlane0f04652010-11-21 03:44:04 +00001729
Yury Selivanov5376ba92015-06-22 12:19:30 -04001730class TestGetCoroutineState(unittest.TestCase):
1731
1732 def setUp(self):
1733 @types.coroutine
1734 def number_coroutine():
1735 for number in range(5):
1736 yield number
1737 async def coroutine():
1738 await number_coroutine()
1739 self.coroutine = coroutine()
1740
1741 def tearDown(self):
1742 self.coroutine.close()
1743
1744 def _coroutinestate(self):
1745 return inspect.getcoroutinestate(self.coroutine)
1746
1747 def test_created(self):
1748 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1749
1750 def test_suspended(self):
1751 self.coroutine.send(None)
1752 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1753
1754 def test_closed_after_exhaustion(self):
1755 while True:
1756 try:
1757 self.coroutine.send(None)
1758 except StopIteration:
1759 break
1760
1761 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1762
1763 def test_closed_after_immediate_exception(self):
1764 with self.assertRaises(RuntimeError):
1765 self.coroutine.throw(RuntimeError)
1766 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1767
1768 def test_easy_debugging(self):
1769 # repr() and str() of a coroutine state should contain the state name
1770 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1771 for name in names:
1772 state = getattr(inspect, name)
1773 self.assertIn(name, repr(state))
1774 self.assertIn(name, str(state))
1775
1776 def test_getcoroutinelocals(self):
1777 @types.coroutine
1778 def gencoro():
1779 yield
1780
1781 gencoro = gencoro()
1782 async def func(a=None):
1783 b = 'spam'
1784 await gencoro
1785
1786 coro = func()
1787 self.assertEqual(inspect.getcoroutinelocals(coro),
1788 {'a': None, 'gencoro': gencoro})
1789 coro.send(None)
1790 self.assertEqual(inspect.getcoroutinelocals(coro),
1791 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
1792
1793
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001794class MySignature(inspect.Signature):
1795 # Top-level to make it picklable;
1796 # used in test_signature_object_pickle
1797 pass
1798
1799class MyParameter(inspect.Parameter):
1800 # Top-level to make it picklable;
1801 # used in test_signature_object_pickle
1802 pass
1803
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001804
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001805
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001806class TestSignatureObject(unittest.TestCase):
1807 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04001808 def signature(func, **kw):
1809 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001810 return (tuple((param.name,
1811 (... if param.default is param.empty else param.default),
1812 (... if param.annotation is param.empty
1813 else param.annotation),
1814 str(param.kind).lower())
1815 for param in sig.parameters.values()),
1816 (... if sig.return_annotation is sig.empty
1817 else sig.return_annotation))
1818
1819 def test_signature_object(self):
1820 S = inspect.Signature
1821 P = inspect.Parameter
1822
1823 self.assertEqual(str(S()), '()')
1824
Yury Selivanov07a9e452014-01-29 10:58:16 -05001825 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001826 pass
1827 sig = inspect.signature(test)
1828 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001829 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001830 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001831 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001832 args = sig.parameters['args']
1833 ko = sig.parameters['ko']
1834 kwargs = sig.parameters['kwargs']
1835
1836 S((po, pk, args, ko, kwargs))
1837
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001838 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001839 S((pk, po, args, ko, kwargs))
1840
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001841 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001842 S((po, args, pk, ko, kwargs))
1843
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001844 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001845 S((args, po, pk, 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((po, pk, args, kwargs, ko))
1849
1850 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001851 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001852 S((po, pk, args, kwargs2, ko))
1853
Yury Selivanov07a9e452014-01-29 10:58:16 -05001854 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1855 S((pod, po))
1856
1857 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1858 S((po, pkd, pk))
1859
1860 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1861 S((pkd, pk))
1862
Yury Selivanov374375d2014-03-27 12:41:53 -04001863 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04001864 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04001865
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001866 def test_signature_object_pickle(self):
1867 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1868 foo_partial = functools.partial(foo, a=1)
1869
1870 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001871
1872 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1873 with self.subTest(pickle_ver=ver, subclass=False):
1874 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1875 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001876
1877 # Test that basic sub-classing works
1878 sig = inspect.signature(foo)
1879 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1880 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1881 mysig = MySignature().replace(parameters=myparams.values(),
1882 return_annotation=sig.return_annotation)
1883 self.assertTrue(isinstance(mysig, MySignature))
1884 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1885
1886 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1887 with self.subTest(pickle_ver=ver, subclass=True):
1888 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1889 self.assertEqual(mysig, sig_pickled)
1890 self.assertTrue(isinstance(sig_pickled, MySignature))
1891 self.assertTrue(isinstance(sig_pickled.parameters['z'],
1892 MyParameter))
1893
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001894 def test_signature_immutability(self):
1895 def test(a):
1896 pass
1897 sig = inspect.signature(test)
1898
1899 with self.assertRaises(AttributeError):
1900 sig.foo = 'bar'
1901
1902 with self.assertRaises(TypeError):
1903 sig.parameters['a'] = None
1904
1905 def test_signature_on_noarg(self):
1906 def test():
1907 pass
1908 self.assertEqual(self.signature(test), ((), ...))
1909
1910 def test_signature_on_wargs(self):
1911 def test(a, b:'foo') -> 123:
1912 pass
1913 self.assertEqual(self.signature(test),
1914 ((('a', ..., ..., "positional_or_keyword"),
1915 ('b', ..., 'foo', "positional_or_keyword")),
1916 123))
1917
1918 def test_signature_on_wkwonly(self):
1919 def test(*, a:float, b:str) -> int:
1920 pass
1921 self.assertEqual(self.signature(test),
1922 ((('a', ..., float, "keyword_only"),
1923 ('b', ..., str, "keyword_only")),
1924 int))
1925
1926 def test_signature_on_complex_args(self):
1927 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1928 pass
1929 self.assertEqual(self.signature(test),
1930 ((('a', ..., ..., "positional_or_keyword"),
1931 ('b', 10, 'foo', "positional_or_keyword"),
1932 ('args', ..., 'bar', "var_positional"),
1933 ('spam', ..., 'baz', "keyword_only"),
1934 ('ham', 123, ..., "keyword_only"),
1935 ('kwargs', ..., int, "var_keyword")),
1936 ...))
1937
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001938 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001939 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1940 "Signature information for builtins requires docstrings")
1941 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001942 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001943
Larry Hastings5c661892014-01-24 06:17:25 -08001944 def test_unbound_method(o):
1945 """Use this to test unbound methods (things that should have a self)"""
1946 signature = inspect.signature(o)
1947 self.assertTrue(isinstance(signature, inspect.Signature))
1948 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1949 return signature
1950
1951 def test_callable(o):
1952 """Use this to test bound methods or normal callables (things that don't expect self)"""
1953 signature = inspect.signature(o)
1954 self.assertTrue(isinstance(signature, inspect.Signature))
1955 if signature.parameters:
1956 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1957 return signature
1958
1959 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001960 def p(name): return signature.parameters[name].default
1961 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001962 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001963 self.assertEqual(p('d'), 3.14)
1964 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001965 self.assertEqual(p('n'), None)
1966 self.assertEqual(p('t'), True)
1967 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001968 self.assertEqual(p('local'), 3)
1969 self.assertEqual(p('sys'), sys.maxsize)
1970 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001971
Larry Hastings5c661892014-01-24 06:17:25 -08001972 test_callable(object)
1973
1974 # normal method
1975 # (PyMethodDescr_Type, "method_descriptor")
1976 test_unbound_method(_pickle.Pickler.dump)
1977 d = _pickle.Pickler(io.StringIO())
1978 test_callable(d.dump)
1979
1980 # static method
1981 test_callable(str.maketrans)
1982 test_callable('abc'.maketrans)
1983
1984 # class method
1985 test_callable(dict.fromkeys)
1986 test_callable({}.fromkeys)
1987
1988 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1989 test_unbound_method(type.__call__)
1990 test_unbound_method(int.__add__)
1991 test_callable((3).__add__)
1992
1993 # _PyMethodWrapper_Type
1994 # support for 'method-wrapper'
1995 test_callable(min.__call__)
1996
Larry Hastings2623c8c2014-02-08 22:15:29 -08001997 # This doesn't work now.
1998 # (We don't have a valid signature for "type" in 3.4)
1999 with self.assertRaisesRegex(ValueError, "no signature found"):
2000 class ThisWorksNow:
2001 __call__ = type
2002 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002003
Yury Selivanov056e2652014-03-02 12:25:27 -05002004 # Regression test for issue #20786
2005 test_unbound_method(dict.__delitem__)
2006 test_unbound_method(property.__delete__)
2007
Zachary Ware8ef887c2015-04-13 18:22:35 -05002008 # Regression test for issue #20586
2009 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2010
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002011 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002012 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2013 "Signature information for builtins requires docstrings")
2014 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002015 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002016 func = _testcapi.docstring_with_signature_with_defaults
2017
2018 def decorator(func):
2019 @functools.wraps(func)
2020 def wrapper(*args, **kwargs) -> int:
2021 return func(*args, **kwargs)
2022 return wrapper
2023
2024 decorated_func = decorator(func)
2025
2026 self.assertEqual(inspect.signature(func),
2027 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002028
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002029 def wrapper_like(*args, **kwargs) -> int: pass
2030 self.assertEqual(inspect.signature(decorated_func,
2031 follow_wrapped=False),
2032 inspect.signature(wrapper_like))
2033
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002034 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002035 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002036 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002037 with self.assertRaisesRegex(ValueError,
2038 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002039 inspect.signature(_testcapi.docstring_no_signature)
2040
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002041 with self.assertRaisesRegex(ValueError,
2042 'no signature found for builtin'):
2043 inspect.signature(str)
2044
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002045 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002046 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002047 inspect.signature(42)
2048
Yury Selivanov63da7c72014-01-31 14:48:37 -05002049 def test_signature_from_functionlike_object(self):
2050 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2051 pass
2052
2053 class funclike:
2054 # Has to be callable, and have correct
2055 # __code__, __annotations__, __defaults__, __name__,
2056 # and __kwdefaults__ attributes
2057
2058 def __init__(self, func):
2059 self.__name__ = func.__name__
2060 self.__code__ = func.__code__
2061 self.__annotations__ = func.__annotations__
2062 self.__defaults__ = func.__defaults__
2063 self.__kwdefaults__ = func.__kwdefaults__
2064 self.func = func
2065
2066 def __call__(self, *args, **kwargs):
2067 return self.func(*args, **kwargs)
2068
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002069 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002070
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002071 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002072 self.assertEqual(sig_funclike, sig_func)
2073
2074 sig_funclike = inspect.signature(funclike(func))
2075 self.assertEqual(sig_funclike, sig_func)
2076
2077 # If object is not a duck type of function, then
2078 # signature will try to get a signature for its '__call__'
2079 # method
2080 fl = funclike(func)
2081 del fl.__defaults__
2082 self.assertEqual(self.signature(fl),
2083 ((('args', ..., ..., "var_positional"),
2084 ('kwargs', ..., ..., "var_keyword")),
2085 ...))
2086
Yury Selivanova773de02014-02-21 18:30:53 -05002087 # Test with cython-like builtins:
2088 _orig_isdesc = inspect.ismethoddescriptor
2089 def _isdesc(obj):
2090 if hasattr(obj, '_builtinmock'):
2091 return True
2092 return _orig_isdesc(obj)
2093
2094 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2095 builtin_func = funclike(func)
2096 # Make sure that our mock setup is working
2097 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2098 builtin_func._builtinmock = True
2099 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2100 self.assertEqual(inspect.signature(builtin_func), sig_func)
2101
Yury Selivanov63da7c72014-01-31 14:48:37 -05002102 def test_signature_functionlike_class(self):
2103 # We only want to duck type function-like objects,
2104 # not classes.
2105
2106 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2107 pass
2108
2109 class funclike:
2110 def __init__(self, marker):
2111 pass
2112
2113 __name__ = func.__name__
2114 __code__ = func.__code__
2115 __annotations__ = func.__annotations__
2116 __defaults__ = func.__defaults__
2117 __kwdefaults__ = func.__kwdefaults__
2118
Yury Selivanov63da7c72014-01-31 14:48:37 -05002119 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2120
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002121 def test_signature_on_method(self):
2122 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002123 def __init__(*args):
2124 pass
2125 def m1(self, arg1, arg2=1) -> int:
2126 pass
2127 def m2(*args):
2128 pass
2129 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002130 pass
2131
Yury Selivanov62560fb2014-01-28 12:26:24 -05002132 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002133 ((('arg1', ..., ..., "positional_or_keyword"),
2134 ('arg2', 1, ..., "positional_or_keyword")),
2135 int))
2136
Yury Selivanov62560fb2014-01-28 12:26:24 -05002137 self.assertEqual(self.signature(Test().m2),
2138 ((('args', ..., ..., "var_positional"),),
2139 ...))
2140
2141 self.assertEqual(self.signature(Test),
2142 ((('args', ..., ..., "var_positional"),),
2143 ...))
2144
2145 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2146 self.signature(Test())
2147
Yury Selivanov46c759d2015-05-27 21:56:53 -04002148 def test_signature_wrapped_bound_method(self):
2149 # Issue 24298
2150 class Test:
2151 def m1(self, arg1, arg2=1) -> int:
2152 pass
2153 @functools.wraps(Test().m1)
2154 def m1d(*args, **kwargs):
2155 pass
2156 self.assertEqual(self.signature(m1d),
2157 ((('arg1', ..., ..., "positional_or_keyword"),
2158 ('arg2', 1, ..., "positional_or_keyword")),
2159 int))
2160
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002161 def test_signature_on_classmethod(self):
2162 class Test:
2163 @classmethod
2164 def foo(cls, arg1, *, arg2=1):
2165 pass
2166
2167 meth = Test().foo
2168 self.assertEqual(self.signature(meth),
2169 ((('arg1', ..., ..., "positional_or_keyword"),
2170 ('arg2', 1, ..., "keyword_only")),
2171 ...))
2172
2173 meth = Test.foo
2174 self.assertEqual(self.signature(meth),
2175 ((('arg1', ..., ..., "positional_or_keyword"),
2176 ('arg2', 1, ..., "keyword_only")),
2177 ...))
2178
2179 def test_signature_on_staticmethod(self):
2180 class Test:
2181 @staticmethod
2182 def foo(cls, *, arg):
2183 pass
2184
2185 meth = Test().foo
2186 self.assertEqual(self.signature(meth),
2187 ((('cls', ..., ..., "positional_or_keyword"),
2188 ('arg', ..., ..., "keyword_only")),
2189 ...))
2190
2191 meth = Test.foo
2192 self.assertEqual(self.signature(meth),
2193 ((('cls', ..., ..., "positional_or_keyword"),
2194 ('arg', ..., ..., "keyword_only")),
2195 ...))
2196
2197 def test_signature_on_partial(self):
2198 from functools import partial
2199
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002200 Parameter = inspect.Parameter
2201
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002202 def test():
2203 pass
2204
2205 self.assertEqual(self.signature(partial(test)), ((), ...))
2206
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002207 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002208 inspect.signature(partial(test, 1))
2209
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002210 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002211 inspect.signature(partial(test, a=1))
2212
2213 def test(a, b, *, c, d):
2214 pass
2215
2216 self.assertEqual(self.signature(partial(test)),
2217 ((('a', ..., ..., "positional_or_keyword"),
2218 ('b', ..., ..., "positional_or_keyword"),
2219 ('c', ..., ..., "keyword_only"),
2220 ('d', ..., ..., "keyword_only")),
2221 ...))
2222
2223 self.assertEqual(self.signature(partial(test, 1)),
2224 ((('b', ..., ..., "positional_or_keyword"),
2225 ('c', ..., ..., "keyword_only"),
2226 ('d', ..., ..., "keyword_only")),
2227 ...))
2228
2229 self.assertEqual(self.signature(partial(test, 1, c=2)),
2230 ((('b', ..., ..., "positional_or_keyword"),
2231 ('c', 2, ..., "keyword_only"),
2232 ('d', ..., ..., "keyword_only")),
2233 ...))
2234
2235 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2236 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002237 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002238 ('c', 2, ..., "keyword_only"),
2239 ('d', ..., ..., "keyword_only")),
2240 ...))
2241
2242 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002243 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002244 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002245 ('d', ..., ..., "keyword_only")),
2246 ...))
2247
2248 self.assertEqual(self.signature(partial(test, a=1)),
2249 ((('a', 1, ..., "keyword_only"),
2250 ('b', ..., ..., "keyword_only"),
2251 ('c', ..., ..., "keyword_only"),
2252 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002253 ...))
2254
2255 def test(a, *args, b, **kwargs):
2256 pass
2257
2258 self.assertEqual(self.signature(partial(test, 1)),
2259 ((('args', ..., ..., "var_positional"),
2260 ('b', ..., ..., "keyword_only"),
2261 ('kwargs', ..., ..., "var_keyword")),
2262 ...))
2263
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002264 self.assertEqual(self.signature(partial(test, a=1)),
2265 ((('a', 1, ..., "keyword_only"),
2266 ('b', ..., ..., "keyword_only"),
2267 ('kwargs', ..., ..., "var_keyword")),
2268 ...))
2269
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002270 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2271 ((('args', ..., ..., "var_positional"),
2272 ('b', ..., ..., "keyword_only"),
2273 ('kwargs', ..., ..., "var_keyword")),
2274 ...))
2275
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002276 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2277 ((('args', ..., ..., "var_positional"),
2278 ('b', ..., ..., "keyword_only"),
2279 ('kwargs', ..., ..., "var_keyword")),
2280 ...))
2281
2282 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2283 ((('args', ..., ..., "var_positional"),
2284 ('b', 0, ..., "keyword_only"),
2285 ('kwargs', ..., ..., "var_keyword")),
2286 ...))
2287
2288 self.assertEqual(self.signature(partial(test, b=0)),
2289 ((('a', ..., ..., "positional_or_keyword"),
2290 ('args', ..., ..., "var_positional"),
2291 ('b', 0, ..., "keyword_only"),
2292 ('kwargs', ..., ..., "var_keyword")),
2293 ...))
2294
2295 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2296 ((('a', ..., ..., "positional_or_keyword"),
2297 ('args', ..., ..., "var_positional"),
2298 ('b', 0, ..., "keyword_only"),
2299 ('kwargs', ..., ..., "var_keyword")),
2300 ...))
2301
2302 def test(a, b, c:int) -> 42:
2303 pass
2304
2305 sig = test.__signature__ = inspect.signature(test)
2306
2307 self.assertEqual(self.signature(partial(partial(test, 1))),
2308 ((('b', ..., ..., "positional_or_keyword"),
2309 ('c', ..., int, "positional_or_keyword")),
2310 42))
2311
2312 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2313 ((('c', ..., int, "positional_or_keyword"),),
2314 42))
2315
2316 psig = inspect.signature(partial(partial(test, 1), 2))
2317
2318 def foo(a):
2319 return a
2320 _foo = partial(partial(foo, a=10), a=20)
2321 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002322 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002323 ...))
2324 # check that we don't have any side-effects in signature(),
2325 # and the partial object is still functioning
2326 self.assertEqual(_foo(), 20)
2327
2328 def foo(a, b, c):
2329 return a, b, c
2330 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002331
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002332 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002333 ((('b', 30, ..., "keyword_only"),
2334 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002335 ...))
2336 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002337
2338 def foo(a, b, c, *, d):
2339 return a, b, c, d
2340 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2341 self.assertEqual(self.signature(_foo),
2342 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002343 ('b', 10, ..., "keyword_only"),
2344 ('c', 20, ..., "keyword_only"),
2345 ('d', 30, ..., "keyword_only"),
2346 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002347 ...))
2348 ba = inspect.signature(_foo).bind(a=200, b=11)
2349 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2350
2351 def foo(a=1, b=2, c=3):
2352 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002353 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2354
2355 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002356 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002357
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002358 ba = inspect.signature(_foo).bind(11, 12)
2359 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002360
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002361 ba = inspect.signature(_foo).bind(11, b=12)
2362 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002363
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002364 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002365 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2366
2367 _foo = partial(_foo, b=10, c=20)
2368 ba = inspect.signature(_foo).bind(12)
2369 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2370
2371
2372 def foo(a, b, c, d, **kwargs):
2373 pass
2374 sig = inspect.signature(foo)
2375 params = sig.parameters.copy()
2376 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2377 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2378 foo.__signature__ = inspect.Signature(params.values())
2379 sig = inspect.signature(foo)
2380 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2381
2382 self.assertEqual(self.signature(partial(foo, 1)),
2383 ((('b', ..., ..., 'positional_only'),
2384 ('c', ..., ..., 'positional_or_keyword'),
2385 ('d', ..., ..., 'positional_or_keyword'),
2386 ('kwargs', ..., ..., 'var_keyword')),
2387 ...))
2388
2389 self.assertEqual(self.signature(partial(foo, 1, 2)),
2390 ((('c', ..., ..., 'positional_or_keyword'),
2391 ('d', ..., ..., 'positional_or_keyword'),
2392 ('kwargs', ..., ..., 'var_keyword')),
2393 ...))
2394
2395 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2396 ((('d', ..., ..., 'positional_or_keyword'),
2397 ('kwargs', ..., ..., 'var_keyword')),
2398 ...))
2399
2400 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2401 ((('c', 3, ..., 'keyword_only'),
2402 ('d', ..., ..., 'keyword_only'),
2403 ('kwargs', ..., ..., 'var_keyword')),
2404 ...))
2405
2406 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2407 ((('b', ..., ..., 'positional_only'),
2408 ('c', 3, ..., 'keyword_only'),
2409 ('d', ..., ..., 'keyword_only'),
2410 ('kwargs', ..., ..., 'var_keyword')),
2411 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002412
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002413 def test_signature_on_partialmethod(self):
2414 from functools import partialmethod
2415
2416 class Spam:
2417 def test():
2418 pass
2419 ham = partialmethod(test)
2420
2421 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2422 inspect.signature(Spam.ham)
2423
2424 class Spam:
2425 def test(it, a, *, c) -> 'spam':
2426 pass
2427 ham = partialmethod(test, c=1)
2428
2429 self.assertEqual(self.signature(Spam.ham),
2430 ((('it', ..., ..., 'positional_or_keyword'),
2431 ('a', ..., ..., 'positional_or_keyword'),
2432 ('c', 1, ..., 'keyword_only')),
2433 'spam'))
2434
2435 self.assertEqual(self.signature(Spam().ham),
2436 ((('a', ..., ..., 'positional_or_keyword'),
2437 ('c', 1, ..., 'keyword_only')),
2438 'spam'))
2439
Yury Selivanov0486f812014-01-29 12:18:59 -05002440 def test_signature_on_fake_partialmethod(self):
2441 def foo(a): pass
2442 foo._partialmethod = 'spam'
2443 self.assertEqual(str(inspect.signature(foo)), '(a)')
2444
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002445 def test_signature_on_decorated(self):
2446 import functools
2447
2448 def decorator(func):
2449 @functools.wraps(func)
2450 def wrapper(*args, **kwargs) -> int:
2451 return func(*args, **kwargs)
2452 return wrapper
2453
2454 class Foo:
2455 @decorator
2456 def bar(self, a, b):
2457 pass
2458
2459 self.assertEqual(self.signature(Foo.bar),
2460 ((('self', ..., ..., "positional_or_keyword"),
2461 ('a', ..., ..., "positional_or_keyword"),
2462 ('b', ..., ..., "positional_or_keyword")),
2463 ...))
2464
2465 self.assertEqual(self.signature(Foo().bar),
2466 ((('a', ..., ..., "positional_or_keyword"),
2467 ('b', ..., ..., "positional_or_keyword")),
2468 ...))
2469
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002470 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2471 ((('args', ..., ..., "var_positional"),
2472 ('kwargs', ..., ..., "var_keyword")),
2473 ...)) # functools.wraps will copy __annotations__
2474 # from "func" to "wrapper", hence no
2475 # return_annotation
2476
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002477 # Test that we handle method wrappers correctly
2478 def decorator(func):
2479 @functools.wraps(func)
2480 def wrapper(*args, **kwargs) -> int:
2481 return func(42, *args, **kwargs)
2482 sig = inspect.signature(func)
2483 new_params = tuple(sig.parameters.values())[1:]
2484 wrapper.__signature__ = sig.replace(parameters=new_params)
2485 return wrapper
2486
2487 class Foo:
2488 @decorator
2489 def __call__(self, a, b):
2490 pass
2491
2492 self.assertEqual(self.signature(Foo.__call__),
2493 ((('a', ..., ..., "positional_or_keyword"),
2494 ('b', ..., ..., "positional_or_keyword")),
2495 ...))
2496
2497 self.assertEqual(self.signature(Foo().__call__),
2498 ((('b', ..., ..., "positional_or_keyword"),),
2499 ...))
2500
Nick Coghlane8c45d62013-07-28 20:00:01 +10002501 # Test we handle __signature__ partway down the wrapper stack
2502 def wrapped_foo_call():
2503 pass
2504 wrapped_foo_call.__wrapped__ = Foo.__call__
2505
2506 self.assertEqual(self.signature(wrapped_foo_call),
2507 ((('a', ..., ..., "positional_or_keyword"),
2508 ('b', ..., ..., "positional_or_keyword")),
2509 ...))
2510
2511
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002512 def test_signature_on_class(self):
2513 class C:
2514 def __init__(self, a):
2515 pass
2516
2517 self.assertEqual(self.signature(C),
2518 ((('a', ..., ..., "positional_or_keyword"),),
2519 ...))
2520
2521 class CM(type):
2522 def __call__(cls, a):
2523 pass
2524 class C(metaclass=CM):
2525 def __init__(self, b):
2526 pass
2527
2528 self.assertEqual(self.signature(C),
2529 ((('a', ..., ..., "positional_or_keyword"),),
2530 ...))
2531
2532 class CM(type):
2533 def __new__(mcls, name, bases, dct, *, foo=1):
2534 return super().__new__(mcls, name, bases, dct)
2535 class C(metaclass=CM):
2536 def __init__(self, b):
2537 pass
2538
2539 self.assertEqual(self.signature(C),
2540 ((('b', ..., ..., "positional_or_keyword"),),
2541 ...))
2542
2543 self.assertEqual(self.signature(CM),
2544 ((('name', ..., ..., "positional_or_keyword"),
2545 ('bases', ..., ..., "positional_or_keyword"),
2546 ('dct', ..., ..., "positional_or_keyword"),
2547 ('foo', 1, ..., "keyword_only")),
2548 ...))
2549
2550 class CMM(type):
2551 def __new__(mcls, name, bases, dct, *, foo=1):
2552 return super().__new__(mcls, name, bases, dct)
2553 def __call__(cls, nm, bs, dt):
2554 return type(nm, bs, dt)
2555 class CM(type, metaclass=CMM):
2556 def __new__(mcls, name, bases, dct, *, bar=2):
2557 return super().__new__(mcls, name, bases, dct)
2558 class C(metaclass=CM):
2559 def __init__(self, b):
2560 pass
2561
2562 self.assertEqual(self.signature(CMM),
2563 ((('name', ..., ..., "positional_or_keyword"),
2564 ('bases', ..., ..., "positional_or_keyword"),
2565 ('dct', ..., ..., "positional_or_keyword"),
2566 ('foo', 1, ..., "keyword_only")),
2567 ...))
2568
2569 self.assertEqual(self.signature(CM),
2570 ((('nm', ..., ..., "positional_or_keyword"),
2571 ('bs', ..., ..., "positional_or_keyword"),
2572 ('dt', ..., ..., "positional_or_keyword")),
2573 ...))
2574
2575 self.assertEqual(self.signature(C),
2576 ((('b', ..., ..., "positional_or_keyword"),),
2577 ...))
2578
2579 class CM(type):
2580 def __init__(cls, name, bases, dct, *, bar=2):
2581 return super().__init__(name, bases, dct)
2582 class C(metaclass=CM):
2583 def __init__(self, b):
2584 pass
2585
2586 self.assertEqual(self.signature(CM),
2587 ((('name', ..., ..., "positional_or_keyword"),
2588 ('bases', ..., ..., "positional_or_keyword"),
2589 ('dct', ..., ..., "positional_or_keyword"),
2590 ('bar', 2, ..., "keyword_only")),
2591 ...))
2592
Yury Selivanov145dff82014-02-01 13:49:29 -05002593 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2594 "Signature information for builtins requires docstrings")
2595 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002596 # Test classes without user-defined __init__ or __new__
2597 class C: pass
2598 self.assertEqual(str(inspect.signature(C)), '()')
2599 class D(C): pass
2600 self.assertEqual(str(inspect.signature(D)), '()')
2601
2602 # Test meta-classes without user-defined __init__ or __new__
2603 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002604 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002605 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2606 self.assertEqual(inspect.signature(C), None)
2607 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2608 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002609
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002610 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2611 "Signature information for builtins requires docstrings")
2612 def test_signature_on_builtin_class(self):
2613 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2614 '(file, protocol=None, fix_imports=True)')
2615
2616 class P(_pickle.Pickler): pass
2617 class EmptyTrait: pass
2618 class P2(EmptyTrait, P): pass
2619 self.assertEqual(str(inspect.signature(P)),
2620 '(file, protocol=None, fix_imports=True)')
2621 self.assertEqual(str(inspect.signature(P2)),
2622 '(file, protocol=None, fix_imports=True)')
2623
2624 class P3(P2):
2625 def __init__(self, spam):
2626 pass
2627 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2628
2629 class MetaP(type):
2630 def __call__(cls, foo, bar):
2631 pass
2632 class P4(P2, metaclass=MetaP):
2633 pass
2634 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2635
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002636 def test_signature_on_callable_objects(self):
2637 class Foo:
2638 def __call__(self, a):
2639 pass
2640
2641 self.assertEqual(self.signature(Foo()),
2642 ((('a', ..., ..., "positional_or_keyword"),),
2643 ...))
2644
2645 class Spam:
2646 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002647 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002648 inspect.signature(Spam())
2649
2650 class Bar(Spam, Foo):
2651 pass
2652
2653 self.assertEqual(self.signature(Bar()),
2654 ((('a', ..., ..., "positional_or_keyword"),),
2655 ...))
2656
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002657 class Wrapped:
2658 pass
2659 Wrapped.__wrapped__ = lambda a: None
2660 self.assertEqual(self.signature(Wrapped),
2661 ((('a', ..., ..., "positional_or_keyword"),),
2662 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002663 # wrapper loop:
2664 Wrapped.__wrapped__ = Wrapped
2665 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2666 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002667
2668 def test_signature_on_lambdas(self):
2669 self.assertEqual(self.signature((lambda a=10: a)),
2670 ((('a', 10, ..., "positional_or_keyword"),),
2671 ...))
2672
2673 def test_signature_equality(self):
2674 def foo(a, *, b:int) -> float: pass
2675 self.assertNotEqual(inspect.signature(foo), 42)
2676
2677 def bar(a, *, b:int) -> float: pass
2678 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002679 self.assertEqual(
2680 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002681
2682 def bar(a, *, b:int) -> int: pass
2683 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002684 self.assertNotEqual(
2685 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002686
2687 def bar(a, *, b:int): pass
2688 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002689 self.assertNotEqual(
2690 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002691
2692 def bar(a, *, b:int=42) -> float: pass
2693 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002694 self.assertNotEqual(
2695 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002696
2697 def bar(a, *, c) -> float: pass
2698 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002699 self.assertNotEqual(
2700 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002701
2702 def bar(a, b:int) -> float: pass
2703 self.assertNotEqual(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 def spam(b:int, a) -> float: pass
2707 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002708 self.assertNotEqual(
2709 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002710
2711 def foo(*, a, b, c): pass
2712 def bar(*, c, b, a): pass
2713 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002714 self.assertEqual(
2715 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002716
2717 def foo(*, a=1, b, c): pass
2718 def bar(*, c, b, a=1): pass
2719 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002720 self.assertEqual(
2721 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002722
2723 def foo(pos, *, a=1, b, c): pass
2724 def bar(pos, *, c, b, a=1): pass
2725 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002726 self.assertEqual(
2727 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002728
2729 def foo(pos, *, a, b, c): pass
2730 def bar(pos, *, c, b, a=1): pass
2731 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002732 self.assertNotEqual(
2733 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002734
2735 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2736 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2737 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002738 self.assertEqual(
2739 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002740
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002741 def test_signature_hashable(self):
2742 S = inspect.Signature
2743 P = inspect.Parameter
2744
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002745 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002746 foo_sig = inspect.signature(foo)
2747
2748 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2749
2750 self.assertEqual(hash(foo_sig), hash(manual_sig))
2751 self.assertNotEqual(hash(foo_sig),
2752 hash(manual_sig.replace(return_annotation='spam')))
2753
2754 def bar(a) -> 1: pass
2755 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2756
2757 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002758 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002759 hash(inspect.signature(foo))
2760
2761 def foo(a) -> {}: pass
2762 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2763 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002764
2765 def test_signature_str(self):
2766 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2767 pass
2768 self.assertEqual(str(inspect.signature(foo)),
2769 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2770
2771 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2772 pass
2773 self.assertEqual(str(inspect.signature(foo)),
2774 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2775
2776 def foo():
2777 pass
2778 self.assertEqual(str(inspect.signature(foo)), '()')
2779
2780 def test_signature_str_positional_only(self):
2781 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002782 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002783
2784 def test(a_po, *, b, **kwargs):
2785 return a_po, kwargs
2786
2787 sig = inspect.signature(test)
2788 new_params = list(sig.parameters.values())
2789 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2790 test.__signature__ = sig.replace(parameters=new_params)
2791
2792 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002793 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002794
Yury Selivanov2393dca2014-01-27 15:07:58 -05002795 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2796 '(foo, /)')
2797
2798 self.assertEqual(str(S(parameters=[
2799 P('foo', P.POSITIONAL_ONLY),
2800 P('bar', P.VAR_KEYWORD)])),
2801 '(foo, /, **bar)')
2802
2803 self.assertEqual(str(S(parameters=[
2804 P('foo', P.POSITIONAL_ONLY),
2805 P('bar', P.VAR_POSITIONAL)])),
2806 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002807
2808 def test_signature_replace_anno(self):
2809 def test() -> 42:
2810 pass
2811
2812 sig = inspect.signature(test)
2813 sig = sig.replace(return_annotation=None)
2814 self.assertIs(sig.return_annotation, None)
2815 sig = sig.replace(return_annotation=sig.empty)
2816 self.assertIs(sig.return_annotation, sig.empty)
2817 sig = sig.replace(return_annotation=42)
2818 self.assertEqual(sig.return_annotation, 42)
2819 self.assertEqual(sig, inspect.signature(test))
2820
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002821 def test_signature_on_mangled_parameters(self):
2822 class Spam:
2823 def foo(self, __p1:1=2, *, __p2:2=3):
2824 pass
2825 class Ham(Spam):
2826 pass
2827
2828 self.assertEqual(self.signature(Spam.foo),
2829 ((('self', ..., ..., "positional_or_keyword"),
2830 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2831 ('_Spam__p2', 3, 2, "keyword_only")),
2832 ...))
2833
2834 self.assertEqual(self.signature(Spam.foo),
2835 self.signature(Ham.foo))
2836
Yury Selivanovda396452014-03-27 12:09:24 -04002837 def test_signature_from_callable_python_obj(self):
2838 class MySignature(inspect.Signature): pass
2839 def foo(a, *, b:1): pass
2840 foo_sig = MySignature.from_callable(foo)
2841 self.assertTrue(isinstance(foo_sig, MySignature))
2842
2843 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2844 "Signature information for builtins requires docstrings")
2845 def test_signature_from_callable_builtin_obj(self):
2846 class MySignature(inspect.Signature): pass
2847 sig = MySignature.from_callable(_pickle.Pickler)
2848 self.assertTrue(isinstance(sig, MySignature))
2849
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002850
2851class TestParameterObject(unittest.TestCase):
2852 def test_signature_parameter_kinds(self):
2853 P = inspect.Parameter
2854 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2855 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2856
2857 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2858 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2859
2860 def test_signature_parameter_object(self):
2861 p = inspect.Parameter('foo', default=10,
2862 kind=inspect.Parameter.POSITIONAL_ONLY)
2863 self.assertEqual(p.name, 'foo')
2864 self.assertEqual(p.default, 10)
2865 self.assertIs(p.annotation, p.empty)
2866 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2867
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002868 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002869 inspect.Parameter('foo', default=10, kind='123')
2870
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002871 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002872 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2873
Yury Selivanov2393dca2014-01-27 15:07:58 -05002874 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002875 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2876
Yury Selivanov2393dca2014-01-27 15:07:58 -05002877 with self.assertRaisesRegex(ValueError,
2878 'is not a valid parameter name'):
2879 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2880
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002881 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002882 inspect.Parameter('a', default=42,
2883 kind=inspect.Parameter.VAR_KEYWORD)
2884
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002885 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002886 inspect.Parameter('a', default=42,
2887 kind=inspect.Parameter.VAR_POSITIONAL)
2888
2889 p = inspect.Parameter('a', default=42,
2890 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002891 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002892 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2893
2894 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002895 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002896
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002897 def test_signature_parameter_hashable(self):
2898 P = inspect.Parameter
2899 foo = P('foo', kind=P.POSITIONAL_ONLY)
2900 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
2901 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
2902 default=42)))
2903 self.assertNotEqual(hash(foo),
2904 hash(foo.replace(kind=P.VAR_POSITIONAL)))
2905
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002906 def test_signature_parameter_equality(self):
2907 P = inspect.Parameter
2908 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2909
2910 self.assertEqual(p, p)
2911 self.assertNotEqual(p, 42)
2912
2913 self.assertEqual(p, P('foo', default=42,
2914 kind=inspect.Parameter.KEYWORD_ONLY))
2915
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002916 def test_signature_parameter_replace(self):
2917 p = inspect.Parameter('foo', default=42,
2918 kind=inspect.Parameter.KEYWORD_ONLY)
2919
2920 self.assertIsNot(p, p.replace())
2921 self.assertEqual(p, p.replace())
2922
2923 p2 = p.replace(annotation=1)
2924 self.assertEqual(p2.annotation, 1)
2925 p2 = p2.replace(annotation=p2.empty)
2926 self.assertEqual(p, p2)
2927
2928 p2 = p2.replace(name='bar')
2929 self.assertEqual(p2.name, 'bar')
2930 self.assertNotEqual(p2, p)
2931
Yury Selivanov2393dca2014-01-27 15:07:58 -05002932 with self.assertRaisesRegex(ValueError,
2933 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002934 p2 = p2.replace(name=p2.empty)
2935
2936 p2 = p2.replace(name='foo', default=None)
2937 self.assertIs(p2.default, None)
2938 self.assertNotEqual(p2, p)
2939
2940 p2 = p2.replace(name='foo', default=p2.empty)
2941 self.assertIs(p2.default, p2.empty)
2942
2943
2944 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2945 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2946 self.assertNotEqual(p2, p)
2947
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002948 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002949 p2 = p2.replace(kind=p2.empty)
2950
2951 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2952 self.assertEqual(p2, p)
2953
2954 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002955 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2956 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002957
2958 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002959 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002960
2961 with self.assertRaises(AttributeError):
2962 p.foo = 'bar'
2963
2964 with self.assertRaises(AttributeError):
2965 p.kind = 123
2966
2967
2968class TestSignatureBind(unittest.TestCase):
2969 @staticmethod
2970 def call(func, *args, **kwargs):
2971 sig = inspect.signature(func)
2972 ba = sig.bind(*args, **kwargs)
2973 return func(*ba.args, **ba.kwargs)
2974
2975 def test_signature_bind_empty(self):
2976 def test():
2977 return 42
2978
2979 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002980 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002981 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002982 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002983 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04002984 with self.assertRaisesRegex(
2985 TypeError, "got an unexpected keyword argument 'spam'"):
2986
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002987 self.call(test, spam=1)
2988
2989 def test_signature_bind_var(self):
2990 def test(*args, **kwargs):
2991 return args, kwargs
2992
2993 self.assertEqual(self.call(test), ((), {}))
2994 self.assertEqual(self.call(test, 1), ((1,), {}))
2995 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2996 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2997 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2998 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2999 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3000 ((1, 2), {'foo': 'bar'}))
3001
3002 def test_signature_bind_just_args(self):
3003 def test(a, b, c):
3004 return a, b, c
3005
3006 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3007
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003008 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003009 self.call(test, 1, 2, 3, 4)
3010
Yury Selivanov86872752015-05-19 00:27:49 -04003011 with self.assertRaisesRegex(TypeError,
3012 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003013 self.call(test, 1)
3014
Yury Selivanov86872752015-05-19 00:27:49 -04003015 with self.assertRaisesRegex(TypeError,
3016 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003017 self.call(test)
3018
3019 def test(a, b, c=10):
3020 return a, b, c
3021 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3022 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3023
3024 def test(a=1, b=2, c=3):
3025 return a, b, c
3026 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3027 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3028 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3029
3030 def test_signature_bind_varargs_order(self):
3031 def test(*args):
3032 return args
3033
3034 self.assertEqual(self.call(test), ())
3035 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3036
3037 def test_signature_bind_args_and_varargs(self):
3038 def test(a, b, c=3, *args):
3039 return a, b, c, args
3040
3041 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3042 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3043 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3044 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3045
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003046 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003047 "multiple values for argument 'c'"):
3048 self.call(test, 1, 2, 3, c=4)
3049
3050 def test_signature_bind_just_kwargs(self):
3051 def test(**kwargs):
3052 return kwargs
3053
3054 self.assertEqual(self.call(test), {})
3055 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3056 {'foo': 'bar', 'spam': 'ham'})
3057
3058 def test_signature_bind_args_and_kwargs(self):
3059 def test(a, b, c=3, **kwargs):
3060 return a, b, c, kwargs
3061
3062 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3063 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3064 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3065 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3066 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3067 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3068 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3069 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3070 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3071 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3072 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3073 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3074 (1, 2, 4, {'foo': 'bar'}))
3075 self.assertEqual(self.call(test, c=5, a=4, b=3),
3076 (4, 3, 5, {}))
3077
3078 def test_signature_bind_kwonly(self):
3079 def test(*, foo):
3080 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003081 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003082 'too many positional arguments'):
3083 self.call(test, 1)
3084 self.assertEqual(self.call(test, foo=1), 1)
3085
3086 def test(a, *, foo=1, bar):
3087 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003088 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003089 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003090 self.call(test, 1)
3091
3092 def test(foo, *, bar):
3093 return foo, bar
3094 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3095 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3096
Yury Selivanov86872752015-05-19 00:27:49 -04003097 with self.assertRaisesRegex(
3098 TypeError, "got an unexpected keyword argument 'spam'"):
3099
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003100 self.call(test, bar=2, foo=1, spam=10)
3101
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003102 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003103 'too many positional arguments'):
3104 self.call(test, 1, 2)
3105
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003106 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003107 'too many positional arguments'):
3108 self.call(test, 1, 2, bar=2)
3109
Yury Selivanov86872752015-05-19 00:27:49 -04003110 with self.assertRaisesRegex(
3111 TypeError, "got an unexpected keyword argument 'spam'"):
3112
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003113 self.call(test, 1, bar=2, spam='ham')
3114
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003115 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003116 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003117 self.call(test, 1)
3118
3119 def test(foo, *, bar, **bin):
3120 return foo, bar, bin
3121 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3122 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3123 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3124 (1, 2, {'spam': 'ham'}))
3125 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3126 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003127 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003128 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003129 self.call(test, spam='ham', bar=2)
3130 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3131 (1, 2, {'bin': 1, 'spam': 10}))
3132
3133 def test_signature_bind_arguments(self):
3134 def test(a, *args, b, z=100, **kwargs):
3135 pass
3136 sig = inspect.signature(test)
3137 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3138 # we won't have 'z' argument in the bound arguments object, as we didn't
3139 # pass it to the 'bind'
3140 self.assertEqual(tuple(ba.arguments.items()),
3141 (('a', 10), ('args', (20,)), ('b', 30),
3142 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3143 self.assertEqual(ba.kwargs,
3144 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3145 self.assertEqual(ba.args, (10, 20))
3146
3147 def test_signature_bind_positional_only(self):
3148 P = inspect.Parameter
3149
3150 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3151 return a_po, b_po, c_po, foo, bar, kwargs
3152
3153 sig = inspect.signature(test)
3154 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3155 for name in ('a_po', 'b_po', 'c_po'):
3156 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3157 new_sig = sig.replace(parameters=new_params.values())
3158 test.__signature__ = new_sig
3159
3160 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3161 (1, 2, 4, 5, 6, {}))
3162
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003163 self.assertEqual(self.call(test, 1, 2),
3164 (1, 2, 3, 42, 50, {}))
3165
3166 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3167 (1, 2, 3, 4, 5, {}))
3168
3169 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3170 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3171
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003172 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003173 self.call(test, 1, 2, c_po=4)
3174
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003175 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003176 self.call(test, a_po=1, b_po=2)
3177
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003178 def test_signature_bind_with_self_arg(self):
3179 # Issue #17071: one of the parameters is named "self
3180 def test(a, self, b):
3181 pass
3182 sig = inspect.signature(test)
3183 ba = sig.bind(1, 2, 3)
3184 self.assertEqual(ba.args, (1, 2, 3))
3185 ba = sig.bind(1, self=2, b=3)
3186 self.assertEqual(ba.args, (1, 2, 3))
3187
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003188 def test_signature_bind_vararg_name(self):
3189 def test(a, *args):
3190 return a, args
3191 sig = inspect.signature(test)
3192
Yury Selivanov86872752015-05-19 00:27:49 -04003193 with self.assertRaisesRegex(
3194 TypeError, "got an unexpected keyword argument 'args'"):
3195
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003196 sig.bind(a=0, args=1)
3197
3198 def test(*args, **kwargs):
3199 return args, kwargs
3200 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3201
3202 sig = inspect.signature(test)
3203 ba = sig.bind(args=1)
3204 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3205
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003206
3207class TestBoundArguments(unittest.TestCase):
3208 def test_signature_bound_arguments_unhashable(self):
3209 def foo(a): pass
3210 ba = inspect.signature(foo).bind(1)
3211
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003212 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003213 hash(ba)
3214
3215 def test_signature_bound_arguments_equality(self):
3216 def foo(a): pass
3217 ba = inspect.signature(foo).bind(1)
3218 self.assertEqual(ba, ba)
3219
3220 ba2 = inspect.signature(foo).bind(1)
3221 self.assertEqual(ba, ba2)
3222
3223 ba3 = inspect.signature(foo).bind(2)
3224 self.assertNotEqual(ba, ba3)
3225 ba3.arguments['a'] = 1
3226 self.assertEqual(ba, ba3)
3227
3228 def bar(b): pass
3229 ba4 = inspect.signature(bar).bind(1)
3230 self.assertNotEqual(ba, ba4)
3231
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003232 def foo(*, a, b): pass
3233 sig = inspect.signature(foo)
3234 ba1 = sig.bind(a=1, b=2)
3235 ba2 = sig.bind(b=2, a=1)
3236 self.assertEqual(ba1, ba2)
3237
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003238 def test_signature_bound_arguments_pickle(self):
3239 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3240 sig = inspect.signature(foo)
3241 ba = sig.bind(20, 30, z={})
3242
3243 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3244 with self.subTest(pickle_ver=ver):
3245 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3246 self.assertEqual(ba, ba_pickled)
3247
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003248 def test_signature_bound_arguments_repr(self):
3249 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3250 sig = inspect.signature(foo)
3251 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003252 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003253
Yury Selivanovb907a512015-05-16 13:45:09 -04003254 def test_signature_bound_arguments_apply_defaults(self):
3255 def foo(a, b=1, *args, c:1={}, **kw): pass
3256 sig = inspect.signature(foo)
3257
3258 ba = sig.bind(20)
3259 ba.apply_defaults()
3260 self.assertEqual(
3261 list(ba.arguments.items()),
3262 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3263
3264 # Make sure that we preserve the order:
3265 # i.e. 'c' should be *before* 'kw'.
3266 ba = sig.bind(10, 20, 30, d=1)
3267 ba.apply_defaults()
3268 self.assertEqual(
3269 list(ba.arguments.items()),
3270 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3271
3272 # Make sure that BoundArguments produced by bind_partial()
3273 # are supported.
3274 def foo(a, b): pass
3275 sig = inspect.signature(foo)
3276 ba = sig.bind_partial(20)
3277 ba.apply_defaults()
3278 self.assertEqual(
3279 list(ba.arguments.items()),
3280 [('a', 20)])
3281
3282 # Test no args
3283 def foo(): pass
3284 sig = inspect.signature(foo)
3285 ba = sig.bind()
3286 ba.apply_defaults()
3287 self.assertEqual(list(ba.arguments.items()), [])
3288
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003289
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003290class TestSignaturePrivateHelpers(unittest.TestCase):
3291 def test_signature_get_bound_param(self):
3292 getter = inspect._signature_get_bound_param
3293
3294 self.assertEqual(getter('($self)'), 'self')
3295 self.assertEqual(getter('($self, obj)'), 'self')
3296 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3297
Larry Hastings2623c8c2014-02-08 22:15:29 -08003298 def _strip_non_python_syntax(self, input,
3299 clean_signature, self_parameter, last_positional_only):
3300 computed_clean_signature, \
3301 computed_self_parameter, \
3302 computed_last_positional_only = \
3303 inspect._signature_strip_non_python_syntax(input)
3304 self.assertEqual(computed_clean_signature, clean_signature)
3305 self.assertEqual(computed_self_parameter, self_parameter)
3306 self.assertEqual(computed_last_positional_only, last_positional_only)
3307
3308 def test_signature_strip_non_python_syntax(self):
3309 self._strip_non_python_syntax(
3310 "($module, /, path, mode, *, dir_fd=None, " +
3311 "effective_ids=False,\n follow_symlinks=True)",
3312 "(module, path, mode, *, dir_fd=None, " +
3313 "effective_ids=False, follow_symlinks=True)",
3314 0,
3315 0)
3316
3317 self._strip_non_python_syntax(
3318 "($module, word, salt, /)",
3319 "(module, word, salt)",
3320 0,
3321 2)
3322
3323 self._strip_non_python_syntax(
3324 "(x, y=None, z=None, /)",
3325 "(x, y=None, z=None)",
3326 None,
3327 2)
3328
3329 self._strip_non_python_syntax(
3330 "(x, y=None, z=None)",
3331 "(x, y=None, z=None)",
3332 None,
3333 None)
3334
3335 self._strip_non_python_syntax(
3336 "(x,\n y=None,\n z = None )",
3337 "(x, y=None, z=None)",
3338 None,
3339 None)
3340
3341 self._strip_non_python_syntax(
3342 "",
3343 "",
3344 None,
3345 None)
3346
3347 self._strip_non_python_syntax(
3348 None,
3349 None,
3350 None,
3351 None)
3352
Nick Coghlan9c680b02015-04-13 12:54:54 -04003353class TestSignatureDefinitions(unittest.TestCase):
3354 # This test case provides a home for checking that particular APIs
3355 # have signatures available for introspection
3356
3357 @cpython_only
3358 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3359 "Signature information for builtins requires docstrings")
3360 def test_builtins_have_signatures(self):
3361 # This checks all builtin callables in CPython have signatures
3362 # A few have signatures Signature can't yet handle, so we skip those
3363 # since they will have to wait until PEP 457 adds the required
3364 # introspection support to the inspect module
3365 # Some others also haven't been converted yet for various other
3366 # reasons, so we also skip those for the time being, but design
3367 # the test to fail in order to indicate when it needs to be
3368 # updated.
3369 no_signature = set()
3370 # These need PEP 457 groups
3371 needs_groups = {"range", "slice", "dir", "getattr",
3372 "next", "iter", "vars"}
3373 no_signature |= needs_groups
3374 # These need PEP 457 groups or a signature change to accept None
3375 needs_semantic_update = {"round"}
3376 no_signature |= needs_semantic_update
3377 # These need *args support in Argument Clinic
3378 needs_varargs = {"min", "max", "print", "__build_class__"}
3379 no_signature |= needs_varargs
3380 # These simply weren't covered in the initial AC conversion
3381 # for builtin callables
3382 not_converted_yet = {"open", "__import__"}
3383 no_signature |= not_converted_yet
3384 # These builtin types are expected to provide introspection info
3385 types_with_signatures = set()
3386 # Check the signatures we expect to be there
3387 ns = vars(builtins)
3388 for name, obj in sorted(ns.items()):
3389 if not callable(obj):
3390 continue
3391 # The builtin types haven't been converted to AC yet
3392 if isinstance(obj, type) and (name not in types_with_signatures):
3393 # Note that this also skips all the exception types
3394 no_signature.add(name)
3395 if (name in no_signature):
3396 # Not yet converted
3397 continue
3398 with self.subTest(builtin=name):
3399 self.assertIsNotNone(inspect.signature(obj))
3400 # Check callables that haven't been converted don't claim a signature
3401 # This ensures this test will start failing as more signatures are
3402 # added, so the affected items can be moved into the scope of the
3403 # regression test above
3404 for name in no_signature:
3405 with self.subTest(builtin=name):
3406 self.assertIsNone(obj.__text_signature__)
3407
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003408
Nick Coghlane8c45d62013-07-28 20:00:01 +10003409class TestUnwrap(unittest.TestCase):
3410
3411 def test_unwrap_one(self):
3412 def func(a, b):
3413 return a + b
3414 wrapper = functools.lru_cache(maxsize=20)(func)
3415 self.assertIs(inspect.unwrap(wrapper), func)
3416
3417 def test_unwrap_several(self):
3418 def func(a, b):
3419 return a + b
3420 wrapper = func
3421 for __ in range(10):
3422 @functools.wraps(wrapper)
3423 def wrapper():
3424 pass
3425 self.assertIsNot(wrapper.__wrapped__, func)
3426 self.assertIs(inspect.unwrap(wrapper), func)
3427
3428 def test_stop(self):
3429 def func1(a, b):
3430 return a + b
3431 @functools.wraps(func1)
3432 def func2():
3433 pass
3434 @functools.wraps(func2)
3435 def wrapper():
3436 pass
3437 func2.stop_here = 1
3438 unwrapped = inspect.unwrap(wrapper,
3439 stop=(lambda f: hasattr(f, "stop_here")))
3440 self.assertIs(unwrapped, func2)
3441
3442 def test_cycle(self):
3443 def func1(): pass
3444 func1.__wrapped__ = func1
3445 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3446 inspect.unwrap(func1)
3447
3448 def func2(): pass
3449 func2.__wrapped__ = func1
3450 func1.__wrapped__ = func2
3451 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3452 inspect.unwrap(func1)
3453 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3454 inspect.unwrap(func2)
3455
3456 def test_unhashable(self):
3457 def func(): pass
3458 func.__wrapped__ = None
3459 class C:
3460 __hash__ = None
3461 __wrapped__ = func
3462 self.assertIsNone(inspect.unwrap(C()))
3463
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003464class TestMain(unittest.TestCase):
3465 def test_only_source(self):
3466 module = importlib.import_module('unittest')
3467 rc, out, err = assert_python_ok('-m', 'inspect',
3468 'unittest')
3469 lines = out.decode().splitlines()
3470 # ignore the final newline
3471 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3472 self.assertEqual(err, b'')
3473
Yury Selivanov42407ab2014-06-23 10:23:50 -07003474 def test_custom_getattr(self):
3475 def foo():
3476 pass
3477 foo.__signature__ = 42
3478 with self.assertRaises(TypeError):
3479 inspect.signature(foo)
3480
Brett Cannon634a8fc2013-10-02 10:25:42 -04003481 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003482 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003483 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003484 rc, out, err = assert_python_ok('-m', 'inspect',
3485 'concurrent.futures:ThreadPoolExecutor')
3486 lines = out.decode().splitlines()
3487 # ignore the final newline
3488 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003489 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003490 self.assertEqual(err, b'')
3491
3492 def test_builtins(self):
3493 module = importlib.import_module('unittest')
3494 _, out, err = assert_python_failure('-m', 'inspect',
3495 'sys')
3496 lines = err.decode().splitlines()
3497 self.assertEqual(lines, ["Can't get info for builtin modules."])
3498
3499 def test_details(self):
3500 module = importlib.import_module('unittest')
3501 rc, out, err = assert_python_ok('-m', 'inspect',
3502 'unittest', '--details')
3503 output = out.decode()
3504 # Just a quick sanity check on the output
3505 self.assertIn(module.__name__, output)
3506 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003507 if not sys.flags.optimize:
3508 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003509 self.assertEqual(err, b'')
3510
3511
Yury Selivanovef1e7502014-12-08 16:05:34 -05003512class TestReload(unittest.TestCase):
3513
3514 src_before = textwrap.dedent("""\
3515def foo():
3516 print("Bla")
3517 """)
3518
3519 src_after = textwrap.dedent("""\
3520def foo():
3521 print("Oh no!")
3522 """)
3523
3524 def assertInspectEqual(self, path, source):
3525 inspected_src = inspect.getsource(source)
3526 with open(path) as src:
3527 self.assertEqual(
3528 src.read().splitlines(True),
3529 inspected_src.splitlines(True)
3530 )
3531
3532 def test_getsource_reload(self):
3533 # see issue 1218234
3534 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3535 module = importlib.import_module(name)
3536 self.assertInspectEqual(path, module)
3537 with open(path, 'w') as src:
3538 src.write(self.src_after)
3539 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003540
Nick Coghlane8c45d62013-07-28 20:00:01 +10003541
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003542def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003543 run_unittest(
3544 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3545 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3546 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003547 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003548 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003549 TestBoundArguments, TestSignaturePrivateHelpers,
3550 TestSignatureDefinitions,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003551 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
3552 TestGetCoroutineState
Michael Foord95fc51d2010-11-20 15:07:30 +00003553 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003554
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003555if __name__ == "__main__":
3556 test_main()