blob: 47244aeaa4943f68bbdfa86905ea13e90ef58122 [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 Storchaka5cf2b7252015-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
Nick Coghlanb4b966e2016-06-04 14:40:03 -07002906 with self.assertRaisesRegex(ValueError,
2907 'is not a valid parameter name'):
2908 inspect.Parameter('.a', 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_KEYWORD)
2913
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002914 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002915 inspect.Parameter('a', default=42,
2916 kind=inspect.Parameter.VAR_POSITIONAL)
2917
2918 p = inspect.Parameter('a', default=42,
2919 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002920 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002921 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2922
2923 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002924 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002925
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002926 def test_signature_parameter_hashable(self):
2927 P = inspect.Parameter
2928 foo = P('foo', kind=P.POSITIONAL_ONLY)
2929 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
2930 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
2931 default=42)))
2932 self.assertNotEqual(hash(foo),
2933 hash(foo.replace(kind=P.VAR_POSITIONAL)))
2934
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002935 def test_signature_parameter_equality(self):
2936 P = inspect.Parameter
2937 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2938
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002939 self.assertTrue(p == p)
2940 self.assertFalse(p != p)
2941 self.assertFalse(p == 42)
2942 self.assertTrue(p != 42)
2943 self.assertTrue(p == EqualsToAll())
2944 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002945
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002946 self.assertTrue(p == P('foo', default=42,
2947 kind=inspect.Parameter.KEYWORD_ONLY))
2948 self.assertFalse(p != P('foo', default=42,
2949 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002950
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002951 def test_signature_parameter_replace(self):
2952 p = inspect.Parameter('foo', default=42,
2953 kind=inspect.Parameter.KEYWORD_ONLY)
2954
2955 self.assertIsNot(p, p.replace())
2956 self.assertEqual(p, p.replace())
2957
2958 p2 = p.replace(annotation=1)
2959 self.assertEqual(p2.annotation, 1)
2960 p2 = p2.replace(annotation=p2.empty)
2961 self.assertEqual(p, p2)
2962
2963 p2 = p2.replace(name='bar')
2964 self.assertEqual(p2.name, 'bar')
2965 self.assertNotEqual(p2, p)
2966
Yury Selivanov2393dca2014-01-27 15:07:58 -05002967 with self.assertRaisesRegex(ValueError,
2968 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002969 p2 = p2.replace(name=p2.empty)
2970
2971 p2 = p2.replace(name='foo', default=None)
2972 self.assertIs(p2.default, None)
2973 self.assertNotEqual(p2, p)
2974
2975 p2 = p2.replace(name='foo', default=p2.empty)
2976 self.assertIs(p2.default, p2.empty)
2977
2978
2979 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2980 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2981 self.assertNotEqual(p2, p)
2982
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002983 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002984 p2 = p2.replace(kind=p2.empty)
2985
2986 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2987 self.assertEqual(p2, p)
2988
2989 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002990 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2991 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002992
Nick Coghlanb4b966e2016-06-04 14:40:03 -07002993 @cpython_only
2994 def test_signature_parameter_implicit(self):
2995 with self.assertRaisesRegex(ValueError,
2996 'implicit arguments must be passed in as'):
2997 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
2998
2999 param = inspect.Parameter(
3000 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3001 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3002 self.assertEqual(param.name, 'implicit0')
3003
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003004 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003005 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003006
3007 with self.assertRaises(AttributeError):
3008 p.foo = 'bar'
3009
3010 with self.assertRaises(AttributeError):
3011 p.kind = 123
3012
3013
3014class TestSignatureBind(unittest.TestCase):
3015 @staticmethod
3016 def call(func, *args, **kwargs):
3017 sig = inspect.signature(func)
3018 ba = sig.bind(*args, **kwargs)
3019 return func(*ba.args, **ba.kwargs)
3020
3021 def test_signature_bind_empty(self):
3022 def test():
3023 return 42
3024
3025 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003026 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003027 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003028 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003029 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003030 with self.assertRaisesRegex(
3031 TypeError, "got an unexpected keyword argument 'spam'"):
3032
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003033 self.call(test, spam=1)
3034
3035 def test_signature_bind_var(self):
3036 def test(*args, **kwargs):
3037 return args, kwargs
3038
3039 self.assertEqual(self.call(test), ((), {}))
3040 self.assertEqual(self.call(test, 1), ((1,), {}))
3041 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3042 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3043 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3044 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3045 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3046 ((1, 2), {'foo': 'bar'}))
3047
3048 def test_signature_bind_just_args(self):
3049 def test(a, b, c):
3050 return a, b, c
3051
3052 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3053
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003054 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003055 self.call(test, 1, 2, 3, 4)
3056
Yury Selivanov86872752015-05-19 00:27:49 -04003057 with self.assertRaisesRegex(TypeError,
3058 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003059 self.call(test, 1)
3060
Yury Selivanov86872752015-05-19 00:27:49 -04003061 with self.assertRaisesRegex(TypeError,
3062 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003063 self.call(test)
3064
3065 def test(a, b, c=10):
3066 return a, b, c
3067 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3068 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3069
3070 def test(a=1, b=2, c=3):
3071 return a, b, c
3072 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3073 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3074 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3075
3076 def test_signature_bind_varargs_order(self):
3077 def test(*args):
3078 return args
3079
3080 self.assertEqual(self.call(test), ())
3081 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3082
3083 def test_signature_bind_args_and_varargs(self):
3084 def test(a, b, c=3, *args):
3085 return a, b, c, args
3086
3087 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3088 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3089 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3090 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3091
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003092 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003093 "multiple values for argument 'c'"):
3094 self.call(test, 1, 2, 3, c=4)
3095
3096 def test_signature_bind_just_kwargs(self):
3097 def test(**kwargs):
3098 return kwargs
3099
3100 self.assertEqual(self.call(test), {})
3101 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3102 {'foo': 'bar', 'spam': 'ham'})
3103
3104 def test_signature_bind_args_and_kwargs(self):
3105 def test(a, b, c=3, **kwargs):
3106 return a, b, c, kwargs
3107
3108 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3109 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3110 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3111 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3112 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3113 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3114 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3115 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3116 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3117 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3118 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3119 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3120 (1, 2, 4, {'foo': 'bar'}))
3121 self.assertEqual(self.call(test, c=5, a=4, b=3),
3122 (4, 3, 5, {}))
3123
3124 def test_signature_bind_kwonly(self):
3125 def test(*, foo):
3126 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003127 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003128 'too many positional arguments'):
3129 self.call(test, 1)
3130 self.assertEqual(self.call(test, foo=1), 1)
3131
3132 def test(a, *, foo=1, bar):
3133 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003134 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003135 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003136 self.call(test, 1)
3137
3138 def test(foo, *, bar):
3139 return foo, bar
3140 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3141 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3142
Yury Selivanov86872752015-05-19 00:27:49 -04003143 with self.assertRaisesRegex(
3144 TypeError, "got an unexpected keyword argument 'spam'"):
3145
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003146 self.call(test, bar=2, foo=1, spam=10)
3147
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003148 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003149 'too many positional arguments'):
3150 self.call(test, 1, 2)
3151
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003152 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003153 'too many positional arguments'):
3154 self.call(test, 1, 2, bar=2)
3155
Yury Selivanov86872752015-05-19 00:27:49 -04003156 with self.assertRaisesRegex(
3157 TypeError, "got an unexpected keyword argument 'spam'"):
3158
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003159 self.call(test, 1, bar=2, spam='ham')
3160
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003161 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003162 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003163 self.call(test, 1)
3164
3165 def test(foo, *, bar, **bin):
3166 return foo, bar, bin
3167 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3168 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3169 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3170 (1, 2, {'spam': 'ham'}))
3171 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3172 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003173 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003174 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003175 self.call(test, spam='ham', bar=2)
3176 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3177 (1, 2, {'bin': 1, 'spam': 10}))
3178
3179 def test_signature_bind_arguments(self):
3180 def test(a, *args, b, z=100, **kwargs):
3181 pass
3182 sig = inspect.signature(test)
3183 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3184 # we won't have 'z' argument in the bound arguments object, as we didn't
3185 # pass it to the 'bind'
3186 self.assertEqual(tuple(ba.arguments.items()),
3187 (('a', 10), ('args', (20,)), ('b', 30),
3188 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3189 self.assertEqual(ba.kwargs,
3190 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3191 self.assertEqual(ba.args, (10, 20))
3192
3193 def test_signature_bind_positional_only(self):
3194 P = inspect.Parameter
3195
3196 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3197 return a_po, b_po, c_po, foo, bar, kwargs
3198
3199 sig = inspect.signature(test)
3200 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3201 for name in ('a_po', 'b_po', 'c_po'):
3202 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3203 new_sig = sig.replace(parameters=new_params.values())
3204 test.__signature__ = new_sig
3205
3206 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3207 (1, 2, 4, 5, 6, {}))
3208
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003209 self.assertEqual(self.call(test, 1, 2),
3210 (1, 2, 3, 42, 50, {}))
3211
3212 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3213 (1, 2, 3, 4, 5, {}))
3214
3215 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3216 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3217
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003218 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003219 self.call(test, 1, 2, c_po=4)
3220
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003221 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003222 self.call(test, a_po=1, b_po=2)
3223
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003224 def test_signature_bind_with_self_arg(self):
3225 # Issue #17071: one of the parameters is named "self
3226 def test(a, self, b):
3227 pass
3228 sig = inspect.signature(test)
3229 ba = sig.bind(1, 2, 3)
3230 self.assertEqual(ba.args, (1, 2, 3))
3231 ba = sig.bind(1, self=2, b=3)
3232 self.assertEqual(ba.args, (1, 2, 3))
3233
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003234 def test_signature_bind_vararg_name(self):
3235 def test(a, *args):
3236 return a, args
3237 sig = inspect.signature(test)
3238
Yury Selivanov86872752015-05-19 00:27:49 -04003239 with self.assertRaisesRegex(
3240 TypeError, "got an unexpected keyword argument 'args'"):
3241
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003242 sig.bind(a=0, args=1)
3243
3244 def test(*args, **kwargs):
3245 return args, kwargs
3246 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3247
3248 sig = inspect.signature(test)
3249 ba = sig.bind(args=1)
3250 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3251
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003252 @cpython_only
3253 def test_signature_bind_implicit_arg(self):
3254 # Issue #19611: getcallargs should work with set comprehensions
3255 def make_set():
3256 return {z * z for z in range(5)}
3257 setcomp_code = make_set.__code__.co_consts[1]
3258 setcomp_func = types.FunctionType(setcomp_code, {})
3259
3260 iterator = iter(range(5))
3261 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3262
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003263
3264class TestBoundArguments(unittest.TestCase):
3265 def test_signature_bound_arguments_unhashable(self):
3266 def foo(a): pass
3267 ba = inspect.signature(foo).bind(1)
3268
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003269 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003270 hash(ba)
3271
3272 def test_signature_bound_arguments_equality(self):
3273 def foo(a): pass
3274 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003275 self.assertTrue(ba == ba)
3276 self.assertFalse(ba != ba)
3277 self.assertTrue(ba == EqualsToAll())
3278 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003279
3280 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003281 self.assertTrue(ba == ba2)
3282 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003283
3284 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003285 self.assertFalse(ba == ba3)
3286 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003287 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003288 self.assertTrue(ba == ba3)
3289 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003290
3291 def bar(b): pass
3292 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003293 self.assertFalse(ba == ba4)
3294 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003295
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003296 def foo(*, a, b): pass
3297 sig = inspect.signature(foo)
3298 ba1 = sig.bind(a=1, b=2)
3299 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003300 self.assertTrue(ba1 == ba2)
3301 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003302
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003303 def test_signature_bound_arguments_pickle(self):
3304 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3305 sig = inspect.signature(foo)
3306 ba = sig.bind(20, 30, z={})
3307
3308 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3309 with self.subTest(pickle_ver=ver):
3310 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3311 self.assertEqual(ba, ba_pickled)
3312
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003313 def test_signature_bound_arguments_repr(self):
3314 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3315 sig = inspect.signature(foo)
3316 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003317 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003318
Yury Selivanovb907a512015-05-16 13:45:09 -04003319 def test_signature_bound_arguments_apply_defaults(self):
3320 def foo(a, b=1, *args, c:1={}, **kw): pass
3321 sig = inspect.signature(foo)
3322
3323 ba = sig.bind(20)
3324 ba.apply_defaults()
3325 self.assertEqual(
3326 list(ba.arguments.items()),
3327 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3328
3329 # Make sure that we preserve the order:
3330 # i.e. 'c' should be *before* 'kw'.
3331 ba = sig.bind(10, 20, 30, d=1)
3332 ba.apply_defaults()
3333 self.assertEqual(
3334 list(ba.arguments.items()),
3335 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3336
3337 # Make sure that BoundArguments produced by bind_partial()
3338 # are supported.
3339 def foo(a, b): pass
3340 sig = inspect.signature(foo)
3341 ba = sig.bind_partial(20)
3342 ba.apply_defaults()
3343 self.assertEqual(
3344 list(ba.arguments.items()),
3345 [('a', 20)])
3346
3347 # Test no args
3348 def foo(): pass
3349 sig = inspect.signature(foo)
3350 ba = sig.bind()
3351 ba.apply_defaults()
3352 self.assertEqual(list(ba.arguments.items()), [])
3353
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003354 # Make sure a no-args binding still acquires proper defaults.
3355 def foo(a='spam'): pass
3356 sig = inspect.signature(foo)
3357 ba = sig.bind()
3358 ba.apply_defaults()
3359 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3360
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003361
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003362class TestSignaturePrivateHelpers(unittest.TestCase):
3363 def test_signature_get_bound_param(self):
3364 getter = inspect._signature_get_bound_param
3365
3366 self.assertEqual(getter('($self)'), 'self')
3367 self.assertEqual(getter('($self, obj)'), 'self')
3368 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3369
Larry Hastings2623c8c2014-02-08 22:15:29 -08003370 def _strip_non_python_syntax(self, input,
3371 clean_signature, self_parameter, last_positional_only):
3372 computed_clean_signature, \
3373 computed_self_parameter, \
3374 computed_last_positional_only = \
3375 inspect._signature_strip_non_python_syntax(input)
3376 self.assertEqual(computed_clean_signature, clean_signature)
3377 self.assertEqual(computed_self_parameter, self_parameter)
3378 self.assertEqual(computed_last_positional_only, last_positional_only)
3379
3380 def test_signature_strip_non_python_syntax(self):
3381 self._strip_non_python_syntax(
3382 "($module, /, path, mode, *, dir_fd=None, " +
3383 "effective_ids=False,\n follow_symlinks=True)",
3384 "(module, path, mode, *, dir_fd=None, " +
3385 "effective_ids=False, follow_symlinks=True)",
3386 0,
3387 0)
3388
3389 self._strip_non_python_syntax(
3390 "($module, word, salt, /)",
3391 "(module, word, salt)",
3392 0,
3393 2)
3394
3395 self._strip_non_python_syntax(
3396 "(x, y=None, z=None, /)",
3397 "(x, y=None, z=None)",
3398 None,
3399 2)
3400
3401 self._strip_non_python_syntax(
3402 "(x, y=None, z=None)",
3403 "(x, y=None, z=None)",
3404 None,
3405 None)
3406
3407 self._strip_non_python_syntax(
3408 "(x,\n y=None,\n z = None )",
3409 "(x, y=None, z=None)",
3410 None,
3411 None)
3412
3413 self._strip_non_python_syntax(
3414 "",
3415 "",
3416 None,
3417 None)
3418
3419 self._strip_non_python_syntax(
3420 None,
3421 None,
3422 None,
3423 None)
3424
Nick Coghlan9c680b02015-04-13 12:54:54 -04003425class TestSignatureDefinitions(unittest.TestCase):
3426 # This test case provides a home for checking that particular APIs
3427 # have signatures available for introspection
3428
3429 @cpython_only
3430 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3431 "Signature information for builtins requires docstrings")
3432 def test_builtins_have_signatures(self):
3433 # This checks all builtin callables in CPython have signatures
3434 # A few have signatures Signature can't yet handle, so we skip those
3435 # since they will have to wait until PEP 457 adds the required
3436 # introspection support to the inspect module
3437 # Some others also haven't been converted yet for various other
3438 # reasons, so we also skip those for the time being, but design
3439 # the test to fail in order to indicate when it needs to be
3440 # updated.
3441 no_signature = set()
3442 # These need PEP 457 groups
3443 needs_groups = {"range", "slice", "dir", "getattr",
3444 "next", "iter", "vars"}
3445 no_signature |= needs_groups
3446 # These need PEP 457 groups or a signature change to accept None
3447 needs_semantic_update = {"round"}
3448 no_signature |= needs_semantic_update
3449 # These need *args support in Argument Clinic
3450 needs_varargs = {"min", "max", "print", "__build_class__"}
3451 no_signature |= needs_varargs
3452 # These simply weren't covered in the initial AC conversion
3453 # for builtin callables
3454 not_converted_yet = {"open", "__import__"}
3455 no_signature |= not_converted_yet
3456 # These builtin types are expected to provide introspection info
3457 types_with_signatures = set()
3458 # Check the signatures we expect to be there
3459 ns = vars(builtins)
3460 for name, obj in sorted(ns.items()):
3461 if not callable(obj):
3462 continue
3463 # The builtin types haven't been converted to AC yet
3464 if isinstance(obj, type) and (name not in types_with_signatures):
3465 # Note that this also skips all the exception types
3466 no_signature.add(name)
3467 if (name in no_signature):
3468 # Not yet converted
3469 continue
3470 with self.subTest(builtin=name):
3471 self.assertIsNotNone(inspect.signature(obj))
3472 # Check callables that haven't been converted don't claim a signature
3473 # This ensures this test will start failing as more signatures are
3474 # added, so the affected items can be moved into the scope of the
3475 # regression test above
3476 for name in no_signature:
3477 with self.subTest(builtin=name):
3478 self.assertIsNone(obj.__text_signature__)
3479
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003480
Nick Coghlane8c45d62013-07-28 20:00:01 +10003481class TestUnwrap(unittest.TestCase):
3482
3483 def test_unwrap_one(self):
3484 def func(a, b):
3485 return a + b
3486 wrapper = functools.lru_cache(maxsize=20)(func)
3487 self.assertIs(inspect.unwrap(wrapper), func)
3488
3489 def test_unwrap_several(self):
3490 def func(a, b):
3491 return a + b
3492 wrapper = func
3493 for __ in range(10):
3494 @functools.wraps(wrapper)
3495 def wrapper():
3496 pass
3497 self.assertIsNot(wrapper.__wrapped__, func)
3498 self.assertIs(inspect.unwrap(wrapper), func)
3499
3500 def test_stop(self):
3501 def func1(a, b):
3502 return a + b
3503 @functools.wraps(func1)
3504 def func2():
3505 pass
3506 @functools.wraps(func2)
3507 def wrapper():
3508 pass
3509 func2.stop_here = 1
3510 unwrapped = inspect.unwrap(wrapper,
3511 stop=(lambda f: hasattr(f, "stop_here")))
3512 self.assertIs(unwrapped, func2)
3513
3514 def test_cycle(self):
3515 def func1(): pass
3516 func1.__wrapped__ = func1
3517 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3518 inspect.unwrap(func1)
3519
3520 def func2(): pass
3521 func2.__wrapped__ = func1
3522 func1.__wrapped__ = func2
3523 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3524 inspect.unwrap(func1)
3525 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3526 inspect.unwrap(func2)
3527
3528 def test_unhashable(self):
3529 def func(): pass
3530 func.__wrapped__ = None
3531 class C:
3532 __hash__ = None
3533 __wrapped__ = func
3534 self.assertIsNone(inspect.unwrap(C()))
3535
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003536class TestMain(unittest.TestCase):
3537 def test_only_source(self):
3538 module = importlib.import_module('unittest')
3539 rc, out, err = assert_python_ok('-m', 'inspect',
3540 'unittest')
3541 lines = out.decode().splitlines()
3542 # ignore the final newline
3543 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3544 self.assertEqual(err, b'')
3545
Yury Selivanov42407ab2014-06-23 10:23:50 -07003546 def test_custom_getattr(self):
3547 def foo():
3548 pass
3549 foo.__signature__ = 42
3550 with self.assertRaises(TypeError):
3551 inspect.signature(foo)
3552
Brett Cannon634a8fc2013-10-02 10:25:42 -04003553 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003554 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003555 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003556 rc, out, err = assert_python_ok('-m', 'inspect',
3557 'concurrent.futures:ThreadPoolExecutor')
3558 lines = out.decode().splitlines()
3559 # ignore the final newline
3560 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003561 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003562 self.assertEqual(err, b'')
3563
3564 def test_builtins(self):
3565 module = importlib.import_module('unittest')
3566 _, out, err = assert_python_failure('-m', 'inspect',
3567 'sys')
3568 lines = err.decode().splitlines()
3569 self.assertEqual(lines, ["Can't get info for builtin modules."])
3570
3571 def test_details(self):
3572 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003573 args = support.optim_args_from_interpreter_flags()
3574 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003575 'unittest', '--details')
3576 output = out.decode()
3577 # Just a quick sanity check on the output
3578 self.assertIn(module.__name__, output)
3579 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003580 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003581 self.assertEqual(err, b'')
3582
3583
Yury Selivanovef1e7502014-12-08 16:05:34 -05003584class TestReload(unittest.TestCase):
3585
3586 src_before = textwrap.dedent("""\
3587def foo():
3588 print("Bla")
3589 """)
3590
3591 src_after = textwrap.dedent("""\
3592def foo():
3593 print("Oh no!")
3594 """)
3595
3596 def assertInspectEqual(self, path, source):
3597 inspected_src = inspect.getsource(source)
3598 with open(path) as src:
3599 self.assertEqual(
3600 src.read().splitlines(True),
3601 inspected_src.splitlines(True)
3602 )
3603
3604 def test_getsource_reload(self):
3605 # see issue 1218234
3606 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3607 module = importlib.import_module(name)
3608 self.assertInspectEqual(path, module)
3609 with open(path, 'w') as src:
3610 src.write(self.src_after)
3611 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003612
Nick Coghlane8c45d62013-07-28 20:00:01 +10003613
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003614def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003615 run_unittest(
3616 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3617 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3618 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003619 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003620 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003621 TestBoundArguments, TestSignaturePrivateHelpers,
3622 TestSignatureDefinitions,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003623 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
3624 TestGetCoroutineState
Michael Foord95fc51d2010-11-20 15:07:30 +00003625 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003626
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003627if __name__ == "__main__":
3628 test_main()