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