blob: bd0605e6c37d36e66c884ca7bd534a84f37ebde1 [file] [log] [blame]
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001import builtins
Guido van Rossum813b0e52007-05-21 18:11:34 +00002import collections
Larry Hastings5c661892014-01-24 06:17:25 -08003import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10004import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10005import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08006import inspect
7import io
8import linecache
9import os
Christian Heimesa3538eb2007-11-06 11:44:48 +000010from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080011import _pickle
Yury Selivanova5d63dd2014-03-27 11:31:43 -040012import pickle
Larry Hastings5c661892014-01-24 06:17:25 -080013import re
14import shutil
15import sys
16import types
Yury Selivanovef1e7502014-12-08 16:05:34 -050017import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080018import unicodedata
19import unittest
Yury Selivanova773de02014-02-21 18:30:53 -050020import unittest.mock
Yury Selivanov75445082015-05-11 22:57:16 -040021import warnings
Larry Hastings5c661892014-01-24 06:17:25 -080022
Brett Cannon634a8fc2013-10-02 10:25:42 -040023try:
24 from concurrent.futures import ThreadPoolExecutor
25except ImportError:
26 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000027
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020028from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Nick Coghlanf9e227e2014-08-17 14:01:19 +100029from test.support import MISSING_C_DOCSTRINGS, cpython_only
Berker Peksagce643912015-05-06 06:33:17 +030030from test.support.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000031from test import inspect_fodder as mod
32from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000033
Yury Selivanovef1e7502014-12-08 16:05:34 -050034from test.test_import import _ready_to_import
35
R. David Murray74b89242009-05-13 17:33:03 +000036
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000037# Functions tested in this suite:
38# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000039# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
40# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
41# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
42# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000043
Nick Coghlanf088e5e2008-12-14 11:50:48 +000044# NOTE: There are some additional tests relating to interaction with
45# zipimport in the test_zipimport_support test module.
46
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000047modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000048if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000049 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000050
Christian Heimesa3538eb2007-11-06 11:44:48 +000051# Normalize file names: on Windows, the case of file names of compiled
52# modules depends on the path used to start the python executable.
53modfile = normcase(modfile)
54
55def revise(filename, *args):
56 return (normcase(filename),) + args
57
Georg Brandl1a3284e2007-12-02 09:40:06 +000058import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000059
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000060git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000061
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000062class IsTestBase(unittest.TestCase):
63 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
64 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000065 inspect.ismodule, inspect.istraceback,
Yury Selivanov75445082015-05-11 22:57:16 -040066 inspect.isgenerator, inspect.isgeneratorfunction,
67 inspect.iscoroutine, inspect.iscoroutinefunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000068
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000069 def istest(self, predicate, exp):
70 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000071 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000072
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000073 for other in self.predicates - set([predicate]):
Yury Selivanov75445082015-05-11 22:57:16 -040074 if (predicate == inspect.isgeneratorfunction or \
75 predicate == inspect.iscoroutinefunction) and \
Christian Heimes7131fd92008-02-19 14:21:46 +000076 other == inspect.isfunction:
77 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000078 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000079
Christian Heimes7131fd92008-02-19 14:21:46 +000080def generator_function_example(self):
81 for i in range(2):
82 yield i
83
Yury Selivanov75445082015-05-11 22:57:16 -040084async def coroutine_function_example(self):
85 return 'spam'
86
87@types.coroutine
88def gen_coroutine_function_example(self):
89 yield
90 return 'spam'
91
Serhiy Storchaka3018cc42015-07-18 23:19:05 +030092class EqualsToAll:
93 def __eq__(self, other):
94 return True
Yury Selivanova5d63dd2014-03-27 11:31:43 -040095
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000096class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +000097
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000098 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020099 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000100 self.istest(inspect.isbuiltin, 'sys.exit')
101 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +0000102 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200103 try:
104 1/0
105 except:
106 tb = sys.exc_info()[2]
107 self.istest(inspect.isframe, 'tb.tb_frame')
108 self.istest(inspect.istraceback, 'tb')
109 if hasattr(types, 'GetSetDescriptorType'):
110 self.istest(inspect.isgetsetdescriptor,
111 'type(tb.tb_frame).f_locals')
112 else:
113 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
114 finally:
115 # Clear traceback and all the frames and local variables hanging to it.
116 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000117 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000118 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000119 self.istest(inspect.ismethod, 'git.argue')
120 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000121 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000122 self.istest(inspect.isgenerator, '(x for x in range(2))')
123 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400124
125 with warnings.catch_warnings():
126 warnings.simplefilter("ignore")
127 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
128 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
129
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000130 if hasattr(types, 'MemberDescriptorType'):
131 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
132 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000133 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000134
Yury Selivanov75445082015-05-11 22:57:16 -0400135 def test_iscoroutine(self):
136 gen_coro = gen_coroutine_function_example(1)
137 coro = coroutine_function_example(1)
138
Yury Selivanov5376ba92015-06-22 12:19:30 -0400139 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400140 inspect.iscoroutinefunction(gen_coroutine_function_example))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400141 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400142
143 self.assertTrue(
144 inspect.isgeneratorfunction(gen_coroutine_function_example))
145 self.assertTrue(inspect.isgenerator(gen_coro))
146
147 self.assertTrue(
148 inspect.iscoroutinefunction(coroutine_function_example))
149 self.assertTrue(inspect.iscoroutine(coro))
150
151 self.assertFalse(
152 inspect.isgeneratorfunction(coroutine_function_example))
153 self.assertFalse(inspect.isgenerator(coro))
154
155 coro.close(); gen_coro.close() # silence warnings
156
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400157 def test_isawaitable(self):
158 def gen(): yield
159 self.assertFalse(inspect.isawaitable(gen()))
160
161 coro = coroutine_function_example(1)
162 gen_coro = gen_coroutine_function_example(1)
163
164 self.assertTrue(inspect.isawaitable(coro))
165 self.assertTrue(inspect.isawaitable(gen_coro))
166
167 class Future:
168 def __await__():
169 pass
170 self.assertTrue(inspect.isawaitable(Future()))
171 self.assertFalse(inspect.isawaitable(Future))
172
173 class NotFuture: pass
174 not_fut = NotFuture()
175 not_fut.__await__ = lambda: None
176 self.assertFalse(inspect.isawaitable(not_fut))
177
178 coro.close(); gen_coro.close() # silence warnings
179
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000180 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000181 self.assertTrue(inspect.isroutine(mod.spam))
182 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000183
Benjamin Petersonc4656002009-01-17 22:41:18 +0000184 def test_isclass(self):
185 self.istest(inspect.isclass, 'mod.StupidGit')
186 self.assertTrue(inspect.isclass(list))
187
188 class CustomGetattr(object):
189 def __getattr__(self, attr):
190 return None
191 self.assertFalse(inspect.isclass(CustomGetattr()))
192
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000193 def test_get_slot_members(self):
194 class C(object):
195 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000196 x = C()
197 x.a = 42
198 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000199 self.assertIn('a', members)
200 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000201
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000202 def test_isabstract(self):
203 from abc import ABCMeta, abstractmethod
204
205 class AbstractClassExample(metaclass=ABCMeta):
206
207 @abstractmethod
208 def foo(self):
209 pass
210
211 class ClassExample(AbstractClassExample):
212 def foo(self):
213 pass
214
215 a = ClassExample()
216
217 # Test general behaviour.
218 self.assertTrue(inspect.isabstract(AbstractClassExample))
219 self.assertFalse(inspect.isabstract(ClassExample))
220 self.assertFalse(inspect.isabstract(a))
221 self.assertFalse(inspect.isabstract(int))
222 self.assertFalse(inspect.isabstract(5))
223
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000224
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000225class TestInterpreterStack(IsTestBase):
226 def __init__(self, *args, **kwargs):
227 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000228
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000229 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000230
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000231 def test_abuse_done(self):
232 self.istest(inspect.istraceback, 'git.ex[2]')
233 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000234
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000235 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000236 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000237 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000238 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000239 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000240 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000241 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000242 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000243 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000244 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400245 # Test named tuple fields
246 record = mod.st[0]
247 self.assertIs(record.frame, mod.fr)
248 self.assertEqual(record.lineno, 16)
249 self.assertEqual(record.filename, mod.__file__)
250 self.assertEqual(record.function, 'eggs')
251 self.assertIn('inspect.stack()', record.code_context[0])
252 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000253
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000254 def test_trace(self):
255 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000256 self.assertEqual(revise(*git.tr[0][1:]),
257 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
258 self.assertEqual(revise(*git.tr[1][1:]),
259 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
260 self.assertEqual(revise(*git.tr[2][1:]),
261 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000262
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000263 def test_frame(self):
264 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
265 self.assertEqual(args, ['x', 'y'])
266 self.assertEqual(varargs, None)
267 self.assertEqual(varkw, None)
268 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
269 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
270 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000271
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000272 def test_previous_frame(self):
273 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000274 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000275 self.assertEqual(varargs, 'g')
276 self.assertEqual(varkw, 'h')
277 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000278 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000279
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000280class GetSourceBase(unittest.TestCase):
281 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000282 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000283
Yury Selivanov6738b112015-05-16 10:10:21 -0400284 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000285 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000286 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000287
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000288 def sourcerange(self, top, bottom):
289 lines = self.source.split("\n")
290 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000291
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000292 def assertSourceEqual(self, obj, top, bottom):
293 self.assertEqual(inspect.getsource(obj),
294 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000295
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000296class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000297 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000298
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000299 def test_getclasses(self):
300 classes = inspect.getmembers(mod, inspect.isclass)
301 self.assertEqual(classes,
302 [('FesteringGob', mod.FesteringGob),
303 ('MalodorousPervert', mod.MalodorousPervert),
304 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300305 ('StupidGit', mod.StupidGit),
306 ('Tit', mod.MalodorousPervert),
307 ])
308 tree = inspect.getclasstree([cls[1] for cls in classes])
309 self.assertEqual(tree,
310 [(object, ()),
311 [(mod.ParrotDroppings, (object,)),
312 [(mod.FesteringGob, (mod.MalodorousPervert,
313 mod.ParrotDroppings))
314 ],
315 (mod.StupidGit, (object,)),
316 [(mod.MalodorousPervert, (mod.StupidGit,)),
317 [(mod.FesteringGob, (mod.MalodorousPervert,
318 mod.ParrotDroppings))
319 ]
320 ]
321 ]
322 ])
323 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000324 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000325 [(object, ()),
326 [(mod.ParrotDroppings, (object,)),
327 (mod.StupidGit, (object,)),
328 [(mod.MalodorousPervert, (mod.StupidGit,)),
329 [(mod.FesteringGob, (mod.MalodorousPervert,
330 mod.ParrotDroppings))
331 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000332 ]
333 ]
334 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000335
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000336 def test_getfunctions(self):
337 functions = inspect.getmembers(mod, inspect.isfunction)
338 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300339 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000340 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000341
R. David Murray378c0cf2010-02-24 01:46:21 +0000342 @unittest.skipIf(sys.flags.optimize >= 2,
343 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000344 def test_getdoc(self):
345 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
346 self.assertEqual(inspect.getdoc(mod.StupidGit),
347 'A longer,\n\nindented\n\ndocstring.')
348 self.assertEqual(inspect.getdoc(git.abuse),
349 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000350
Serhiy Storchaka5cf2b7252015-04-03 22:38:53 +0300351 @unittest.skipIf(sys.flags.optimize >= 2,
352 "Docstrings are omitted with -O2 and above")
353 def test_getdoc_inherited(self):
354 self.assertEqual(inspect.getdoc(mod.FesteringGob),
355 'A longer,\n\nindented\n\ndocstring.')
356 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
357 'Another\n\ndocstring\n\ncontaining\n\ntabs')
358 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
359 'Another\n\ndocstring\n\ncontaining\n\ntabs')
360 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
361 'The automatic gainsaying.')
362
363 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
364 def test_finddoc(self):
365 finddoc = inspect._finddoc
366 self.assertEqual(finddoc(int), int.__doc__)
367 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
368 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
369 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
370 self.assertEqual(finddoc(int.real), int.real.__doc__)
371
Georg Brandl0c77a822008-06-10 16:37:50 +0000372 def test_cleandoc(self):
373 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
374 'An\nindented\ndocstring.')
375
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000376 def test_getcomments(self):
377 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
378 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000379
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000380 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000381 # Check actual module
382 self.assertEqual(inspect.getmodule(mod), mod)
383 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000384 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000385 # Check a method (no __module__ attribute, falls back to filename)
386 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
387 # Do it again (check the caching isn't broken)
388 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
389 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000390 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000391 # Check filename override
392 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000393
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000394 def test_getsource(self):
395 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchaka5cf2b7252015-04-03 22:38:53 +0300396 self.assertSourceEqual(mod.StupidGit, 21, 50)
Yury Selivanove4e811d2015-07-21 19:01:52 +0300397 self.assertSourceEqual(mod.lobbest, 70, 71)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000398
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000399 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000400 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
401 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000402 fn = "_non_existing_filename_used_for_sourcefile_test.py"
403 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000404 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000405 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200406 try:
407 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
408 finally:
409 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000410
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000411 def test_getfile(self):
412 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000413
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500414 def test_getfile_class_without_module(self):
415 class CM(type):
416 @property
417 def __module__(cls):
418 raise AttributeError
419 class C(metaclass=CM):
420 pass
421 with self.assertRaises(TypeError):
422 inspect.getfile(C)
423
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000424 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000425 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000426 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000427 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000428 m.__file__ = "<string>" # hopefully not a real filename...
429 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000430 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000431 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000432 del sys.modules[name]
433 inspect.getmodule(compile('a=10','','single'))
434
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500435 def test_proceed_with_fake_filename(self):
436 '''doctest monkeypatches linecache to enable inspection'''
437 fn, source = '<test>', 'def x(): pass\n'
438 getlines = linecache.getlines
439 def monkey(filename, module_globals=None):
440 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300441 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500442 else:
443 return getlines(filename, module_globals)
444 linecache.getlines = monkey
445 try:
446 ns = {}
447 exec(compile(source, fn, 'single'), ns)
448 inspect.getsource(ns["x"])
449 finally:
450 linecache.getlines = getlines
451
Antoine Pitroua8723a02015-04-15 00:41:29 +0200452 def test_getsource_on_code_object(self):
453 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
454
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000455class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000456 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000457
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000458 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000459 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000460
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000461 def test_replacing_decorator(self):
462 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000463
Yury Selivanov081bbf62014-09-26 17:34:54 -0400464 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200465 self.assertSourceEqual(mod2.real, 130, 132)
466
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300467 @unittest.expectedFailure
Antoine Pitroua8723a02015-04-15 00:41:29 +0200468 def test_decorator_with_lambda(self):
469 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400470
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000471class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000472 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000473 def test_oneline_lambda(self):
474 # Test inspect.getsource with a one-line lambda function.
475 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000476
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000477 def test_threeline_lambda(self):
478 # Test inspect.getsource with a three-line lambda function,
479 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000480 self.assertSourceEqual(mod2.tll, 28, 30)
481
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000482 def test_twoline_indented_lambda(self):
483 # Test inspect.getsource with a two-line lambda function,
484 # where the second line _is_ indented.
485 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000486
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000487 def test_onelinefunc(self):
488 # Test inspect.getsource with a regular one-line function.
489 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000490
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000491 def test_manyargs(self):
492 # Test inspect.getsource with a regular function where
493 # the arguments are on two lines and _not_ indented and
494 # the body on the second line with the last arguments.
495 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000496
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000497 def test_twolinefunc(self):
498 # Test inspect.getsource with a regular function where
499 # the body is on two lines, following the argument list and
500 # continued on the next line by a \\.
501 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000502
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000503 def test_lambda_in_list(self):
504 # Test inspect.getsource with a one-line lambda function
505 # defined in a list, indented.
506 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000507
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000508 def test_anonymous(self):
509 # Test inspect.getsource with a lambda function defined
510 # as argument to another function.
511 self.assertSourceEqual(mod2.anonymous, 55, 55)
512
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000513class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000514 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000515
516 def test_with_comment(self):
517 self.assertSourceEqual(mod2.with_comment, 58, 59)
518
519 def test_multiline_sig(self):
520 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
521
Armin Rigodd5c0232005-09-25 11:45:45 +0000522 def test_nested_class(self):
523 self.assertSourceEqual(mod2.func69().func71, 71, 72)
524
525 def test_one_liner_followed_by_non_name(self):
526 self.assertSourceEqual(mod2.func77, 77, 77)
527
528 def test_one_liner_dedent_non_name(self):
529 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
530
531 def test_with_comment_instead_of_docstring(self):
532 self.assertSourceEqual(mod2.func88, 88, 90)
533
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000534 def test_method_in_dynamic_class(self):
535 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
536
R David Murray32562d72014-10-03 11:15:38 -0400537 # This should not skip for CPython, but might on a repackaged python where
538 # unicodedata is not an external module, or on pypy.
539 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
540 unicodedata.__file__.endswith('.py'),
541 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000542 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200543 self.assertRaises(OSError, inspect.getsource, unicodedata)
544 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000545
R. David Murraya1b37402010-06-17 02:04:29 +0000546 def test_findsource_code_in_linecache(self):
547 lines = ["x=1"]
548 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200549 self.assertRaises(OSError, inspect.findsource, co)
550 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000551 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200552 try:
553 self.assertEqual(inspect.findsource(co), (lines,0))
554 self.assertEqual(inspect.getsource(co), lines[0])
555 finally:
556 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000557
Ezio Melotti1b145922013-03-30 05:17:24 +0200558 def test_findsource_without_filename(self):
559 for fname in ['', '<string>']:
560 co = compile('x=1', fname, "exec")
561 self.assertRaises(IOError, inspect.findsource, co)
562 self.assertRaises(IOError, inspect.getsource, co)
563
Antoine Pitroua8723a02015-04-15 00:41:29 +0200564 def test_getsource_on_method(self):
565 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
566
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300567 def test_nested_func(self):
568 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
569
570
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000571class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400572 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000573 self.tempdir = TESTFN + '_dir'
574 os.mkdir(self.tempdir)
575 with open(os.path.join(self.tempdir,
576 'inspect_fodder3%spy' % os.extsep), 'w') as f:
577 f.write("class X:\n pass # No EOL")
578 with DirsOnSysPath(self.tempdir):
579 import inspect_fodder3 as mod3
580 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400581 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000582
583 def tearDown(self):
584 shutil.rmtree(self.tempdir)
585
586 def test_class(self):
587 self.assertSourceEqual(self.fodderModule.X, 1, 2)
588
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100589
590class _BrokenDataDescriptor(object):
591 """
592 A broken data descriptor. See bug #1785.
593 """
594 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700595 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100596
597 def __set__(*args):
598 raise RuntimeError
599
600 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700601 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100602
603
604class _BrokenMethodDescriptor(object):
605 """
606 A broken method descriptor. See bug #1785.
607 """
608 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700609 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100610
611 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700612 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100613
614
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000615# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000616def attrs_wo_objs(cls):
617 return [t[:3] for t in inspect.classify_class_attrs(cls)]
618
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100619
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000620class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000621 def test_newstyle_mro(self):
622 # The same w/ new-class MRO.
623 class A(object): pass
624 class B(A): pass
625 class C(A): pass
626 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000627
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000628 expected = (D, B, C, A, object)
629 got = inspect.getmro(D)
630 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000631
Christian Heimes3795b532007-11-08 13:48:53 +0000632 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
633 varkw_e=None, defaults_e=None,
634 kwonlyargs_e=[], kwonlydefaults_e=None,
635 ann_e={}, formatted=None):
636 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
637 inspect.getfullargspec(routine)
638 self.assertEqual(args, args_e)
639 self.assertEqual(varargs, varargs_e)
640 self.assertEqual(varkw, varkw_e)
641 self.assertEqual(defaults, defaults_e)
642 self.assertEqual(kwonlyargs, kwonlyargs_e)
643 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
644 self.assertEqual(ann, ann_e)
645 if formatted is not None:
646 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
647 kwonlyargs, kwonlydefaults, ann),
648 formatted)
649
Christian Heimes3795b532007-11-08 13:48:53 +0000650 def test_getfullargspec(self):
651 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
652 kwonlyargs_e=['arg2'],
653 kwonlydefaults_e={'arg2':1},
654 formatted='(*arg1, arg2=1)')
655
656 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000657 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000658 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000659 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
660 kwonlyargs_e=['arg'],
661 formatted='(*, arg)')
662
Yury Selivanovf1b5ccb2015-07-23 17:36:02 +0300663 def test_fullargspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500664 # Issue 20684: low level introspection API must ignore __wrapped__
665 @functools.wraps(mod.spam)
666 def ham(x, y):
667 pass
668 # Basic check
Yury Selivanov57d240e2014-02-19 16:27:23 -0500669 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
670 self.assertFullArgSpecEquals(functools.partial(ham),
671 ['x', 'y'], formatted='(x, y)')
672 # Other variants
673 def check_method(f):
Yury Selivanovf1b5ccb2015-07-23 17:36:02 +0300674 self.assertFullArgSpecEquals(f, ['self', 'x', 'y'],
675 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500676 class C:
677 @functools.wraps(mod.spam)
678 def ham(self, x, y):
679 pass
680 pham = functools.partialmethod(ham)
681 @functools.wraps(mod.spam)
682 def __call__(self, x, y):
683 pass
684 check_method(C())
685 check_method(C.ham)
686 check_method(C().ham)
687 check_method(C.pham)
688 check_method(C().pham)
689
690 class C_new:
691 @functools.wraps(mod.spam)
692 def __new__(self, x, y):
693 pass
694 check_method(C_new)
695
696 class C_init:
697 @functools.wraps(mod.spam)
698 def __init__(self, x, y):
699 pass
700 check_method(C_init)
701
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500702 def test_getfullargspec_signature_attr(self):
703 def test():
704 pass
705 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
706 test.__signature__ = inspect.Signature(parameters=(spam_param,))
707
708 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
709
Yury Selivanov4cb93912014-01-29 11:54:12 -0500710 def test_getfullargspec_signature_annos(self):
711 def test(a:'spam') -> 'ham': pass
712 spec = inspect.getfullargspec(test)
713 self.assertEqual(test.__annotations__, spec.annotations)
714
715 def test(): pass
716 spec = inspect.getfullargspec(test)
717 self.assertEqual(test.__annotations__, spec.annotations)
718
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500719 @unittest.skipIf(MISSING_C_DOCSTRINGS,
720 "Signature information for builtins requires docstrings")
721 def test_getfullargspec_builtin_methods(self):
722 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
723 args_e=['self', 'obj'], formatted='(self, obj)')
724
725 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
726 args_e=['self', 'obj'], formatted='(self, obj)')
727
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500728 self.assertFullArgSpecEquals(
729 os.stat,
730 args_e=['path'],
731 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
732 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
733 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
734
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200735 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500736 @unittest.skipIf(MISSING_C_DOCSTRINGS,
737 "Signature information for builtins requires docstrings")
738 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200739 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500740 builtin = _testcapi.docstring_with_signature_with_defaults
741 spec = inspect.getfullargspec(builtin)
742 self.assertEqual(spec.defaults[0], 'avocado')
743
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200744 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500745 @unittest.skipIf(MISSING_C_DOCSTRINGS,
746 "Signature information for builtins requires docstrings")
747 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200748 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500749 builtin = _testcapi.docstring_no_signature
750 with self.assertRaises(TypeError):
751 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000752
Yury Selivanovf1b5ccb2015-07-23 17:36:02 +0300753 def test_getfullargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000754 class A(object):
755 def m(self):
756 pass
Yury Selivanovf1b5ccb2015-07-23 17:36:02 +0300757 self.assertFullArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000758
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000759 def test_classify_newstyle(self):
760 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000761
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000762 def s(): pass
763 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000764
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000765 def c(cls): pass
766 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000767
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000768 def getp(self): pass
769 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000770
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000771 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000772
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000773 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000774
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000775 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000776
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100777 dd = _BrokenDataDescriptor()
778 md = _BrokenMethodDescriptor()
779
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000780 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500781
782 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
783 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
784
Benjamin Peterson577473f2010-01-19 00:09:57 +0000785 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
786 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
787 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000788 self.assertIn(('m', 'method', A), attrs,
789 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000790 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
791 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100792 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
793 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000794
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000795 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000796
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000797 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000798
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000799 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000800 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
801 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
802 self.assertIn(('p', 'property', A), attrs, 'missing property')
803 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
804 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
805 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100806 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
807 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000808
809
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000810 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000811
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000812 def m(self): pass
813 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000814
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000815 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000816 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
817 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
818 self.assertIn(('p', 'property', A), attrs, 'missing property')
819 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
820 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 D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000826
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000827 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000828
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000829 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000830 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
831 self.assertIn(('c', 'method', C), attrs, 'missing plain 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', D), 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')
838
839 def test_classify_builtin_types(self):
840 # Simple sanity check that all built-in types can have their
841 # attributes classified.
842 for name in dir(__builtins__):
843 builtin = getattr(__builtins__, name)
844 if isinstance(builtin, type):
845 inspect.classify_class_attrs(builtin)
846
Ethan Furman63c141c2013-10-18 00:27:39 -0700847 def test_classify_DynamicClassAttribute(self):
848 class Meta(type):
849 def __getattr__(self, name):
850 if name == 'ham':
851 return 'spam'
852 return super().__getattr__(name)
853 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700854 @types.DynamicClassAttribute
855 def ham(self):
856 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700857 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
858 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700859 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700860 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
861
Yury Selivanovbf341fb2015-05-21 15:41:57 -0400862 def test_classify_overrides_bool(self):
863 class NoBool(object):
864 def __eq__(self, other):
865 return NoBool()
866
867 def __bool__(self):
868 raise NotImplementedError(
869 "This object does not specify a boolean value")
870
871 class HasNB(object):
872 dd = NoBool()
873
874 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
875 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
876
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700877 def test_classify_metaclass_class_attribute(self):
878 class Meta(type):
879 fish = 'slap'
880 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200881 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700882 class Class(metaclass=Meta):
883 pass
884 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
885 self.assertIn(should_find, inspect.classify_class_attrs(Class))
886
Ethan Furman63c141c2013-10-18 00:27:39 -0700887 def test_classify_VirtualAttribute(self):
888 class Meta(type):
889 def __dir__(cls):
890 return ['__class__', '__module__', '__name__', 'BOOM']
891 def __getattr__(self, name):
892 if name =='BOOM':
893 return 42
894 return super().__getattr(name)
895 class Class(metaclass=Meta):
896 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700897 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700898 self.assertIn(should_find, inspect.classify_class_attrs(Class))
899
900 def test_classify_VirtualAttribute_multi_classes(self):
901 class Meta1(type):
902 def __dir__(cls):
903 return ['__class__', '__module__', '__name__', 'one']
904 def __getattr__(self, name):
905 if name =='one':
906 return 1
907 return super().__getattr__(name)
908 class Meta2(type):
909 def __dir__(cls):
910 return ['__class__', '__module__', '__name__', 'two']
911 def __getattr__(self, name):
912 if name =='two':
913 return 2
914 return super().__getattr__(name)
915 class Meta3(Meta1, Meta2):
916 def __dir__(cls):
917 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
918 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
919 def __getattr__(self, name):
920 if name =='three':
921 return 3
922 return super().__getattr__(name)
923 class Class1(metaclass=Meta1):
924 pass
925 class Class2(Class1, metaclass=Meta3):
926 pass
927
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700928 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
929 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
930 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700931 cca = inspect.classify_class_attrs(Class2)
932 for sf in (should_find1, should_find2, should_find3):
933 self.assertIn(sf, cca)
934
935 def test_classify_class_attrs_with_buggy_dir(self):
936 class M(type):
937 def __dir__(cls):
938 return ['__class__', '__name__', 'missing']
939 class C(metaclass=M):
940 pass
941 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
942 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700943
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100944 def test_getmembers_descriptors(self):
945 class A(object):
946 dd = _BrokenDataDescriptor()
947 md = _BrokenMethodDescriptor()
948
949 def pred_wrapper(pred):
950 # A quick'n'dirty way to discard standard attributes of new-style
951 # classes.
952 class Empty(object):
953 pass
954 def wrapped(x):
955 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
956 return False
957 return pred(x)
958 return wrapped
959
960 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
961 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
962
963 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
964 [('md', A.__dict__['md'])])
965 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
966 [('dd', A.__dict__['dd'])])
967
968 class B(A):
969 pass
970
971 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
972 [('md', A.__dict__['md'])])
973 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
974 [('dd', A.__dict__['dd'])])
975
Antoine Pitrou0c603812012-01-18 17:40:18 +0100976 def test_getmembers_method(self):
977 class B:
978 def f(self):
979 pass
980
981 self.assertIn(('f', B.f), inspect.getmembers(B))
982 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
983 b = B()
984 self.assertIn(('f', b.f), inspect.getmembers(b))
985 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
986
Ethan Furmane03ea372013-09-25 07:14:41 -0700987 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700988 class M(type):
989 def __getattr__(cls, name):
990 if name == 'eggs':
991 return 'scrambled'
992 return super().__getattr__(name)
993 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700994 @types.DynamicClassAttribute
995 def eggs(self):
996 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700997 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
998 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
999
1000 def test_getmembers_with_buggy_dir(self):
1001 class M(type):
1002 def __dir__(cls):
1003 return ['__class__', '__name__', 'missing']
1004 class C(metaclass=M):
1005 pass
1006 attrs = [a[0] for a in inspect.getmembers(C)]
1007 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001008
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001009
Nick Coghlan2f92e542012-06-23 19:39:55 +10001010_global_ref = object()
1011class TestGetClosureVars(unittest.TestCase):
1012
1013 def test_name_resolution(self):
1014 # Basic test of the 4 different resolution mechanisms
1015 def f(nonlocal_ref):
1016 def g(local_ref):
1017 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1018 return g
1019 _arg = object()
1020 nonlocal_vars = {"nonlocal_ref": _arg}
1021 global_vars = {"_global_ref": _global_ref}
1022 builtin_vars = {"print": print}
1023 unbound_names = {"unbound_ref"}
1024 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1025 builtin_vars, unbound_names)
1026 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1027
1028 def test_generator_closure(self):
1029 def f(nonlocal_ref):
1030 def g(local_ref):
1031 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1032 yield
1033 return g
1034 _arg = object()
1035 nonlocal_vars = {"nonlocal_ref": _arg}
1036 global_vars = {"_global_ref": _global_ref}
1037 builtin_vars = {"print": print}
1038 unbound_names = {"unbound_ref"}
1039 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1040 builtin_vars, unbound_names)
1041 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1042
1043 def test_method_closure(self):
1044 class C:
1045 def f(self, 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(C().f(_arg)), expected)
1057
1058 def test_nonlocal_vars(self):
1059 # More complex tests of nonlocal resolution
1060 def _nonlocal_vars(f):
1061 return inspect.getclosurevars(f).nonlocals
1062
1063 def make_adder(x):
1064 def add(y):
1065 return x + y
1066 return add
1067
1068 def curry(func, arg1):
1069 return lambda arg2: func(arg1, arg2)
1070
1071 def less_than(a, b):
1072 return a < b
1073
1074 # The infamous Y combinator.
1075 def Y(le):
1076 def g(f):
1077 return le(lambda x: f(f)(x))
1078 Y.g_ref = g
1079 return g(g)
1080
1081 def check_y_combinator(func):
1082 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1083
1084 inc = make_adder(1)
1085 add_two = make_adder(2)
1086 greater_than_five = curry(less_than, 5)
1087
1088 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1089 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1090 self.assertEqual(_nonlocal_vars(greater_than_five),
1091 {'arg1': 5, 'func': less_than})
1092 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1093 {'x': 3})
1094 Y(check_y_combinator)
1095
1096 def test_getclosurevars_empty(self):
1097 def foo(): pass
1098 _empty = inspect.ClosureVars({}, {}, {}, set())
1099 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1100 self.assertEqual(inspect.getclosurevars(foo), _empty)
1101
1102 def test_getclosurevars_error(self):
1103 class T: pass
1104 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1105 self.assertRaises(TypeError, inspect.getclosurevars, list)
1106 self.assertRaises(TypeError, inspect.getclosurevars, {})
1107
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001108 def _private_globals(self):
1109 code = """def f(): print(path)"""
1110 ns = {}
1111 exec(code, ns)
1112 return ns["f"], ns
1113
1114 def test_builtins_fallback(self):
1115 f, ns = self._private_globals()
1116 ns.pop("__builtins__", None)
1117 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1118 self.assertEqual(inspect.getclosurevars(f), expected)
1119
1120 def test_builtins_as_dict(self):
1121 f, ns = self._private_globals()
1122 ns["__builtins__"] = {"path":1}
1123 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1124 self.assertEqual(inspect.getclosurevars(f), expected)
1125
1126 def test_builtins_as_module(self):
1127 f, ns = self._private_globals()
1128 ns["__builtins__"] = os
1129 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1130 self.assertEqual(inspect.getclosurevars(f), expected)
1131
Nick Coghlan2f92e542012-06-23 19:39:55 +10001132
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001133class TestGetcallargsFunctions(unittest.TestCase):
1134
1135 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1136 locs = dict(locs or {}, func=func)
1137 r1 = eval('func(%s)' % call_params_string, None, locs)
1138 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1139 locs)
1140 self.assertEqual(r1, r2)
1141
1142 def assertEqualException(self, func, call_param_string, locs=None):
1143 locs = dict(locs or {}, func=func)
1144 try:
1145 eval('func(%s)' % call_param_string, None, locs)
1146 except Exception as e:
1147 ex1 = e
1148 else:
1149 self.fail('Exception not raised')
1150 try:
1151 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1152 locs)
1153 except Exception as e:
1154 ex2 = e
1155 else:
1156 self.fail('Exception not raised')
1157 self.assertIs(type(ex1), type(ex2))
1158 self.assertEqual(str(ex1), str(ex2))
1159 del ex1, ex2
1160
1161 def makeCallable(self, signature):
1162 """Create a function that returns its locals()"""
1163 code = "lambda %s: locals()"
1164 return eval(code % signature)
1165
1166 def test_plain(self):
1167 f = self.makeCallable('a, b=1')
1168 self.assertEqualCallArgs(f, '2')
1169 self.assertEqualCallArgs(f, '2, 3')
1170 self.assertEqualCallArgs(f, 'a=2')
1171 self.assertEqualCallArgs(f, 'b=3, a=2')
1172 self.assertEqualCallArgs(f, '2, b=3')
1173 # expand *iterable / **mapping
1174 self.assertEqualCallArgs(f, '*(2,)')
1175 self.assertEqualCallArgs(f, '*[2]')
1176 self.assertEqualCallArgs(f, '*(2, 3)')
1177 self.assertEqualCallArgs(f, '*[2, 3]')
1178 self.assertEqualCallArgs(f, '**{"a":2}')
1179 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1180 self.assertEqualCallArgs(f, '2, **{"b":3}')
1181 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1182 # expand UserList / UserDict
1183 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1184 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1185 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1186 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1187 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1188
1189 def test_varargs(self):
1190 f = self.makeCallable('a, b=1, *c')
1191 self.assertEqualCallArgs(f, '2')
1192 self.assertEqualCallArgs(f, '2, 3')
1193 self.assertEqualCallArgs(f, '2, 3, 4')
1194 self.assertEqualCallArgs(f, '*(2,3,4)')
1195 self.assertEqualCallArgs(f, '2, *[3,4]')
1196 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1197
1198 def test_varkw(self):
1199 f = self.makeCallable('a, b=1, **c')
1200 self.assertEqualCallArgs(f, 'a=2')
1201 self.assertEqualCallArgs(f, '2, b=3, c=4')
1202 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1203 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1204 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1205 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1206 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1207 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1208 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1209
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001210 def test_varkw_only(self):
1211 # issue11256:
1212 f = self.makeCallable('**c')
1213 self.assertEqualCallArgs(f, '')
1214 self.assertEqualCallArgs(f, 'a=1')
1215 self.assertEqualCallArgs(f, 'a=1, b=2')
1216 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1217 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1218 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1219
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001220 def test_keyword_only(self):
1221 f = self.makeCallable('a=3, *, c, d=2')
1222 self.assertEqualCallArgs(f, 'c=3')
1223 self.assertEqualCallArgs(f, 'c=3, a=3')
1224 self.assertEqualCallArgs(f, 'a=2, c=4')
1225 self.assertEqualCallArgs(f, '4, c=4')
1226 self.assertEqualException(f, '')
1227 self.assertEqualException(f, '3')
1228 self.assertEqualException(f, 'a=3')
1229 self.assertEqualException(f, 'd=4')
1230
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001231 f = self.makeCallable('*, c, d=2')
1232 self.assertEqualCallArgs(f, 'c=3')
1233 self.assertEqualCallArgs(f, 'c=3, d=4')
1234 self.assertEqualCallArgs(f, 'd=4, c=3')
1235
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001236 def test_multiple_features(self):
1237 f = self.makeCallable('a, b=2, *f, **g')
1238 self.assertEqualCallArgs(f, '2, 3, 7')
1239 self.assertEqualCallArgs(f, '2, 3, x=8')
1240 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1241 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1242 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1243 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1244 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1245 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1246 '(4,[5,6])]), **collections.UserDict('
1247 'y=9, z=10)')
1248
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001249 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1250 self.assertEqualCallArgs(f, '2, 3, x=8')
1251 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1252 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1253 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1254 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1255 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1256 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1257 '(4,[5,6])]), q=0, **collections.UserDict('
1258 'y=9, z=10)')
1259
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001260 def test_errors(self):
1261 f0 = self.makeCallable('')
1262 f1 = self.makeCallable('a, b')
1263 f2 = self.makeCallable('a, b=1')
1264 # f0 takes no arguments
1265 self.assertEqualException(f0, '1')
1266 self.assertEqualException(f0, 'x=1')
1267 self.assertEqualException(f0, '1,x=1')
1268 # f1 takes exactly 2 arguments
1269 self.assertEqualException(f1, '')
1270 self.assertEqualException(f1, '1')
1271 self.assertEqualException(f1, 'a=2')
1272 self.assertEqualException(f1, 'b=3')
1273 # f2 takes at least 1 argument
1274 self.assertEqualException(f2, '')
1275 self.assertEqualException(f2, 'b=3')
1276 for f in f1, f2:
1277 # f1/f2 takes exactly/at most 2 arguments
1278 self.assertEqualException(f, '2, 3, 4')
1279 self.assertEqualException(f, '1, 2, 3, a=1')
1280 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001281 # XXX: success of this one depends on dict order
1282 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001283 # f got an unexpected keyword argument
1284 self.assertEqualException(f, 'c=2')
1285 self.assertEqualException(f, '2, c=3')
1286 self.assertEqualException(f, '2, 3, c=4')
1287 self.assertEqualException(f, '2, c=4, b=3')
1288 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1289 # f got multiple values for keyword argument
1290 self.assertEqualException(f, '1, a=2')
1291 self.assertEqualException(f, '1, **{"a":2}')
1292 self.assertEqualException(f, '1, 2, b=3')
1293 # XXX: Python inconsistency
1294 # - for functions and bound methods: unexpected keyword 'c'
1295 # - for unbound methods: multiple values for keyword 'a'
1296 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001297 # issue11256:
1298 f3 = self.makeCallable('**c')
1299 self.assertEqualException(f3, '1, 2')
1300 self.assertEqualException(f3, '1, 2, a=1, b=2')
1301 f4 = self.makeCallable('*, a, b=0')
1302 self.assertEqualException(f3, '1, 2')
1303 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001304
Yury Selivanov875df202014-03-27 18:23:03 -04001305 # issue #20816: getcallargs() fails to iterate over non-existent
1306 # kwonlydefaults and raises a wrong TypeError
1307 def f5(*, a): pass
1308 with self.assertRaisesRegex(TypeError,
1309 'missing 1 required keyword-only'):
1310 inspect.getcallargs(f5)
1311
1312
Yury Selivanovdccfa132014-03-27 18:42:52 -04001313 # issue20817:
1314 def f6(a, b, c):
1315 pass
1316 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1317 inspect.getcallargs(f6)
1318
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001319class TestGetcallargsMethods(TestGetcallargsFunctions):
1320
1321 def setUp(self):
1322 class Foo(object):
1323 pass
1324 self.cls = Foo
1325 self.inst = Foo()
1326
1327 def makeCallable(self, signature):
1328 assert 'self' not in signature
1329 mk = super(TestGetcallargsMethods, self).makeCallable
1330 self.cls.method = mk('self, ' + signature)
1331 return self.inst.method
1332
1333class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1334
1335 def makeCallable(self, signature):
1336 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1337 return self.cls.method
1338
1339 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1340 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1341 *self._getAssertEqualParams(func, call_params_string, locs))
1342
1343 def assertEqualException(self, func, call_params_string, locs=None):
1344 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1345 *self._getAssertEqualParams(func, call_params_string, locs))
1346
1347 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1348 assert 'inst' not in call_params_string
1349 locs = dict(locs or {}, inst=self.inst)
1350 return (func, 'inst,' + call_params_string, locs)
1351
Michael Foord95fc51d2010-11-20 15:07:30 +00001352
1353class TestGetattrStatic(unittest.TestCase):
1354
1355 def test_basic(self):
1356 class Thing(object):
1357 x = object()
1358
1359 thing = Thing()
1360 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1361 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1362 with self.assertRaises(AttributeError):
1363 inspect.getattr_static(thing, 'y')
1364
1365 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1366
1367 def test_inherited(self):
1368 class Thing(object):
1369 x = object()
1370 class OtherThing(Thing):
1371 pass
1372
1373 something = OtherThing()
1374 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1375
1376 def test_instance_attr(self):
1377 class Thing(object):
1378 x = 2
1379 def __init__(self, x):
1380 self.x = x
1381 thing = Thing(3)
1382 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1383 del thing.x
1384 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1385
1386 def test_property(self):
1387 class Thing(object):
1388 @property
1389 def x(self):
1390 raise AttributeError("I'm pretending not to exist")
1391 thing = Thing()
1392 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1393
Ezio Melotti75cbd732011-04-28 00:59:29 +03001394 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001395 class descriptor(object):
1396 def __get__(*_):
1397 raise AttributeError("I'm pretending not to exist")
1398 desc = descriptor()
1399 class Thing(object):
1400 x = desc
1401 thing = Thing()
1402 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1403
1404 def test_classAttribute(self):
1405 class Thing(object):
1406 x = object()
1407
1408 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1409
Ethan Furmane03ea372013-09-25 07:14:41 -07001410 def test_classVirtualAttribute(self):
1411 class Thing(object):
1412 @types.DynamicClassAttribute
1413 def x(self):
1414 return self._x
1415 _x = object()
1416
1417 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1418
Michael Foord95fc51d2010-11-20 15:07:30 +00001419 def test_inherited_classattribute(self):
1420 class Thing(object):
1421 x = object()
1422 class OtherThing(Thing):
1423 pass
1424
1425 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1426
1427 def test_slots(self):
1428 class Thing(object):
1429 y = 'bar'
1430 __slots__ = ['x']
1431 def __init__(self):
1432 self.x = 'foo'
1433 thing = Thing()
1434 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1435 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1436
1437 del thing.x
1438 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1439
1440 def test_metaclass(self):
1441 class meta(type):
1442 attr = 'foo'
1443 class Thing(object, metaclass=meta):
1444 pass
1445 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1446
1447 class sub(meta):
1448 pass
1449 class OtherThing(object, metaclass=sub):
1450 x = 3
1451 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1452
1453 class OtherOtherThing(OtherThing):
1454 pass
1455 # this test is odd, but it was added as it exposed a bug
1456 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1457
1458 def test_no_dict_no_slots(self):
1459 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1460 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1461
1462 def test_no_dict_no_slots_instance_member(self):
1463 # returns descriptor
1464 with open(__file__) as handle:
1465 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1466
1467 def test_inherited_slots(self):
1468 # returns descriptor
1469 class Thing(object):
1470 __slots__ = ['x']
1471 def __init__(self):
1472 self.x = 'foo'
1473
1474 class OtherThing(Thing):
1475 pass
1476 # it would be nice if this worked...
1477 # we get the descriptor instead of the instance attribute
1478 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1479
1480 def test_descriptor(self):
1481 class descriptor(object):
1482 def __get__(self, instance, owner):
1483 return 3
1484 class Foo(object):
1485 d = descriptor()
1486
1487 foo = Foo()
1488
1489 # for a non data descriptor we return the instance attribute
1490 foo.__dict__['d'] = 1
1491 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1492
1493 # if the descriptor is a data-desciptor we should return the
1494 # descriptor
1495 descriptor.__set__ = lambda s, i, v: None
1496 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1497
1498
1499 def test_metaclass_with_descriptor(self):
1500 class descriptor(object):
1501 def __get__(self, instance, owner):
1502 return 3
1503 class meta(type):
1504 d = descriptor()
1505 class Thing(object, metaclass=meta):
1506 pass
1507 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1508
1509
Michael Foordcc7ebb82010-11-20 16:20:16 +00001510 def test_class_as_property(self):
1511 class Base(object):
1512 foo = 3
1513
1514 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001515 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001516 @property
1517 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001518 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001519 return object
1520
Michael Foord35184ed2010-11-20 16:58:30 +00001521 instance = Something()
1522 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1523 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001524 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1525
Michael Foorde5162652010-11-20 16:40:44 +00001526 def test_mro_as_property(self):
1527 class Meta(type):
1528 @property
1529 def __mro__(self):
1530 return (object,)
1531
1532 class Base(object):
1533 foo = 3
1534
1535 class Something(Base, metaclass=Meta):
1536 pass
1537
1538 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1539 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1540
Michael Foorddcebe0f2011-03-15 19:20:44 -04001541 def test_dict_as_property(self):
1542 test = self
1543 test.called = False
1544
1545 class Foo(dict):
1546 a = 3
1547 @property
1548 def __dict__(self):
1549 test.called = True
1550 return {}
1551
1552 foo = Foo()
1553 foo.a = 4
1554 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1555 self.assertFalse(test.called)
1556
1557 def test_custom_object_dict(self):
1558 test = self
1559 test.called = False
1560
1561 class Custom(dict):
1562 def get(self, key, default=None):
1563 test.called = True
1564 super().get(key, default)
1565
1566 class Foo(object):
1567 a = 3
1568 foo = Foo()
1569 foo.__dict__ = Custom()
1570 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1571 self.assertFalse(test.called)
1572
1573 def test_metaclass_dict_as_property(self):
1574 class Meta(type):
1575 @property
1576 def __dict__(self):
1577 self.executed = True
1578
1579 class Thing(metaclass=Meta):
1580 executed = False
1581
1582 def __init__(self):
1583 self.spam = 42
1584
1585 instance = Thing()
1586 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1587 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001588
Michael Foorda51623b2011-12-18 22:01:40 +00001589 def test_module(self):
1590 sentinel = object()
1591 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1592 sentinel)
1593
Michael Foord3ba95f82011-12-22 01:13:37 +00001594 def test_metaclass_with_metaclass_with_dict_as_property(self):
1595 class MetaMeta(type):
1596 @property
1597 def __dict__(self):
1598 self.executed = True
1599 return dict(spam=42)
1600
1601 class Meta(type, metaclass=MetaMeta):
1602 executed = False
1603
1604 class Thing(metaclass=Meta):
1605 pass
1606
1607 with self.assertRaises(AttributeError):
1608 inspect.getattr_static(Thing, "spam")
1609 self.assertFalse(Thing.executed)
1610
Nick Coghlane0f04652010-11-21 03:44:04 +00001611class TestGetGeneratorState(unittest.TestCase):
1612
1613 def setUp(self):
1614 def number_generator():
1615 for number in range(5):
1616 yield number
1617 self.generator = number_generator()
1618
1619 def _generatorstate(self):
1620 return inspect.getgeneratorstate(self.generator)
1621
1622 def test_created(self):
1623 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1624
1625 def test_suspended(self):
1626 next(self.generator)
1627 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1628
1629 def test_closed_after_exhaustion(self):
1630 for i in self.generator:
1631 pass
1632 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1633
1634 def test_closed_after_immediate_exception(self):
1635 with self.assertRaises(RuntimeError):
1636 self.generator.throw(RuntimeError)
1637 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1638
1639 def test_running(self):
1640 # As mentioned on issue #10220, checking for the RUNNING state only
1641 # makes sense inside the generator itself.
1642 # The following generator checks for this by using the closure's
1643 # reference to self and the generator state checking helper method
1644 def running_check_generator():
1645 for number in range(5):
1646 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1647 yield number
1648 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1649 self.generator = running_check_generator()
1650 # Running up to the first yield
1651 next(self.generator)
1652 # Running after the first yield
1653 next(self.generator)
1654
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001655 def test_easy_debugging(self):
1656 # repr() and str() of a generator state should contain the state name
1657 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1658 for name in names:
1659 state = getattr(inspect, name)
1660 self.assertIn(name, repr(state))
1661 self.assertIn(name, str(state))
1662
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001663 def test_getgeneratorlocals(self):
1664 def each(lst, a=None):
1665 b=(1, 2, 3)
1666 for v in lst:
1667 if v == 3:
1668 c = 12
1669 yield v
1670
1671 numbers = each([1, 2, 3])
1672 self.assertEqual(inspect.getgeneratorlocals(numbers),
1673 {'a': None, 'lst': [1, 2, 3]})
1674 next(numbers)
1675 self.assertEqual(inspect.getgeneratorlocals(numbers),
1676 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1677 'b': (1, 2, 3)})
1678 next(numbers)
1679 self.assertEqual(inspect.getgeneratorlocals(numbers),
1680 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1681 'b': (1, 2, 3)})
1682 next(numbers)
1683 self.assertEqual(inspect.getgeneratorlocals(numbers),
1684 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1685 'b': (1, 2, 3), 'c': 12})
1686 try:
1687 next(numbers)
1688 except StopIteration:
1689 pass
1690 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1691
1692 def test_getgeneratorlocals_empty(self):
1693 def yield_one():
1694 yield 1
1695 one = yield_one()
1696 self.assertEqual(inspect.getgeneratorlocals(one), {})
1697 try:
1698 next(one)
1699 except StopIteration:
1700 pass
1701 self.assertEqual(inspect.getgeneratorlocals(one), {})
1702
1703 def test_getgeneratorlocals_error(self):
1704 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1705 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1706 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1707 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1708
Nick Coghlane0f04652010-11-21 03:44:04 +00001709
Yury Selivanov5376ba92015-06-22 12:19:30 -04001710class TestGetCoroutineState(unittest.TestCase):
1711
1712 def setUp(self):
1713 @types.coroutine
1714 def number_coroutine():
1715 for number in range(5):
1716 yield number
1717 async def coroutine():
1718 await number_coroutine()
1719 self.coroutine = coroutine()
1720
1721 def tearDown(self):
1722 self.coroutine.close()
1723
1724 def _coroutinestate(self):
1725 return inspect.getcoroutinestate(self.coroutine)
1726
1727 def test_created(self):
1728 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1729
1730 def test_suspended(self):
1731 self.coroutine.send(None)
1732 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1733
1734 def test_closed_after_exhaustion(self):
1735 while True:
1736 try:
1737 self.coroutine.send(None)
1738 except StopIteration:
1739 break
1740
1741 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1742
1743 def test_closed_after_immediate_exception(self):
1744 with self.assertRaises(RuntimeError):
1745 self.coroutine.throw(RuntimeError)
1746 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1747
1748 def test_easy_debugging(self):
1749 # repr() and str() of a coroutine state should contain the state name
1750 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1751 for name in names:
1752 state = getattr(inspect, name)
1753 self.assertIn(name, repr(state))
1754 self.assertIn(name, str(state))
1755
1756 def test_getcoroutinelocals(self):
1757 @types.coroutine
1758 def gencoro():
1759 yield
1760
1761 gencoro = gencoro()
1762 async def func(a=None):
1763 b = 'spam'
1764 await gencoro
1765
1766 coro = func()
1767 self.assertEqual(inspect.getcoroutinelocals(coro),
1768 {'a': None, 'gencoro': gencoro})
1769 coro.send(None)
1770 self.assertEqual(inspect.getcoroutinelocals(coro),
1771 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
1772
1773
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001774class MySignature(inspect.Signature):
1775 # Top-level to make it picklable;
1776 # used in test_signature_object_pickle
1777 pass
1778
1779class MyParameter(inspect.Parameter):
1780 # Top-level to make it picklable;
1781 # used in test_signature_object_pickle
1782 pass
1783
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001784
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001785
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001786class TestSignatureObject(unittest.TestCase):
1787 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04001788 def signature(func, **kw):
1789 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001790 return (tuple((param.name,
1791 (... if param.default is param.empty else param.default),
1792 (... if param.annotation is param.empty
1793 else param.annotation),
1794 str(param.kind).lower())
1795 for param in sig.parameters.values()),
1796 (... if sig.return_annotation is sig.empty
1797 else sig.return_annotation))
1798
1799 def test_signature_object(self):
1800 S = inspect.Signature
1801 P = inspect.Parameter
1802
1803 self.assertEqual(str(S()), '()')
1804
Yury Selivanov07a9e452014-01-29 10:58:16 -05001805 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001806 pass
1807 sig = inspect.signature(test)
1808 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001809 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001810 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001811 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001812 args = sig.parameters['args']
1813 ko = sig.parameters['ko']
1814 kwargs = sig.parameters['kwargs']
1815
1816 S((po, pk, args, ko, kwargs))
1817
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001818 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001819 S((pk, po, args, ko, kwargs))
1820
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001821 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001822 S((po, args, pk, ko, kwargs))
1823
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001824 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001825 S((args, po, pk, ko, kwargs))
1826
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001827 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001828 S((po, pk, args, kwargs, ko))
1829
1830 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001831 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001832 S((po, pk, args, kwargs2, ko))
1833
Yury Selivanov07a9e452014-01-29 10:58:16 -05001834 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1835 S((pod, po))
1836
1837 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1838 S((po, pkd, pk))
1839
1840 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1841 S((pkd, pk))
1842
Yury Selivanov374375d2014-03-27 12:41:53 -04001843 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04001844 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04001845
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001846 def test_signature_object_pickle(self):
1847 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1848 foo_partial = functools.partial(foo, a=1)
1849
1850 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001851
1852 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1853 with self.subTest(pickle_ver=ver, subclass=False):
1854 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1855 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001856
1857 # Test that basic sub-classing works
1858 sig = inspect.signature(foo)
1859 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1860 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1861 mysig = MySignature().replace(parameters=myparams.values(),
1862 return_annotation=sig.return_annotation)
1863 self.assertTrue(isinstance(mysig, MySignature))
1864 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1865
1866 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1867 with self.subTest(pickle_ver=ver, subclass=True):
1868 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1869 self.assertEqual(mysig, sig_pickled)
1870 self.assertTrue(isinstance(sig_pickled, MySignature))
1871 self.assertTrue(isinstance(sig_pickled.parameters['z'],
1872 MyParameter))
1873
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001874 def test_signature_immutability(self):
1875 def test(a):
1876 pass
1877 sig = inspect.signature(test)
1878
1879 with self.assertRaises(AttributeError):
1880 sig.foo = 'bar'
1881
1882 with self.assertRaises(TypeError):
1883 sig.parameters['a'] = None
1884
1885 def test_signature_on_noarg(self):
1886 def test():
1887 pass
1888 self.assertEqual(self.signature(test), ((), ...))
1889
1890 def test_signature_on_wargs(self):
1891 def test(a, b:'foo') -> 123:
1892 pass
1893 self.assertEqual(self.signature(test),
1894 ((('a', ..., ..., "positional_or_keyword"),
1895 ('b', ..., 'foo', "positional_or_keyword")),
1896 123))
1897
1898 def test_signature_on_wkwonly(self):
1899 def test(*, a:float, b:str) -> int:
1900 pass
1901 self.assertEqual(self.signature(test),
1902 ((('a', ..., float, "keyword_only"),
1903 ('b', ..., str, "keyword_only")),
1904 int))
1905
1906 def test_signature_on_complex_args(self):
1907 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1908 pass
1909 self.assertEqual(self.signature(test),
1910 ((('a', ..., ..., "positional_or_keyword"),
1911 ('b', 10, 'foo', "positional_or_keyword"),
1912 ('args', ..., 'bar', "var_positional"),
1913 ('spam', ..., 'baz', "keyword_only"),
1914 ('ham', 123, ..., "keyword_only"),
1915 ('kwargs', ..., int, "var_keyword")),
1916 ...))
1917
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001918 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001919 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1920 "Signature information for builtins requires docstrings")
1921 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001922 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001923
Larry Hastings5c661892014-01-24 06:17:25 -08001924 def test_unbound_method(o):
1925 """Use this to test unbound methods (things that should have a self)"""
1926 signature = inspect.signature(o)
1927 self.assertTrue(isinstance(signature, inspect.Signature))
1928 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1929 return signature
1930
1931 def test_callable(o):
1932 """Use this to test bound methods or normal callables (things that don't expect self)"""
1933 signature = inspect.signature(o)
1934 self.assertTrue(isinstance(signature, inspect.Signature))
1935 if signature.parameters:
1936 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1937 return signature
1938
1939 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001940 def p(name): return signature.parameters[name].default
1941 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001942 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001943 self.assertEqual(p('d'), 3.14)
1944 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001945 self.assertEqual(p('n'), None)
1946 self.assertEqual(p('t'), True)
1947 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001948 self.assertEqual(p('local'), 3)
1949 self.assertEqual(p('sys'), sys.maxsize)
1950 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001951
Larry Hastings5c661892014-01-24 06:17:25 -08001952 test_callable(object)
1953
1954 # normal method
1955 # (PyMethodDescr_Type, "method_descriptor")
1956 test_unbound_method(_pickle.Pickler.dump)
1957 d = _pickle.Pickler(io.StringIO())
1958 test_callable(d.dump)
1959
1960 # static method
1961 test_callable(str.maketrans)
1962 test_callable('abc'.maketrans)
1963
1964 # class method
1965 test_callable(dict.fromkeys)
1966 test_callable({}.fromkeys)
1967
1968 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1969 test_unbound_method(type.__call__)
1970 test_unbound_method(int.__add__)
1971 test_callable((3).__add__)
1972
1973 # _PyMethodWrapper_Type
1974 # support for 'method-wrapper'
1975 test_callable(min.__call__)
1976
Larry Hastings2623c8c2014-02-08 22:15:29 -08001977 # This doesn't work now.
1978 # (We don't have a valid signature for "type" in 3.4)
1979 with self.assertRaisesRegex(ValueError, "no signature found"):
1980 class ThisWorksNow:
1981 __call__ = type
1982 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001983
Yury Selivanov056e2652014-03-02 12:25:27 -05001984 # Regression test for issue #20786
1985 test_unbound_method(dict.__delitem__)
1986 test_unbound_method(property.__delete__)
1987
Zachary Ware8ef887c2015-04-13 18:22:35 -05001988 # Regression test for issue #20586
1989 test_callable(_testcapi.docstring_with_signature_but_no_doc)
1990
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001991 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001992 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1993 "Signature information for builtins requires docstrings")
1994 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001995 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001996 func = _testcapi.docstring_with_signature_with_defaults
1997
1998 def decorator(func):
1999 @functools.wraps(func)
2000 def wrapper(*args, **kwargs) -> int:
2001 return func(*args, **kwargs)
2002 return wrapper
2003
2004 decorated_func = decorator(func)
2005
2006 self.assertEqual(inspect.signature(func),
2007 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002008
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002009 def wrapper_like(*args, **kwargs) -> int: pass
2010 self.assertEqual(inspect.signature(decorated_func,
2011 follow_wrapped=False),
2012 inspect.signature(wrapper_like))
2013
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002014 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002015 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002016 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002017 with self.assertRaisesRegex(ValueError,
2018 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002019 inspect.signature(_testcapi.docstring_no_signature)
2020
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002021 with self.assertRaisesRegex(ValueError,
2022 'no signature found for builtin'):
2023 inspect.signature(str)
2024
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002025 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002026 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002027 inspect.signature(42)
2028
Yury Selivanov63da7c72014-01-31 14:48:37 -05002029 def test_signature_from_functionlike_object(self):
2030 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2031 pass
2032
2033 class funclike:
2034 # Has to be callable, and have correct
2035 # __code__, __annotations__, __defaults__, __name__,
2036 # and __kwdefaults__ attributes
2037
2038 def __init__(self, func):
2039 self.__name__ = func.__name__
2040 self.__code__ = func.__code__
2041 self.__annotations__ = func.__annotations__
2042 self.__defaults__ = func.__defaults__
2043 self.__kwdefaults__ = func.__kwdefaults__
2044 self.func = func
2045
2046 def __call__(self, *args, **kwargs):
2047 return self.func(*args, **kwargs)
2048
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002049 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002050
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002051 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002052 self.assertEqual(sig_funclike, sig_func)
2053
2054 sig_funclike = inspect.signature(funclike(func))
2055 self.assertEqual(sig_funclike, sig_func)
2056
2057 # If object is not a duck type of function, then
2058 # signature will try to get a signature for its '__call__'
2059 # method
2060 fl = funclike(func)
2061 del fl.__defaults__
2062 self.assertEqual(self.signature(fl),
2063 ((('args', ..., ..., "var_positional"),
2064 ('kwargs', ..., ..., "var_keyword")),
2065 ...))
2066
Yury Selivanova773de02014-02-21 18:30:53 -05002067 # Test with cython-like builtins:
2068 _orig_isdesc = inspect.ismethoddescriptor
2069 def _isdesc(obj):
2070 if hasattr(obj, '_builtinmock'):
2071 return True
2072 return _orig_isdesc(obj)
2073
2074 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2075 builtin_func = funclike(func)
2076 # Make sure that our mock setup is working
2077 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2078 builtin_func._builtinmock = True
2079 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2080 self.assertEqual(inspect.signature(builtin_func), sig_func)
2081
Yury Selivanov63da7c72014-01-31 14:48:37 -05002082 def test_signature_functionlike_class(self):
2083 # We only want to duck type function-like objects,
2084 # not classes.
2085
2086 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2087 pass
2088
2089 class funclike:
2090 def __init__(self, marker):
2091 pass
2092
2093 __name__ = func.__name__
2094 __code__ = func.__code__
2095 __annotations__ = func.__annotations__
2096 __defaults__ = func.__defaults__
2097 __kwdefaults__ = func.__kwdefaults__
2098
Yury Selivanov63da7c72014-01-31 14:48:37 -05002099 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2100
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002101 def test_signature_on_method(self):
2102 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002103 def __init__(*args):
2104 pass
2105 def m1(self, arg1, arg2=1) -> int:
2106 pass
2107 def m2(*args):
2108 pass
2109 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002110 pass
2111
Yury Selivanov62560fb2014-01-28 12:26:24 -05002112 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002113 ((('arg1', ..., ..., "positional_or_keyword"),
2114 ('arg2', 1, ..., "positional_or_keyword")),
2115 int))
2116
Yury Selivanov62560fb2014-01-28 12:26:24 -05002117 self.assertEqual(self.signature(Test().m2),
2118 ((('args', ..., ..., "var_positional"),),
2119 ...))
2120
2121 self.assertEqual(self.signature(Test),
2122 ((('args', ..., ..., "var_positional"),),
2123 ...))
2124
2125 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2126 self.signature(Test())
2127
Yury Selivanov46c759d2015-05-27 21:56:53 -04002128 def test_signature_wrapped_bound_method(self):
2129 # Issue 24298
2130 class Test:
2131 def m1(self, arg1, arg2=1) -> int:
2132 pass
2133 @functools.wraps(Test().m1)
2134 def m1d(*args, **kwargs):
2135 pass
2136 self.assertEqual(self.signature(m1d),
2137 ((('arg1', ..., ..., "positional_or_keyword"),
2138 ('arg2', 1, ..., "positional_or_keyword")),
2139 int))
2140
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002141 def test_signature_on_classmethod(self):
2142 class Test:
2143 @classmethod
2144 def foo(cls, arg1, *, arg2=1):
2145 pass
2146
2147 meth = Test().foo
2148 self.assertEqual(self.signature(meth),
2149 ((('arg1', ..., ..., "positional_or_keyword"),
2150 ('arg2', 1, ..., "keyword_only")),
2151 ...))
2152
2153 meth = Test.foo
2154 self.assertEqual(self.signature(meth),
2155 ((('arg1', ..., ..., "positional_or_keyword"),
2156 ('arg2', 1, ..., "keyword_only")),
2157 ...))
2158
2159 def test_signature_on_staticmethod(self):
2160 class Test:
2161 @staticmethod
2162 def foo(cls, *, arg):
2163 pass
2164
2165 meth = Test().foo
2166 self.assertEqual(self.signature(meth),
2167 ((('cls', ..., ..., "positional_or_keyword"),
2168 ('arg', ..., ..., "keyword_only")),
2169 ...))
2170
2171 meth = Test.foo
2172 self.assertEqual(self.signature(meth),
2173 ((('cls', ..., ..., "positional_or_keyword"),
2174 ('arg', ..., ..., "keyword_only")),
2175 ...))
2176
2177 def test_signature_on_partial(self):
2178 from functools import partial
2179
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002180 Parameter = inspect.Parameter
2181
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002182 def test():
2183 pass
2184
2185 self.assertEqual(self.signature(partial(test)), ((), ...))
2186
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002187 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002188 inspect.signature(partial(test, 1))
2189
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002190 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002191 inspect.signature(partial(test, a=1))
2192
2193 def test(a, b, *, c, d):
2194 pass
2195
2196 self.assertEqual(self.signature(partial(test)),
2197 ((('a', ..., ..., "positional_or_keyword"),
2198 ('b', ..., ..., "positional_or_keyword"),
2199 ('c', ..., ..., "keyword_only"),
2200 ('d', ..., ..., "keyword_only")),
2201 ...))
2202
2203 self.assertEqual(self.signature(partial(test, 1)),
2204 ((('b', ..., ..., "positional_or_keyword"),
2205 ('c', ..., ..., "keyword_only"),
2206 ('d', ..., ..., "keyword_only")),
2207 ...))
2208
2209 self.assertEqual(self.signature(partial(test, 1, c=2)),
2210 ((('b', ..., ..., "positional_or_keyword"),
2211 ('c', 2, ..., "keyword_only"),
2212 ('d', ..., ..., "keyword_only")),
2213 ...))
2214
2215 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2216 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002217 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002218 ('c', 2, ..., "keyword_only"),
2219 ('d', ..., ..., "keyword_only")),
2220 ...))
2221
2222 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002223 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002224 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002225 ('d', ..., ..., "keyword_only")),
2226 ...))
2227
2228 self.assertEqual(self.signature(partial(test, a=1)),
2229 ((('a', 1, ..., "keyword_only"),
2230 ('b', ..., ..., "keyword_only"),
2231 ('c', ..., ..., "keyword_only"),
2232 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002233 ...))
2234
2235 def test(a, *args, b, **kwargs):
2236 pass
2237
2238 self.assertEqual(self.signature(partial(test, 1)),
2239 ((('args', ..., ..., "var_positional"),
2240 ('b', ..., ..., "keyword_only"),
2241 ('kwargs', ..., ..., "var_keyword")),
2242 ...))
2243
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002244 self.assertEqual(self.signature(partial(test, a=1)),
2245 ((('a', 1, ..., "keyword_only"),
2246 ('b', ..., ..., "keyword_only"),
2247 ('kwargs', ..., ..., "var_keyword")),
2248 ...))
2249
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002250 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2251 ((('args', ..., ..., "var_positional"),
2252 ('b', ..., ..., "keyword_only"),
2253 ('kwargs', ..., ..., "var_keyword")),
2254 ...))
2255
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002256 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2257 ((('args', ..., ..., "var_positional"),
2258 ('b', ..., ..., "keyword_only"),
2259 ('kwargs', ..., ..., "var_keyword")),
2260 ...))
2261
2262 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2263 ((('args', ..., ..., "var_positional"),
2264 ('b', 0, ..., "keyword_only"),
2265 ('kwargs', ..., ..., "var_keyword")),
2266 ...))
2267
2268 self.assertEqual(self.signature(partial(test, b=0)),
2269 ((('a', ..., ..., "positional_or_keyword"),
2270 ('args', ..., ..., "var_positional"),
2271 ('b', 0, ..., "keyword_only"),
2272 ('kwargs', ..., ..., "var_keyword")),
2273 ...))
2274
2275 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2276 ((('a', ..., ..., "positional_or_keyword"),
2277 ('args', ..., ..., "var_positional"),
2278 ('b', 0, ..., "keyword_only"),
2279 ('kwargs', ..., ..., "var_keyword")),
2280 ...))
2281
2282 def test(a, b, c:int) -> 42:
2283 pass
2284
2285 sig = test.__signature__ = inspect.signature(test)
2286
2287 self.assertEqual(self.signature(partial(partial(test, 1))),
2288 ((('b', ..., ..., "positional_or_keyword"),
2289 ('c', ..., int, "positional_or_keyword")),
2290 42))
2291
2292 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2293 ((('c', ..., int, "positional_or_keyword"),),
2294 42))
2295
2296 psig = inspect.signature(partial(partial(test, 1), 2))
2297
2298 def foo(a):
2299 return a
2300 _foo = partial(partial(foo, a=10), a=20)
2301 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002302 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002303 ...))
2304 # check that we don't have any side-effects in signature(),
2305 # and the partial object is still functioning
2306 self.assertEqual(_foo(), 20)
2307
2308 def foo(a, b, c):
2309 return a, b, c
2310 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002311
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002312 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002313 ((('b', 30, ..., "keyword_only"),
2314 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002315 ...))
2316 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002317
2318 def foo(a, b, c, *, d):
2319 return a, b, c, d
2320 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2321 self.assertEqual(self.signature(_foo),
2322 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002323 ('b', 10, ..., "keyword_only"),
2324 ('c', 20, ..., "keyword_only"),
2325 ('d', 30, ..., "keyword_only"),
2326 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002327 ...))
2328 ba = inspect.signature(_foo).bind(a=200, b=11)
2329 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2330
2331 def foo(a=1, b=2, c=3):
2332 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002333 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2334
2335 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002336 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002337
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002338 ba = inspect.signature(_foo).bind(11, 12)
2339 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002340
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002341 ba = inspect.signature(_foo).bind(11, b=12)
2342 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002343
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002344 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002345 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2346
2347 _foo = partial(_foo, b=10, c=20)
2348 ba = inspect.signature(_foo).bind(12)
2349 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2350
2351
2352 def foo(a, b, c, d, **kwargs):
2353 pass
2354 sig = inspect.signature(foo)
2355 params = sig.parameters.copy()
2356 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2357 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2358 foo.__signature__ = inspect.Signature(params.values())
2359 sig = inspect.signature(foo)
2360 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2361
2362 self.assertEqual(self.signature(partial(foo, 1)),
2363 ((('b', ..., ..., 'positional_only'),
2364 ('c', ..., ..., 'positional_or_keyword'),
2365 ('d', ..., ..., 'positional_or_keyword'),
2366 ('kwargs', ..., ..., 'var_keyword')),
2367 ...))
2368
2369 self.assertEqual(self.signature(partial(foo, 1, 2)),
2370 ((('c', ..., ..., 'positional_or_keyword'),
2371 ('d', ..., ..., 'positional_or_keyword'),
2372 ('kwargs', ..., ..., 'var_keyword')),
2373 ...))
2374
2375 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2376 ((('d', ..., ..., 'positional_or_keyword'),
2377 ('kwargs', ..., ..., 'var_keyword')),
2378 ...))
2379
2380 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2381 ((('c', 3, ..., 'keyword_only'),
2382 ('d', ..., ..., 'keyword_only'),
2383 ('kwargs', ..., ..., 'var_keyword')),
2384 ...))
2385
2386 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2387 ((('b', ..., ..., 'positional_only'),
2388 ('c', 3, ..., 'keyword_only'),
2389 ('d', ..., ..., 'keyword_only'),
2390 ('kwargs', ..., ..., 'var_keyword')),
2391 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002392
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002393 def test_signature_on_partialmethod(self):
2394 from functools import partialmethod
2395
2396 class Spam:
2397 def test():
2398 pass
2399 ham = partialmethod(test)
2400
2401 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2402 inspect.signature(Spam.ham)
2403
2404 class Spam:
2405 def test(it, a, *, c) -> 'spam':
2406 pass
2407 ham = partialmethod(test, c=1)
2408
2409 self.assertEqual(self.signature(Spam.ham),
2410 ((('it', ..., ..., 'positional_or_keyword'),
2411 ('a', ..., ..., 'positional_or_keyword'),
2412 ('c', 1, ..., 'keyword_only')),
2413 'spam'))
2414
2415 self.assertEqual(self.signature(Spam().ham),
2416 ((('a', ..., ..., 'positional_or_keyword'),
2417 ('c', 1, ..., 'keyword_only')),
2418 'spam'))
2419
Yury Selivanov0486f812014-01-29 12:18:59 -05002420 def test_signature_on_fake_partialmethod(self):
2421 def foo(a): pass
2422 foo._partialmethod = 'spam'
2423 self.assertEqual(str(inspect.signature(foo)), '(a)')
2424
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002425 def test_signature_on_decorated(self):
2426 import functools
2427
2428 def decorator(func):
2429 @functools.wraps(func)
2430 def wrapper(*args, **kwargs) -> int:
2431 return func(*args, **kwargs)
2432 return wrapper
2433
2434 class Foo:
2435 @decorator
2436 def bar(self, a, b):
2437 pass
2438
2439 self.assertEqual(self.signature(Foo.bar),
2440 ((('self', ..., ..., "positional_or_keyword"),
2441 ('a', ..., ..., "positional_or_keyword"),
2442 ('b', ..., ..., "positional_or_keyword")),
2443 ...))
2444
2445 self.assertEqual(self.signature(Foo().bar),
2446 ((('a', ..., ..., "positional_or_keyword"),
2447 ('b', ..., ..., "positional_or_keyword")),
2448 ...))
2449
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002450 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2451 ((('args', ..., ..., "var_positional"),
2452 ('kwargs', ..., ..., "var_keyword")),
2453 ...)) # functools.wraps will copy __annotations__
2454 # from "func" to "wrapper", hence no
2455 # return_annotation
2456
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002457 # Test that we handle method wrappers correctly
2458 def decorator(func):
2459 @functools.wraps(func)
2460 def wrapper(*args, **kwargs) -> int:
2461 return func(42, *args, **kwargs)
2462 sig = inspect.signature(func)
2463 new_params = tuple(sig.parameters.values())[1:]
2464 wrapper.__signature__ = sig.replace(parameters=new_params)
2465 return wrapper
2466
2467 class Foo:
2468 @decorator
2469 def __call__(self, a, b):
2470 pass
2471
2472 self.assertEqual(self.signature(Foo.__call__),
2473 ((('a', ..., ..., "positional_or_keyword"),
2474 ('b', ..., ..., "positional_or_keyword")),
2475 ...))
2476
2477 self.assertEqual(self.signature(Foo().__call__),
2478 ((('b', ..., ..., "positional_or_keyword"),),
2479 ...))
2480
Nick Coghlane8c45d62013-07-28 20:00:01 +10002481 # Test we handle __signature__ partway down the wrapper stack
2482 def wrapped_foo_call():
2483 pass
2484 wrapped_foo_call.__wrapped__ = Foo.__call__
2485
2486 self.assertEqual(self.signature(wrapped_foo_call),
2487 ((('a', ..., ..., "positional_or_keyword"),
2488 ('b', ..., ..., "positional_or_keyword")),
2489 ...))
2490
2491
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002492 def test_signature_on_class(self):
2493 class C:
2494 def __init__(self, a):
2495 pass
2496
2497 self.assertEqual(self.signature(C),
2498 ((('a', ..., ..., "positional_or_keyword"),),
2499 ...))
2500
2501 class CM(type):
2502 def __call__(cls, a):
2503 pass
2504 class C(metaclass=CM):
2505 def __init__(self, b):
2506 pass
2507
2508 self.assertEqual(self.signature(C),
2509 ((('a', ..., ..., "positional_or_keyword"),),
2510 ...))
2511
2512 class CM(type):
2513 def __new__(mcls, name, bases, dct, *, foo=1):
2514 return super().__new__(mcls, name, bases, dct)
2515 class C(metaclass=CM):
2516 def __init__(self, b):
2517 pass
2518
2519 self.assertEqual(self.signature(C),
2520 ((('b', ..., ..., "positional_or_keyword"),),
2521 ...))
2522
2523 self.assertEqual(self.signature(CM),
2524 ((('name', ..., ..., "positional_or_keyword"),
2525 ('bases', ..., ..., "positional_or_keyword"),
2526 ('dct', ..., ..., "positional_or_keyword"),
2527 ('foo', 1, ..., "keyword_only")),
2528 ...))
2529
2530 class CMM(type):
2531 def __new__(mcls, name, bases, dct, *, foo=1):
2532 return super().__new__(mcls, name, bases, dct)
2533 def __call__(cls, nm, bs, dt):
2534 return type(nm, bs, dt)
2535 class CM(type, metaclass=CMM):
2536 def __new__(mcls, name, bases, dct, *, bar=2):
2537 return super().__new__(mcls, name, bases, dct)
2538 class C(metaclass=CM):
2539 def __init__(self, b):
2540 pass
2541
2542 self.assertEqual(self.signature(CMM),
2543 ((('name', ..., ..., "positional_or_keyword"),
2544 ('bases', ..., ..., "positional_or_keyword"),
2545 ('dct', ..., ..., "positional_or_keyword"),
2546 ('foo', 1, ..., "keyword_only")),
2547 ...))
2548
2549 self.assertEqual(self.signature(CM),
2550 ((('nm', ..., ..., "positional_or_keyword"),
2551 ('bs', ..., ..., "positional_or_keyword"),
2552 ('dt', ..., ..., "positional_or_keyword")),
2553 ...))
2554
2555 self.assertEqual(self.signature(C),
2556 ((('b', ..., ..., "positional_or_keyword"),),
2557 ...))
2558
2559 class CM(type):
2560 def __init__(cls, name, bases, dct, *, bar=2):
2561 return super().__init__(name, bases, dct)
2562 class C(metaclass=CM):
2563 def __init__(self, b):
2564 pass
2565
2566 self.assertEqual(self.signature(CM),
2567 ((('name', ..., ..., "positional_or_keyword"),
2568 ('bases', ..., ..., "positional_or_keyword"),
2569 ('dct', ..., ..., "positional_or_keyword"),
2570 ('bar', 2, ..., "keyword_only")),
2571 ...))
2572
Yury Selivanov145dff82014-02-01 13:49:29 -05002573 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2574 "Signature information for builtins requires docstrings")
2575 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002576 # Test classes without user-defined __init__ or __new__
2577 class C: pass
2578 self.assertEqual(str(inspect.signature(C)), '()')
2579 class D(C): pass
2580 self.assertEqual(str(inspect.signature(D)), '()')
2581
2582 # Test meta-classes without user-defined __init__ or __new__
2583 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002584 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002585 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2586 self.assertEqual(inspect.signature(C), None)
2587 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2588 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002589
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002590 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2591 "Signature information for builtins requires docstrings")
2592 def test_signature_on_builtin_class(self):
2593 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2594 '(file, protocol=None, fix_imports=True)')
2595
2596 class P(_pickle.Pickler): pass
2597 class EmptyTrait: pass
2598 class P2(EmptyTrait, P): pass
2599 self.assertEqual(str(inspect.signature(P)),
2600 '(file, protocol=None, fix_imports=True)')
2601 self.assertEqual(str(inspect.signature(P2)),
2602 '(file, protocol=None, fix_imports=True)')
2603
2604 class P3(P2):
2605 def __init__(self, spam):
2606 pass
2607 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2608
2609 class MetaP(type):
2610 def __call__(cls, foo, bar):
2611 pass
2612 class P4(P2, metaclass=MetaP):
2613 pass
2614 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2615
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002616 def test_signature_on_callable_objects(self):
2617 class Foo:
2618 def __call__(self, a):
2619 pass
2620
2621 self.assertEqual(self.signature(Foo()),
2622 ((('a', ..., ..., "positional_or_keyword"),),
2623 ...))
2624
2625 class Spam:
2626 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002627 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002628 inspect.signature(Spam())
2629
2630 class Bar(Spam, Foo):
2631 pass
2632
2633 self.assertEqual(self.signature(Bar()),
2634 ((('a', ..., ..., "positional_or_keyword"),),
2635 ...))
2636
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002637 class Wrapped:
2638 pass
2639 Wrapped.__wrapped__ = lambda a: None
2640 self.assertEqual(self.signature(Wrapped),
2641 ((('a', ..., ..., "positional_or_keyword"),),
2642 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002643 # wrapper loop:
2644 Wrapped.__wrapped__ = Wrapped
2645 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2646 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002647
2648 def test_signature_on_lambdas(self):
2649 self.assertEqual(self.signature((lambda a=10: a)),
2650 ((('a', 10, ..., "positional_or_keyword"),),
2651 ...))
2652
2653 def test_signature_equality(self):
2654 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002655 self.assertFalse(inspect.signature(foo) == 42)
2656 self.assertTrue(inspect.signature(foo) != 42)
2657 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2658 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002659
2660 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002661 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2662 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002663 self.assertEqual(
2664 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002665
2666 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002667 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2668 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002669 self.assertNotEqual(
2670 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002671
2672 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002673 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2674 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002675 self.assertNotEqual(
2676 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002677
2678 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002679 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2680 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002681 self.assertNotEqual(
2682 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002683
2684 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002685 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2686 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002687 self.assertNotEqual(
2688 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002689
2690 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002691 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2692 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002693 self.assertNotEqual(
2694 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002695 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002696 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
2697 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002698 self.assertNotEqual(
2699 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002700
2701 def foo(*, a, b, c): pass
2702 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002703 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2704 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002705 self.assertEqual(
2706 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002707
2708 def foo(*, a=1, b, c): pass
2709 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002710 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2711 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002712 self.assertEqual(
2713 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002714
2715 def foo(pos, *, a=1, b, c): pass
2716 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002717 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2718 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002719 self.assertEqual(
2720 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002721
2722 def foo(pos, *, a, b, c): pass
2723 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002724 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2725 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002726 self.assertNotEqual(
2727 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002728
2729 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2730 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002731 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2732 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002733 self.assertEqual(
2734 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002735
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002736 def test_signature_hashable(self):
2737 S = inspect.Signature
2738 P = inspect.Parameter
2739
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002740 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002741 foo_sig = inspect.signature(foo)
2742
2743 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2744
2745 self.assertEqual(hash(foo_sig), hash(manual_sig))
2746 self.assertNotEqual(hash(foo_sig),
2747 hash(manual_sig.replace(return_annotation='spam')))
2748
2749 def bar(a) -> 1: pass
2750 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2751
2752 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002753 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002754 hash(inspect.signature(foo))
2755
2756 def foo(a) -> {}: pass
2757 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2758 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002759
2760 def test_signature_str(self):
2761 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2762 pass
2763 self.assertEqual(str(inspect.signature(foo)),
2764 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2765
2766 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2767 pass
2768 self.assertEqual(str(inspect.signature(foo)),
2769 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2770
2771 def foo():
2772 pass
2773 self.assertEqual(str(inspect.signature(foo)), '()')
2774
2775 def test_signature_str_positional_only(self):
2776 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002777 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002778
2779 def test(a_po, *, b, **kwargs):
2780 return a_po, kwargs
2781
2782 sig = inspect.signature(test)
2783 new_params = list(sig.parameters.values())
2784 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2785 test.__signature__ = sig.replace(parameters=new_params)
2786
2787 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002788 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002789
Yury Selivanov2393dca2014-01-27 15:07:58 -05002790 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2791 '(foo, /)')
2792
2793 self.assertEqual(str(S(parameters=[
2794 P('foo', P.POSITIONAL_ONLY),
2795 P('bar', P.VAR_KEYWORD)])),
2796 '(foo, /, **bar)')
2797
2798 self.assertEqual(str(S(parameters=[
2799 P('foo', P.POSITIONAL_ONLY),
2800 P('bar', P.VAR_POSITIONAL)])),
2801 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002802
2803 def test_signature_replace_anno(self):
2804 def test() -> 42:
2805 pass
2806
2807 sig = inspect.signature(test)
2808 sig = sig.replace(return_annotation=None)
2809 self.assertIs(sig.return_annotation, None)
2810 sig = sig.replace(return_annotation=sig.empty)
2811 self.assertIs(sig.return_annotation, sig.empty)
2812 sig = sig.replace(return_annotation=42)
2813 self.assertEqual(sig.return_annotation, 42)
2814 self.assertEqual(sig, inspect.signature(test))
2815
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002816 def test_signature_on_mangled_parameters(self):
2817 class Spam:
2818 def foo(self, __p1:1=2, *, __p2:2=3):
2819 pass
2820 class Ham(Spam):
2821 pass
2822
2823 self.assertEqual(self.signature(Spam.foo),
2824 ((('self', ..., ..., "positional_or_keyword"),
2825 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2826 ('_Spam__p2', 3, 2, "keyword_only")),
2827 ...))
2828
2829 self.assertEqual(self.signature(Spam.foo),
2830 self.signature(Ham.foo))
2831
Yury Selivanovda396452014-03-27 12:09:24 -04002832 def test_signature_from_callable_python_obj(self):
2833 class MySignature(inspect.Signature): pass
2834 def foo(a, *, b:1): pass
2835 foo_sig = MySignature.from_callable(foo)
2836 self.assertTrue(isinstance(foo_sig, MySignature))
2837
2838 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2839 "Signature information for builtins requires docstrings")
2840 def test_signature_from_callable_builtin_obj(self):
2841 class MySignature(inspect.Signature): pass
2842 sig = MySignature.from_callable(_pickle.Pickler)
2843 self.assertTrue(isinstance(sig, MySignature))
2844
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002845
2846class TestParameterObject(unittest.TestCase):
2847 def test_signature_parameter_kinds(self):
2848 P = inspect.Parameter
2849 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2850 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2851
2852 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2853 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2854
2855 def test_signature_parameter_object(self):
2856 p = inspect.Parameter('foo', default=10,
2857 kind=inspect.Parameter.POSITIONAL_ONLY)
2858 self.assertEqual(p.name, 'foo')
2859 self.assertEqual(p.default, 10)
2860 self.assertIs(p.annotation, p.empty)
2861 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2862
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002863 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002864 inspect.Parameter('foo', default=10, kind='123')
2865
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002866 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002867 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2868
Yury Selivanov2393dca2014-01-27 15:07:58 -05002869 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002870 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2871
Yury Selivanov2393dca2014-01-27 15:07:58 -05002872 with self.assertRaisesRegex(ValueError,
2873 'is not a valid parameter name'):
2874 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2875
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002876 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002877 inspect.Parameter('a', default=42,
2878 kind=inspect.Parameter.VAR_KEYWORD)
2879
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002880 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002881 inspect.Parameter('a', default=42,
2882 kind=inspect.Parameter.VAR_POSITIONAL)
2883
2884 p = inspect.Parameter('a', default=42,
2885 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002886 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002887 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2888
2889 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002890 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002891
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002892 def test_signature_parameter_hashable(self):
2893 P = inspect.Parameter
2894 foo = P('foo', kind=P.POSITIONAL_ONLY)
2895 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
2896 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
2897 default=42)))
2898 self.assertNotEqual(hash(foo),
2899 hash(foo.replace(kind=P.VAR_POSITIONAL)))
2900
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002901 def test_signature_parameter_equality(self):
2902 P = inspect.Parameter
2903 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2904
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002905 self.assertTrue(p == p)
2906 self.assertFalse(p != p)
2907 self.assertFalse(p == 42)
2908 self.assertTrue(p != 42)
2909 self.assertTrue(p == EqualsToAll())
2910 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002911
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002912 self.assertTrue(p == P('foo', default=42,
2913 kind=inspect.Parameter.KEYWORD_ONLY))
2914 self.assertFalse(p != P('foo', default=42,
2915 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002916
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002917 def test_signature_parameter_replace(self):
2918 p = inspect.Parameter('foo', default=42,
2919 kind=inspect.Parameter.KEYWORD_ONLY)
2920
2921 self.assertIsNot(p, p.replace())
2922 self.assertEqual(p, p.replace())
2923
2924 p2 = p.replace(annotation=1)
2925 self.assertEqual(p2.annotation, 1)
2926 p2 = p2.replace(annotation=p2.empty)
2927 self.assertEqual(p, p2)
2928
2929 p2 = p2.replace(name='bar')
2930 self.assertEqual(p2.name, 'bar')
2931 self.assertNotEqual(p2, p)
2932
Yury Selivanov2393dca2014-01-27 15:07:58 -05002933 with self.assertRaisesRegex(ValueError,
2934 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002935 p2 = p2.replace(name=p2.empty)
2936
2937 p2 = p2.replace(name='foo', default=None)
2938 self.assertIs(p2.default, None)
2939 self.assertNotEqual(p2, p)
2940
2941 p2 = p2.replace(name='foo', default=p2.empty)
2942 self.assertIs(p2.default, p2.empty)
2943
2944
2945 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2946 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2947 self.assertNotEqual(p2, p)
2948
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002949 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002950 p2 = p2.replace(kind=p2.empty)
2951
2952 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2953 self.assertEqual(p2, p)
2954
2955 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002956 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2957 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002958
2959 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002960 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002961
2962 with self.assertRaises(AttributeError):
2963 p.foo = 'bar'
2964
2965 with self.assertRaises(AttributeError):
2966 p.kind = 123
2967
2968
2969class TestSignatureBind(unittest.TestCase):
2970 @staticmethod
2971 def call(func, *args, **kwargs):
2972 sig = inspect.signature(func)
2973 ba = sig.bind(*args, **kwargs)
2974 return func(*ba.args, **ba.kwargs)
2975
2976 def test_signature_bind_empty(self):
2977 def test():
2978 return 42
2979
2980 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002981 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002982 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002983 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002984 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04002985 with self.assertRaisesRegex(
2986 TypeError, "got an unexpected keyword argument 'spam'"):
2987
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002988 self.call(test, spam=1)
2989
2990 def test_signature_bind_var(self):
2991 def test(*args, **kwargs):
2992 return args, kwargs
2993
2994 self.assertEqual(self.call(test), ((), {}))
2995 self.assertEqual(self.call(test, 1), ((1,), {}))
2996 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2997 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2998 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2999 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3000 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3001 ((1, 2), {'foo': 'bar'}))
3002
3003 def test_signature_bind_just_args(self):
3004 def test(a, b, c):
3005 return a, b, c
3006
3007 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3008
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003009 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003010 self.call(test, 1, 2, 3, 4)
3011
Yury Selivanov86872752015-05-19 00:27:49 -04003012 with self.assertRaisesRegex(TypeError,
3013 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003014 self.call(test, 1)
3015
Yury Selivanov86872752015-05-19 00:27:49 -04003016 with self.assertRaisesRegex(TypeError,
3017 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003018 self.call(test)
3019
3020 def test(a, b, c=10):
3021 return a, b, c
3022 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3023 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3024
3025 def test(a=1, b=2, c=3):
3026 return a, b, c
3027 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3028 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3029 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3030
3031 def test_signature_bind_varargs_order(self):
3032 def test(*args):
3033 return args
3034
3035 self.assertEqual(self.call(test), ())
3036 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3037
3038 def test_signature_bind_args_and_varargs(self):
3039 def test(a, b, c=3, *args):
3040 return a, b, c, args
3041
3042 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3043 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3044 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3045 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3046
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003047 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003048 "multiple values for argument 'c'"):
3049 self.call(test, 1, 2, 3, c=4)
3050
3051 def test_signature_bind_just_kwargs(self):
3052 def test(**kwargs):
3053 return kwargs
3054
3055 self.assertEqual(self.call(test), {})
3056 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3057 {'foo': 'bar', 'spam': 'ham'})
3058
3059 def test_signature_bind_args_and_kwargs(self):
3060 def test(a, b, c=3, **kwargs):
3061 return a, b, c, kwargs
3062
3063 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3064 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3065 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3066 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3067 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3068 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3069 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3070 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3071 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3072 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3073 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3074 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3075 (1, 2, 4, {'foo': 'bar'}))
3076 self.assertEqual(self.call(test, c=5, a=4, b=3),
3077 (4, 3, 5, {}))
3078
3079 def test_signature_bind_kwonly(self):
3080 def test(*, foo):
3081 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003082 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003083 'too many positional arguments'):
3084 self.call(test, 1)
3085 self.assertEqual(self.call(test, foo=1), 1)
3086
3087 def test(a, *, foo=1, bar):
3088 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003089 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003090 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003091 self.call(test, 1)
3092
3093 def test(foo, *, bar):
3094 return foo, bar
3095 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3096 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3097
Yury Selivanov86872752015-05-19 00:27:49 -04003098 with self.assertRaisesRegex(
3099 TypeError, "got an unexpected keyword argument 'spam'"):
3100
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003101 self.call(test, bar=2, foo=1, spam=10)
3102
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003103 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003104 'too many positional arguments'):
3105 self.call(test, 1, 2)
3106
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003107 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003108 'too many positional arguments'):
3109 self.call(test, 1, 2, bar=2)
3110
Yury Selivanov86872752015-05-19 00:27:49 -04003111 with self.assertRaisesRegex(
3112 TypeError, "got an unexpected keyword argument 'spam'"):
3113
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003114 self.call(test, 1, bar=2, spam='ham')
3115
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003116 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003117 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003118 self.call(test, 1)
3119
3120 def test(foo, *, bar, **bin):
3121 return foo, bar, bin
3122 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3123 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3124 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3125 (1, 2, {'spam': 'ham'}))
3126 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3127 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003128 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003129 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003130 self.call(test, spam='ham', bar=2)
3131 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3132 (1, 2, {'bin': 1, 'spam': 10}))
3133
3134 def test_signature_bind_arguments(self):
3135 def test(a, *args, b, z=100, **kwargs):
3136 pass
3137 sig = inspect.signature(test)
3138 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3139 # we won't have 'z' argument in the bound arguments object, as we didn't
3140 # pass it to the 'bind'
3141 self.assertEqual(tuple(ba.arguments.items()),
3142 (('a', 10), ('args', (20,)), ('b', 30),
3143 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3144 self.assertEqual(ba.kwargs,
3145 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3146 self.assertEqual(ba.args, (10, 20))
3147
3148 def test_signature_bind_positional_only(self):
3149 P = inspect.Parameter
3150
3151 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3152 return a_po, b_po, c_po, foo, bar, kwargs
3153
3154 sig = inspect.signature(test)
3155 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3156 for name in ('a_po', 'b_po', 'c_po'):
3157 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3158 new_sig = sig.replace(parameters=new_params.values())
3159 test.__signature__ = new_sig
3160
3161 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3162 (1, 2, 4, 5, 6, {}))
3163
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003164 self.assertEqual(self.call(test, 1, 2),
3165 (1, 2, 3, 42, 50, {}))
3166
3167 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3168 (1, 2, 3, 4, 5, {}))
3169
3170 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3171 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3172
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003173 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003174 self.call(test, 1, 2, c_po=4)
3175
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003176 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003177 self.call(test, a_po=1, b_po=2)
3178
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003179 def test_signature_bind_with_self_arg(self):
3180 # Issue #17071: one of the parameters is named "self
3181 def test(a, self, b):
3182 pass
3183 sig = inspect.signature(test)
3184 ba = sig.bind(1, 2, 3)
3185 self.assertEqual(ba.args, (1, 2, 3))
3186 ba = sig.bind(1, self=2, b=3)
3187 self.assertEqual(ba.args, (1, 2, 3))
3188
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003189 def test_signature_bind_vararg_name(self):
3190 def test(a, *args):
3191 return a, args
3192 sig = inspect.signature(test)
3193
Yury Selivanov86872752015-05-19 00:27:49 -04003194 with self.assertRaisesRegex(
3195 TypeError, "got an unexpected keyword argument 'args'"):
3196
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003197 sig.bind(a=0, args=1)
3198
3199 def test(*args, **kwargs):
3200 return args, kwargs
3201 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3202
3203 sig = inspect.signature(test)
3204 ba = sig.bind(args=1)
3205 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3206
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003207
3208class TestBoundArguments(unittest.TestCase):
3209 def test_signature_bound_arguments_unhashable(self):
3210 def foo(a): pass
3211 ba = inspect.signature(foo).bind(1)
3212
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003213 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003214 hash(ba)
3215
3216 def test_signature_bound_arguments_equality(self):
3217 def foo(a): pass
3218 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003219 self.assertTrue(ba == ba)
3220 self.assertFalse(ba != ba)
3221 self.assertTrue(ba == EqualsToAll())
3222 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003223
3224 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003225 self.assertTrue(ba == ba2)
3226 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003227
3228 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003229 self.assertFalse(ba == ba3)
3230 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003231 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003232 self.assertTrue(ba == ba3)
3233 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003234
3235 def bar(b): pass
3236 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003237 self.assertFalse(ba == ba4)
3238 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003239
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003240 def foo(*, a, b): pass
3241 sig = inspect.signature(foo)
3242 ba1 = sig.bind(a=1, b=2)
3243 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003244 self.assertTrue(ba1 == ba2)
3245 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003246
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003247 def test_signature_bound_arguments_pickle(self):
3248 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3249 sig = inspect.signature(foo)
3250 ba = sig.bind(20, 30, z={})
3251
3252 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3253 with self.subTest(pickle_ver=ver):
3254 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3255 self.assertEqual(ba, ba_pickled)
3256
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003257 def test_signature_bound_arguments_repr(self):
3258 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3259 sig = inspect.signature(foo)
3260 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003261 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003262
Yury Selivanovb907a512015-05-16 13:45:09 -04003263 def test_signature_bound_arguments_apply_defaults(self):
3264 def foo(a, b=1, *args, c:1={}, **kw): pass
3265 sig = inspect.signature(foo)
3266
3267 ba = sig.bind(20)
3268 ba.apply_defaults()
3269 self.assertEqual(
3270 list(ba.arguments.items()),
3271 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3272
3273 # Make sure that we preserve the order:
3274 # i.e. 'c' should be *before* 'kw'.
3275 ba = sig.bind(10, 20, 30, d=1)
3276 ba.apply_defaults()
3277 self.assertEqual(
3278 list(ba.arguments.items()),
3279 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3280
3281 # Make sure that BoundArguments produced by bind_partial()
3282 # are supported.
3283 def foo(a, b): pass
3284 sig = inspect.signature(foo)
3285 ba = sig.bind_partial(20)
3286 ba.apply_defaults()
3287 self.assertEqual(
3288 list(ba.arguments.items()),
3289 [('a', 20)])
3290
3291 # Test no args
3292 def foo(): pass
3293 sig = inspect.signature(foo)
3294 ba = sig.bind()
3295 ba.apply_defaults()
3296 self.assertEqual(list(ba.arguments.items()), [])
3297
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003298
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003299class TestSignaturePrivateHelpers(unittest.TestCase):
3300 def test_signature_get_bound_param(self):
3301 getter = inspect._signature_get_bound_param
3302
3303 self.assertEqual(getter('($self)'), 'self')
3304 self.assertEqual(getter('($self, obj)'), 'self')
3305 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3306
Larry Hastings2623c8c2014-02-08 22:15:29 -08003307 def _strip_non_python_syntax(self, input,
3308 clean_signature, self_parameter, last_positional_only):
3309 computed_clean_signature, \
3310 computed_self_parameter, \
3311 computed_last_positional_only = \
3312 inspect._signature_strip_non_python_syntax(input)
3313 self.assertEqual(computed_clean_signature, clean_signature)
3314 self.assertEqual(computed_self_parameter, self_parameter)
3315 self.assertEqual(computed_last_positional_only, last_positional_only)
3316
3317 def test_signature_strip_non_python_syntax(self):
3318 self._strip_non_python_syntax(
3319 "($module, /, path, mode, *, dir_fd=None, " +
3320 "effective_ids=False,\n follow_symlinks=True)",
3321 "(module, path, mode, *, dir_fd=None, " +
3322 "effective_ids=False, follow_symlinks=True)",
3323 0,
3324 0)
3325
3326 self._strip_non_python_syntax(
3327 "($module, word, salt, /)",
3328 "(module, word, salt)",
3329 0,
3330 2)
3331
3332 self._strip_non_python_syntax(
3333 "(x, y=None, z=None, /)",
3334 "(x, y=None, z=None)",
3335 None,
3336 2)
3337
3338 self._strip_non_python_syntax(
3339 "(x, y=None, z=None)",
3340 "(x, y=None, z=None)",
3341 None,
3342 None)
3343
3344 self._strip_non_python_syntax(
3345 "(x,\n y=None,\n z = None )",
3346 "(x, y=None, z=None)",
3347 None,
3348 None)
3349
3350 self._strip_non_python_syntax(
3351 "",
3352 "",
3353 None,
3354 None)
3355
3356 self._strip_non_python_syntax(
3357 None,
3358 None,
3359 None,
3360 None)
3361
Nick Coghlan9c680b02015-04-13 12:54:54 -04003362class TestSignatureDefinitions(unittest.TestCase):
3363 # This test case provides a home for checking that particular APIs
3364 # have signatures available for introspection
3365
3366 @cpython_only
3367 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3368 "Signature information for builtins requires docstrings")
3369 def test_builtins_have_signatures(self):
3370 # This checks all builtin callables in CPython have signatures
3371 # A few have signatures Signature can't yet handle, so we skip those
3372 # since they will have to wait until PEP 457 adds the required
3373 # introspection support to the inspect module
3374 # Some others also haven't been converted yet for various other
3375 # reasons, so we also skip those for the time being, but design
3376 # the test to fail in order to indicate when it needs to be
3377 # updated.
3378 no_signature = set()
3379 # These need PEP 457 groups
3380 needs_groups = {"range", "slice", "dir", "getattr",
3381 "next", "iter", "vars"}
3382 no_signature |= needs_groups
3383 # These need PEP 457 groups or a signature change to accept None
3384 needs_semantic_update = {"round"}
3385 no_signature |= needs_semantic_update
3386 # These need *args support in Argument Clinic
3387 needs_varargs = {"min", "max", "print", "__build_class__"}
3388 no_signature |= needs_varargs
3389 # These simply weren't covered in the initial AC conversion
3390 # for builtin callables
3391 not_converted_yet = {"open", "__import__"}
3392 no_signature |= not_converted_yet
3393 # These builtin types are expected to provide introspection info
3394 types_with_signatures = set()
3395 # Check the signatures we expect to be there
3396 ns = vars(builtins)
3397 for name, obj in sorted(ns.items()):
3398 if not callable(obj):
3399 continue
3400 # The builtin types haven't been converted to AC yet
3401 if isinstance(obj, type) and (name not in types_with_signatures):
3402 # Note that this also skips all the exception types
3403 no_signature.add(name)
3404 if (name in no_signature):
3405 # Not yet converted
3406 continue
3407 with self.subTest(builtin=name):
3408 self.assertIsNotNone(inspect.signature(obj))
3409 # Check callables that haven't been converted don't claim a signature
3410 # This ensures this test will start failing as more signatures are
3411 # added, so the affected items can be moved into the scope of the
3412 # regression test above
3413 for name in no_signature:
3414 with self.subTest(builtin=name):
3415 self.assertIsNone(obj.__text_signature__)
3416
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003417
Nick Coghlane8c45d62013-07-28 20:00:01 +10003418class TestUnwrap(unittest.TestCase):
3419
3420 def test_unwrap_one(self):
3421 def func(a, b):
3422 return a + b
3423 wrapper = functools.lru_cache(maxsize=20)(func)
3424 self.assertIs(inspect.unwrap(wrapper), func)
3425
3426 def test_unwrap_several(self):
3427 def func(a, b):
3428 return a + b
3429 wrapper = func
3430 for __ in range(10):
3431 @functools.wraps(wrapper)
3432 def wrapper():
3433 pass
3434 self.assertIsNot(wrapper.__wrapped__, func)
3435 self.assertIs(inspect.unwrap(wrapper), func)
3436
3437 def test_stop(self):
3438 def func1(a, b):
3439 return a + b
3440 @functools.wraps(func1)
3441 def func2():
3442 pass
3443 @functools.wraps(func2)
3444 def wrapper():
3445 pass
3446 func2.stop_here = 1
3447 unwrapped = inspect.unwrap(wrapper,
3448 stop=(lambda f: hasattr(f, "stop_here")))
3449 self.assertIs(unwrapped, func2)
3450
3451 def test_cycle(self):
3452 def func1(): pass
3453 func1.__wrapped__ = func1
3454 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3455 inspect.unwrap(func1)
3456
3457 def func2(): pass
3458 func2.__wrapped__ = func1
3459 func1.__wrapped__ = func2
3460 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3461 inspect.unwrap(func1)
3462 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3463 inspect.unwrap(func2)
3464
3465 def test_unhashable(self):
3466 def func(): pass
3467 func.__wrapped__ = None
3468 class C:
3469 __hash__ = None
3470 __wrapped__ = func
3471 self.assertIsNone(inspect.unwrap(C()))
3472
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003473class TestMain(unittest.TestCase):
3474 def test_only_source(self):
3475 module = importlib.import_module('unittest')
3476 rc, out, err = assert_python_ok('-m', 'inspect',
3477 'unittest')
3478 lines = out.decode().splitlines()
3479 # ignore the final newline
3480 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3481 self.assertEqual(err, b'')
3482
Yury Selivanov42407ab2014-06-23 10:23:50 -07003483 def test_custom_getattr(self):
3484 def foo():
3485 pass
3486 foo.__signature__ = 42
3487 with self.assertRaises(TypeError):
3488 inspect.signature(foo)
3489
Brett Cannon634a8fc2013-10-02 10:25:42 -04003490 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003491 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003492 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003493 rc, out, err = assert_python_ok('-m', 'inspect',
3494 'concurrent.futures:ThreadPoolExecutor')
3495 lines = out.decode().splitlines()
3496 # ignore the final newline
3497 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003498 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003499 self.assertEqual(err, b'')
3500
3501 def test_builtins(self):
3502 module = importlib.import_module('unittest')
3503 _, out, err = assert_python_failure('-m', 'inspect',
3504 'sys')
3505 lines = err.decode().splitlines()
3506 self.assertEqual(lines, ["Can't get info for builtin modules."])
3507
3508 def test_details(self):
3509 module = importlib.import_module('unittest')
3510 rc, out, err = assert_python_ok('-m', 'inspect',
3511 'unittest', '--details')
3512 output = out.decode()
3513 # Just a quick sanity check on the output
3514 self.assertIn(module.__name__, output)
3515 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003516 if not sys.flags.optimize:
3517 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003518 self.assertEqual(err, b'')
3519
3520
Yury Selivanovef1e7502014-12-08 16:05:34 -05003521class TestReload(unittest.TestCase):
3522
3523 src_before = textwrap.dedent("""\
3524def foo():
3525 print("Bla")
3526 """)
3527
3528 src_after = textwrap.dedent("""\
3529def foo():
3530 print("Oh no!")
3531 """)
3532
3533 def assertInspectEqual(self, path, source):
3534 inspected_src = inspect.getsource(source)
3535 with open(path) as src:
3536 self.assertEqual(
3537 src.read().splitlines(True),
3538 inspected_src.splitlines(True)
3539 )
3540
3541 def test_getsource_reload(self):
3542 # see issue 1218234
3543 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3544 module = importlib.import_module(name)
3545 self.assertInspectEqual(path, module)
3546 with open(path, 'w') as src:
3547 src.write(self.src_after)
3548 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003549
Nick Coghlane8c45d62013-07-28 20:00:01 +10003550
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003551def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003552 run_unittest(
3553 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3554 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3555 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003556 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003557 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003558 TestBoundArguments, TestSignaturePrivateHelpers,
3559 TestSignatureDefinitions,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003560 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
3561 TestGetCoroutineState
Michael Foord95fc51d2010-11-20 15:07:30 +00003562 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003563
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003564if __name__ == "__main__":
3565 test_main()