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