blob: ab22c7d677544a8e93dcff92ac3679b563c19b57 [file] [log] [blame]
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001import builtins
Guido van Rossum813b0e52007-05-21 18:11:34 +00002import collections
Larry Hastings5c661892014-01-24 06:17:25 -08003import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10004import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10005import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08006import inspect
7import io
8import linecache
9import os
Christian Heimesa3538eb2007-11-06 11:44:48 +000010from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080011import _pickle
Yury Selivanova5d63dd2014-03-27 11:31:43 -040012import pickle
Larry Hastings5c661892014-01-24 06:17:25 -080013import re
14import shutil
15import sys
16import types
Yury Selivanovef1e7502014-12-08 16:05:34 -050017import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080018import unicodedata
19import unittest
Yury Selivanova773de02014-02-21 18:30:53 -050020import unittest.mock
Yury Selivanov75445082015-05-11 22:57:16 -040021import warnings
Larry Hastings5c661892014-01-24 06:17:25 -080022
Brett Cannon634a8fc2013-10-02 10:25:42 -040023try:
24 from concurrent.futures import ThreadPoolExecutor
25except ImportError:
26 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000027
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020028from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Nick Coghlanf9e227e2014-08-17 14:01:19 +100029from test.support import MISSING_C_DOCSTRINGS, cpython_only
Berker Peksagce643912015-05-06 06:33:17 +030030from test.support.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000031from test import inspect_fodder as mod
32from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000033
Yury Selivanovef1e7502014-12-08 16:05:34 -050034from test.test_import import _ready_to_import
35
R. David Murray74b89242009-05-13 17:33:03 +000036
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000037# Functions tested in this suite:
38# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000039# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
40# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
41# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
42# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000043
Nick Coghlanf088e5e2008-12-14 11:50:48 +000044# NOTE: There are some additional tests relating to interaction with
45# zipimport in the test_zipimport_support test module.
46
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000047modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000048if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000049 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000050
Christian Heimesa3538eb2007-11-06 11:44:48 +000051# Normalize file names: on Windows, the case of file names of compiled
52# modules depends on the path used to start the python executable.
53modfile = normcase(modfile)
54
55def revise(filename, *args):
56 return (normcase(filename),) + args
57
Georg Brandl1a3284e2007-12-02 09:40:06 +000058import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000059
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000060git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000061
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000062class IsTestBase(unittest.TestCase):
63 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
64 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000065 inspect.ismodule, inspect.istraceback,
Yury Selivanov75445082015-05-11 22:57:16 -040066 inspect.isgenerator, inspect.isgeneratorfunction,
67 inspect.iscoroutine, inspect.iscoroutinefunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000068
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000069 def istest(self, predicate, exp):
70 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000071 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000072
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000073 for other in self.predicates - set([predicate]):
Yury Selivanov75445082015-05-11 22:57:16 -040074 if (predicate == inspect.isgeneratorfunction or \
75 predicate == inspect.iscoroutinefunction) and \
Christian Heimes7131fd92008-02-19 14:21:46 +000076 other == inspect.isfunction:
77 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000078 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000079
Christian Heimes7131fd92008-02-19 14:21:46 +000080def generator_function_example(self):
81 for i in range(2):
82 yield i
83
Yury Selivanov75445082015-05-11 22:57:16 -040084async def coroutine_function_example(self):
85 return 'spam'
86
87@types.coroutine
88def gen_coroutine_function_example(self):
89 yield
90 return 'spam'
91
Yury Selivanova5d63dd2014-03-27 11:31:43 -040092
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000093class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +000094
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000095 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020096 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000097 self.istest(inspect.isbuiltin, 'sys.exit')
98 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +000099 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200100 try:
101 1/0
102 except:
103 tb = sys.exc_info()[2]
104 self.istest(inspect.isframe, 'tb.tb_frame')
105 self.istest(inspect.istraceback, 'tb')
106 if hasattr(types, 'GetSetDescriptorType'):
107 self.istest(inspect.isgetsetdescriptor,
108 'type(tb.tb_frame).f_locals')
109 else:
110 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
111 finally:
112 # Clear traceback and all the frames and local variables hanging to it.
113 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000114 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000115 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000116 self.istest(inspect.ismethod, 'git.argue')
117 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000118 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000119 self.istest(inspect.isgenerator, '(x for x in range(2))')
120 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400121
122 with warnings.catch_warnings():
123 warnings.simplefilter("ignore")
124 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
125 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
126
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000127 if hasattr(types, 'MemberDescriptorType'):
128 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
129 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000130 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000131
Yury Selivanov75445082015-05-11 22:57:16 -0400132 def test_iscoroutine(self):
133 gen_coro = gen_coroutine_function_example(1)
134 coro = coroutine_function_example(1)
135
Yury Selivanov5376ba92015-06-22 12:19:30 -0400136 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400137 inspect.iscoroutinefunction(gen_coroutine_function_example))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400138 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400139
140 self.assertTrue(
141 inspect.isgeneratorfunction(gen_coroutine_function_example))
142 self.assertTrue(inspect.isgenerator(gen_coro))
143
144 self.assertTrue(
145 inspect.iscoroutinefunction(coroutine_function_example))
146 self.assertTrue(inspect.iscoroutine(coro))
147
148 self.assertFalse(
149 inspect.isgeneratorfunction(coroutine_function_example))
150 self.assertFalse(inspect.isgenerator(coro))
151
152 coro.close(); gen_coro.close() # silence warnings
153
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000154 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000155 self.assertTrue(inspect.isroutine(mod.spam))
156 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000157
Benjamin Petersonc4656002009-01-17 22:41:18 +0000158 def test_isclass(self):
159 self.istest(inspect.isclass, 'mod.StupidGit')
160 self.assertTrue(inspect.isclass(list))
161
162 class CustomGetattr(object):
163 def __getattr__(self, attr):
164 return None
165 self.assertFalse(inspect.isclass(CustomGetattr()))
166
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000167 def test_get_slot_members(self):
168 class C(object):
169 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000170 x = C()
171 x.a = 42
172 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000173 self.assertIn('a', members)
174 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000175
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000176 def test_isabstract(self):
177 from abc import ABCMeta, abstractmethod
178
179 class AbstractClassExample(metaclass=ABCMeta):
180
181 @abstractmethod
182 def foo(self):
183 pass
184
185 class ClassExample(AbstractClassExample):
186 def foo(self):
187 pass
188
189 a = ClassExample()
190
191 # Test general behaviour.
192 self.assertTrue(inspect.isabstract(AbstractClassExample))
193 self.assertFalse(inspect.isabstract(ClassExample))
194 self.assertFalse(inspect.isabstract(a))
195 self.assertFalse(inspect.isabstract(int))
196 self.assertFalse(inspect.isabstract(5))
197
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000198
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000199class TestInterpreterStack(IsTestBase):
200 def __init__(self, *args, **kwargs):
201 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000202
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000203 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000204
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000205 def test_abuse_done(self):
206 self.istest(inspect.istraceback, 'git.ex[2]')
207 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000208
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000209 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000210 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000211 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000212 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000213 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000214 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000215 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000216 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000217 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000218 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400219 # Test named tuple fields
220 record = mod.st[0]
221 self.assertIs(record.frame, mod.fr)
222 self.assertEqual(record.lineno, 16)
223 self.assertEqual(record.filename, mod.__file__)
224 self.assertEqual(record.function, 'eggs')
225 self.assertIn('inspect.stack()', record.code_context[0])
226 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000227
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000228 def test_trace(self):
229 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000230 self.assertEqual(revise(*git.tr[0][1:]),
231 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
232 self.assertEqual(revise(*git.tr[1][1:]),
233 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
234 self.assertEqual(revise(*git.tr[2][1:]),
235 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000236
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000237 def test_frame(self):
238 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
239 self.assertEqual(args, ['x', 'y'])
240 self.assertEqual(varargs, None)
241 self.assertEqual(varkw, None)
242 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
243 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
244 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000245
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000246 def test_previous_frame(self):
247 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000248 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000249 self.assertEqual(varargs, 'g')
250 self.assertEqual(varkw, 'h')
251 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000252 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000253
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000254class GetSourceBase(unittest.TestCase):
255 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000256 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000257
Yury Selivanov6738b112015-05-16 10:10:21 -0400258 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000259 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000260 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000261
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000262 def sourcerange(self, top, bottom):
263 lines = self.source.split("\n")
264 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000265
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000266 def assertSourceEqual(self, obj, top, bottom):
267 self.assertEqual(inspect.getsource(obj),
268 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000269
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000270class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000271 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000272
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000273 def test_getclasses(self):
274 classes = inspect.getmembers(mod, inspect.isclass)
275 self.assertEqual(classes,
276 [('FesteringGob', mod.FesteringGob),
277 ('MalodorousPervert', mod.MalodorousPervert),
278 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300279 ('StupidGit', mod.StupidGit),
280 ('Tit', mod.MalodorousPervert),
281 ])
282 tree = inspect.getclasstree([cls[1] for cls in classes])
283 self.assertEqual(tree,
284 [(object, ()),
285 [(mod.ParrotDroppings, (object,)),
286 [(mod.FesteringGob, (mod.MalodorousPervert,
287 mod.ParrotDroppings))
288 ],
289 (mod.StupidGit, (object,)),
290 [(mod.MalodorousPervert, (mod.StupidGit,)),
291 [(mod.FesteringGob, (mod.MalodorousPervert,
292 mod.ParrotDroppings))
293 ]
294 ]
295 ]
296 ])
297 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000298 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000299 [(object, ()),
300 [(mod.ParrotDroppings, (object,)),
301 (mod.StupidGit, (object,)),
302 [(mod.MalodorousPervert, (mod.StupidGit,)),
303 [(mod.FesteringGob, (mod.MalodorousPervert,
304 mod.ParrotDroppings))
305 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000306 ]
307 ]
308 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000309
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000310 def test_getfunctions(self):
311 functions = inspect.getmembers(mod, inspect.isfunction)
312 self.assertEqual(functions, [('eggs', mod.eggs),
313 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000314
R. David Murray378c0cf2010-02-24 01:46:21 +0000315 @unittest.skipIf(sys.flags.optimize >= 2,
316 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000317 def test_getdoc(self):
318 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
319 self.assertEqual(inspect.getdoc(mod.StupidGit),
320 'A longer,\n\nindented\n\ndocstring.')
321 self.assertEqual(inspect.getdoc(git.abuse),
322 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000323
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300324 @unittest.skipIf(sys.flags.optimize >= 2,
325 "Docstrings are omitted with -O2 and above")
326 def test_getdoc_inherited(self):
327 self.assertEqual(inspect.getdoc(mod.FesteringGob),
328 'A longer,\n\nindented\n\ndocstring.')
329 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
330 'Another\n\ndocstring\n\ncontaining\n\ntabs')
331 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
332 'Another\n\ndocstring\n\ncontaining\n\ntabs')
333 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
334 'The automatic gainsaying.')
335
336 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
337 def test_finddoc(self):
338 finddoc = inspect._finddoc
339 self.assertEqual(finddoc(int), int.__doc__)
340 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
341 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
342 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
343 self.assertEqual(finddoc(int.real), int.real.__doc__)
344
Georg Brandl0c77a822008-06-10 16:37:50 +0000345 def test_cleandoc(self):
346 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
347 'An\nindented\ndocstring.')
348
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000349 def test_getcomments(self):
350 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
351 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000352
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000353 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000354 # Check actual module
355 self.assertEqual(inspect.getmodule(mod), mod)
356 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000357 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000358 # Check a method (no __module__ attribute, falls back to filename)
359 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
360 # Do it again (check the caching isn't broken)
361 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
362 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000363 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000364 # Check filename override
365 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000366
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000367 def test_getsource(self):
368 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300369 self.assertSourceEqual(mod.StupidGit, 21, 50)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000370
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000371 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000372 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
373 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000374 fn = "_non_existing_filename_used_for_sourcefile_test.py"
375 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000376 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000377 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200378 try:
379 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
380 finally:
381 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000382
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000383 def test_getfile(self):
384 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000385
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500386 def test_getfile_class_without_module(self):
387 class CM(type):
388 @property
389 def __module__(cls):
390 raise AttributeError
391 class C(metaclass=CM):
392 pass
393 with self.assertRaises(TypeError):
394 inspect.getfile(C)
395
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000396 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000397 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000398 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000399 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000400 m.__file__ = "<string>" # hopefully not a real filename...
401 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000402 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000403 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000404 del sys.modules[name]
405 inspect.getmodule(compile('a=10','','single'))
406
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500407 def test_proceed_with_fake_filename(self):
408 '''doctest monkeypatches linecache to enable inspection'''
409 fn, source = '<test>', 'def x(): pass\n'
410 getlines = linecache.getlines
411 def monkey(filename, module_globals=None):
412 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300413 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500414 else:
415 return getlines(filename, module_globals)
416 linecache.getlines = monkey
417 try:
418 ns = {}
419 exec(compile(source, fn, 'single'), ns)
420 inspect.getsource(ns["x"])
421 finally:
422 linecache.getlines = getlines
423
Antoine Pitroua8723a02015-04-15 00:41:29 +0200424 def test_getsource_on_code_object(self):
425 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
426
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000427class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000428 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000429
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000430 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000431 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000432
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000433 def test_replacing_decorator(self):
434 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000435
Yury Selivanov081bbf62014-09-26 17:34:54 -0400436 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200437 self.assertSourceEqual(mod2.real, 130, 132)
438
439 def test_decorator_with_lambda(self):
440 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400441
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000442class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000443 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000444 def test_oneline_lambda(self):
445 # Test inspect.getsource with a one-line lambda function.
446 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000447
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000448 def test_threeline_lambda(self):
449 # Test inspect.getsource with a three-line lambda function,
450 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000451 self.assertSourceEqual(mod2.tll, 28, 30)
452
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000453 def test_twoline_indented_lambda(self):
454 # Test inspect.getsource with a two-line lambda function,
455 # where the second line _is_ indented.
456 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000457
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000458 def test_onelinefunc(self):
459 # Test inspect.getsource with a regular one-line function.
460 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000461
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000462 def test_manyargs(self):
463 # Test inspect.getsource with a regular function where
464 # the arguments are on two lines and _not_ indented and
465 # the body on the second line with the last arguments.
466 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000467
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000468 def test_twolinefunc(self):
469 # Test inspect.getsource with a regular function where
470 # the body is on two lines, following the argument list and
471 # continued on the next line by a \\.
472 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000473
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000474 def test_lambda_in_list(self):
475 # Test inspect.getsource with a one-line lambda function
476 # defined in a list, indented.
477 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000478
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000479 def test_anonymous(self):
480 # Test inspect.getsource with a lambda function defined
481 # as argument to another function.
482 self.assertSourceEqual(mod2.anonymous, 55, 55)
483
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000484class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000485 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000486
487 def test_with_comment(self):
488 self.assertSourceEqual(mod2.with_comment, 58, 59)
489
490 def test_multiline_sig(self):
491 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
492
Armin Rigodd5c0232005-09-25 11:45:45 +0000493 def test_nested_class(self):
494 self.assertSourceEqual(mod2.func69().func71, 71, 72)
495
496 def test_one_liner_followed_by_non_name(self):
497 self.assertSourceEqual(mod2.func77, 77, 77)
498
499 def test_one_liner_dedent_non_name(self):
500 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
501
502 def test_with_comment_instead_of_docstring(self):
503 self.assertSourceEqual(mod2.func88, 88, 90)
504
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000505 def test_method_in_dynamic_class(self):
506 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
507
R David Murray32562d72014-10-03 11:15:38 -0400508 # This should not skip for CPython, but might on a repackaged python where
509 # unicodedata is not an external module, or on pypy.
510 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
511 unicodedata.__file__.endswith('.py'),
512 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000513 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200514 self.assertRaises(OSError, inspect.getsource, unicodedata)
515 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000516
R. David Murraya1b37402010-06-17 02:04:29 +0000517 def test_findsource_code_in_linecache(self):
518 lines = ["x=1"]
519 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200520 self.assertRaises(OSError, inspect.findsource, co)
521 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000522 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200523 try:
524 self.assertEqual(inspect.findsource(co), (lines,0))
525 self.assertEqual(inspect.getsource(co), lines[0])
526 finally:
527 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000528
Ezio Melotti1b145922013-03-30 05:17:24 +0200529 def test_findsource_without_filename(self):
530 for fname in ['', '<string>']:
531 co = compile('x=1', fname, "exec")
532 self.assertRaises(IOError, inspect.findsource, co)
533 self.assertRaises(IOError, inspect.getsource, co)
534
Antoine Pitroua8723a02015-04-15 00:41:29 +0200535 def test_getsource_on_method(self):
536 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
537
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000538class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400539 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000540 self.tempdir = TESTFN + '_dir'
541 os.mkdir(self.tempdir)
542 with open(os.path.join(self.tempdir,
543 'inspect_fodder3%spy' % os.extsep), 'w') as f:
544 f.write("class X:\n pass # No EOL")
545 with DirsOnSysPath(self.tempdir):
546 import inspect_fodder3 as mod3
547 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400548 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000549
550 def tearDown(self):
551 shutil.rmtree(self.tempdir)
552
553 def test_class(self):
554 self.assertSourceEqual(self.fodderModule.X, 1, 2)
555
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100556
557class _BrokenDataDescriptor(object):
558 """
559 A broken data descriptor. See bug #1785.
560 """
561 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700562 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100563
564 def __set__(*args):
565 raise RuntimeError
566
567 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700568 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100569
570
571class _BrokenMethodDescriptor(object):
572 """
573 A broken method descriptor. See bug #1785.
574 """
575 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700576 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100577
578 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700579 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100580
581
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000582# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000583def attrs_wo_objs(cls):
584 return [t[:3] for t in inspect.classify_class_attrs(cls)]
585
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100586
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000587class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000588 def test_newstyle_mro(self):
589 # The same w/ new-class MRO.
590 class A(object): pass
591 class B(A): pass
592 class C(A): pass
593 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000594
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000595 expected = (D, B, C, A, object)
596 got = inspect.getmro(D)
597 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000598
Christian Heimes3795b532007-11-08 13:48:53 +0000599 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
600 varkw_e=None, defaults_e=None, formatted=None):
Yury Selivanov3cfec2e2015-05-22 11:38:38 -0400601 with self.assertWarns(DeprecationWarning):
602 args, varargs, varkw, defaults = inspect.getargspec(routine)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000603 self.assertEqual(args, args_e)
604 self.assertEqual(varargs, varargs_e)
605 self.assertEqual(varkw, varkw_e)
606 self.assertEqual(defaults, defaults_e)
607 if formatted is not None:
608 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
609 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000610
Christian Heimes3795b532007-11-08 13:48:53 +0000611 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
612 varkw_e=None, defaults_e=None,
613 kwonlyargs_e=[], kwonlydefaults_e=None,
614 ann_e={}, formatted=None):
615 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
616 inspect.getfullargspec(routine)
617 self.assertEqual(args, args_e)
618 self.assertEqual(varargs, varargs_e)
619 self.assertEqual(varkw, varkw_e)
620 self.assertEqual(defaults, defaults_e)
621 self.assertEqual(kwonlyargs, kwonlyargs_e)
622 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
623 self.assertEqual(ann, ann_e)
624 if formatted is not None:
625 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
626 kwonlyargs, kwonlydefaults, ann),
627 formatted)
628
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000629 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000630 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000631
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000632 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000633 ['a', 'b', 'c', 'd', 'e', 'f'],
634 'g', 'h', (3, 4, 5),
635 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000636
Christian Heimes3795b532007-11-08 13:48:53 +0000637 self.assertRaises(ValueError, self.assertArgSpecEquals,
638 mod2.keyworded, [])
639
640 self.assertRaises(ValueError, self.assertArgSpecEquals,
641 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000642 self.assertRaises(ValueError, self.assertArgSpecEquals,
643 mod2.keyword_only_arg, [])
644
Christian Heimes3795b532007-11-08 13:48:53 +0000645
646 def test_getfullargspec(self):
647 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
648 kwonlyargs_e=['arg2'],
649 kwonlydefaults_e={'arg2':1},
650 formatted='(*arg1, arg2=1)')
651
652 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000653 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000654 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000655 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
656 kwonlyargs_e=['arg'],
657 formatted='(*, arg)')
658
Yury Selivanov57d240e2014-02-19 16:27:23 -0500659 def test_argspec_api_ignores_wrapped(self):
660 # Issue 20684: low level introspection API must ignore __wrapped__
661 @functools.wraps(mod.spam)
662 def ham(x, y):
663 pass
664 # Basic check
665 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
666 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
667 self.assertFullArgSpecEquals(functools.partial(ham),
668 ['x', 'y'], formatted='(x, y)')
669 # Other variants
670 def check_method(f):
671 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
672 formatted='(self, x, y)')
673 class C:
674 @functools.wraps(mod.spam)
675 def ham(self, x, y):
676 pass
677 pham = functools.partialmethod(ham)
678 @functools.wraps(mod.spam)
679 def __call__(self, x, y):
680 pass
681 check_method(C())
682 check_method(C.ham)
683 check_method(C().ham)
684 check_method(C.pham)
685 check_method(C().pham)
686
687 class C_new:
688 @functools.wraps(mod.spam)
689 def __new__(self, x, y):
690 pass
691 check_method(C_new)
692
693 class C_init:
694 @functools.wraps(mod.spam)
695 def __init__(self, x, y):
696 pass
697 check_method(C_init)
698
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500699 def test_getfullargspec_signature_attr(self):
700 def test():
701 pass
702 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
703 test.__signature__ = inspect.Signature(parameters=(spam_param,))
704
705 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
706
Yury Selivanov4cb93912014-01-29 11:54:12 -0500707 def test_getfullargspec_signature_annos(self):
708 def test(a:'spam') -> 'ham': pass
709 spec = inspect.getfullargspec(test)
710 self.assertEqual(test.__annotations__, spec.annotations)
711
712 def test(): pass
713 spec = inspect.getfullargspec(test)
714 self.assertEqual(test.__annotations__, spec.annotations)
715
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500716 @unittest.skipIf(MISSING_C_DOCSTRINGS,
717 "Signature information for builtins requires docstrings")
718 def test_getfullargspec_builtin_methods(self):
719 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
720 args_e=['self', 'obj'], formatted='(self, obj)')
721
722 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
723 args_e=['self', 'obj'], formatted='(self, obj)')
724
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500725 self.assertFullArgSpecEquals(
726 os.stat,
727 args_e=['path'],
728 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
729 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
730 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
731
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200732 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500733 @unittest.skipIf(MISSING_C_DOCSTRINGS,
734 "Signature information for builtins requires docstrings")
735 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200736 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500737 builtin = _testcapi.docstring_with_signature_with_defaults
738 spec = inspect.getfullargspec(builtin)
739 self.assertEqual(spec.defaults[0], 'avocado')
740
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200741 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500742 @unittest.skipIf(MISSING_C_DOCSTRINGS,
743 "Signature information for builtins requires docstrings")
744 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200745 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500746 builtin = _testcapi.docstring_no_signature
747 with self.assertRaises(TypeError):
748 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000749
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000750 def test_getargspec_method(self):
751 class A(object):
752 def m(self):
753 pass
754 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000755
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000756 def test_classify_newstyle(self):
757 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000758
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000759 def s(): pass
760 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000761
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000762 def c(cls): pass
763 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000764
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000765 def getp(self): pass
766 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000767
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000768 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000769
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000770 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000771
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000772 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000773
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100774 dd = _BrokenDataDescriptor()
775 md = _BrokenMethodDescriptor()
776
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000777 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500778
779 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
780 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
781
Benjamin Peterson577473f2010-01-19 00:09:57 +0000782 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
783 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
784 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000785 self.assertIn(('m', 'method', A), attrs,
786 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000787 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
788 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100789 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
790 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000791
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000792 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000793
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000794 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000795
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000796 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000797 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
798 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
799 self.assertIn(('p', 'property', A), attrs, 'missing property')
800 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
801 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
802 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100803 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
804 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000805
806
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000807 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000808
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000809 def m(self): pass
810 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000811
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000812 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000813 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
814 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
815 self.assertIn(('p', 'property', A), attrs, 'missing property')
816 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
817 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
818 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100819 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
820 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000821
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000822 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000823
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000824 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000825
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000826 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000827 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
828 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
829 self.assertIn(('p', 'property', A), attrs, 'missing property')
830 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
831 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
832 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100833 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
834 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
835
836 def test_classify_builtin_types(self):
837 # Simple sanity check that all built-in types can have their
838 # attributes classified.
839 for name in dir(__builtins__):
840 builtin = getattr(__builtins__, name)
841 if isinstance(builtin, type):
842 inspect.classify_class_attrs(builtin)
843
Ethan Furman63c141c2013-10-18 00:27:39 -0700844 def test_classify_DynamicClassAttribute(self):
845 class Meta(type):
846 def __getattr__(self, name):
847 if name == 'ham':
848 return 'spam'
849 return super().__getattr__(name)
850 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700851 @types.DynamicClassAttribute
852 def ham(self):
853 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700854 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
855 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700856 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700857 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
858
Yury Selivanovbf341fb2015-05-21 15:41:57 -0400859 def test_classify_overrides_bool(self):
860 class NoBool(object):
861 def __eq__(self, other):
862 return NoBool()
863
864 def __bool__(self):
865 raise NotImplementedError(
866 "This object does not specify a boolean value")
867
868 class HasNB(object):
869 dd = NoBool()
870
871 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
872 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
873
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700874 def test_classify_metaclass_class_attribute(self):
875 class Meta(type):
876 fish = 'slap'
877 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200878 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700879 class Class(metaclass=Meta):
880 pass
881 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
882 self.assertIn(should_find, inspect.classify_class_attrs(Class))
883
Ethan Furman63c141c2013-10-18 00:27:39 -0700884 def test_classify_VirtualAttribute(self):
885 class Meta(type):
886 def __dir__(cls):
887 return ['__class__', '__module__', '__name__', 'BOOM']
888 def __getattr__(self, name):
889 if name =='BOOM':
890 return 42
891 return super().__getattr(name)
892 class Class(metaclass=Meta):
893 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700894 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700895 self.assertIn(should_find, inspect.classify_class_attrs(Class))
896
897 def test_classify_VirtualAttribute_multi_classes(self):
898 class Meta1(type):
899 def __dir__(cls):
900 return ['__class__', '__module__', '__name__', 'one']
901 def __getattr__(self, name):
902 if name =='one':
903 return 1
904 return super().__getattr__(name)
905 class Meta2(type):
906 def __dir__(cls):
907 return ['__class__', '__module__', '__name__', 'two']
908 def __getattr__(self, name):
909 if name =='two':
910 return 2
911 return super().__getattr__(name)
912 class Meta3(Meta1, Meta2):
913 def __dir__(cls):
914 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
915 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
916 def __getattr__(self, name):
917 if name =='three':
918 return 3
919 return super().__getattr__(name)
920 class Class1(metaclass=Meta1):
921 pass
922 class Class2(Class1, metaclass=Meta3):
923 pass
924
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700925 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
926 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
927 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700928 cca = inspect.classify_class_attrs(Class2)
929 for sf in (should_find1, should_find2, should_find3):
930 self.assertIn(sf, cca)
931
932 def test_classify_class_attrs_with_buggy_dir(self):
933 class M(type):
934 def __dir__(cls):
935 return ['__class__', '__name__', 'missing']
936 class C(metaclass=M):
937 pass
938 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
939 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700940
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100941 def test_getmembers_descriptors(self):
942 class A(object):
943 dd = _BrokenDataDescriptor()
944 md = _BrokenMethodDescriptor()
945
946 def pred_wrapper(pred):
947 # A quick'n'dirty way to discard standard attributes of new-style
948 # classes.
949 class Empty(object):
950 pass
951 def wrapped(x):
952 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
953 return False
954 return pred(x)
955 return wrapped
956
957 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
958 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
959
960 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
961 [('md', A.__dict__['md'])])
962 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
963 [('dd', A.__dict__['dd'])])
964
965 class B(A):
966 pass
967
968 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
969 [('md', A.__dict__['md'])])
970 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
971 [('dd', A.__dict__['dd'])])
972
Antoine Pitrou0c603812012-01-18 17:40:18 +0100973 def test_getmembers_method(self):
974 class B:
975 def f(self):
976 pass
977
978 self.assertIn(('f', B.f), inspect.getmembers(B))
979 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
980 b = B()
981 self.assertIn(('f', b.f), inspect.getmembers(b))
982 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
983
Ethan Furmane03ea372013-09-25 07:14:41 -0700984 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700985 class M(type):
986 def __getattr__(cls, name):
987 if name == 'eggs':
988 return 'scrambled'
989 return super().__getattr__(name)
990 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700991 @types.DynamicClassAttribute
992 def eggs(self):
993 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700994 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
995 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
996
997 def test_getmembers_with_buggy_dir(self):
998 class M(type):
999 def __dir__(cls):
1000 return ['__class__', '__name__', 'missing']
1001 class C(metaclass=M):
1002 pass
1003 attrs = [a[0] for a in inspect.getmembers(C)]
1004 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001005
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001006
Nick Coghlan2f92e542012-06-23 19:39:55 +10001007_global_ref = object()
1008class TestGetClosureVars(unittest.TestCase):
1009
1010 def test_name_resolution(self):
1011 # Basic test of the 4 different resolution mechanisms
1012 def f(nonlocal_ref):
1013 def g(local_ref):
1014 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1015 return g
1016 _arg = object()
1017 nonlocal_vars = {"nonlocal_ref": _arg}
1018 global_vars = {"_global_ref": _global_ref}
1019 builtin_vars = {"print": print}
1020 unbound_names = {"unbound_ref"}
1021 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1022 builtin_vars, unbound_names)
1023 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1024
1025 def test_generator_closure(self):
1026 def f(nonlocal_ref):
1027 def g(local_ref):
1028 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1029 yield
1030 return g
1031 _arg = object()
1032 nonlocal_vars = {"nonlocal_ref": _arg}
1033 global_vars = {"_global_ref": _global_ref}
1034 builtin_vars = {"print": print}
1035 unbound_names = {"unbound_ref"}
1036 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1037 builtin_vars, unbound_names)
1038 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1039
1040 def test_method_closure(self):
1041 class C:
1042 def f(self, nonlocal_ref):
1043 def g(local_ref):
1044 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1045 return g
1046 _arg = object()
1047 nonlocal_vars = {"nonlocal_ref": _arg}
1048 global_vars = {"_global_ref": _global_ref}
1049 builtin_vars = {"print": print}
1050 unbound_names = {"unbound_ref"}
1051 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1052 builtin_vars, unbound_names)
1053 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1054
1055 def test_nonlocal_vars(self):
1056 # More complex tests of nonlocal resolution
1057 def _nonlocal_vars(f):
1058 return inspect.getclosurevars(f).nonlocals
1059
1060 def make_adder(x):
1061 def add(y):
1062 return x + y
1063 return add
1064
1065 def curry(func, arg1):
1066 return lambda arg2: func(arg1, arg2)
1067
1068 def less_than(a, b):
1069 return a < b
1070
1071 # The infamous Y combinator.
1072 def Y(le):
1073 def g(f):
1074 return le(lambda x: f(f)(x))
1075 Y.g_ref = g
1076 return g(g)
1077
1078 def check_y_combinator(func):
1079 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1080
1081 inc = make_adder(1)
1082 add_two = make_adder(2)
1083 greater_than_five = curry(less_than, 5)
1084
1085 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1086 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1087 self.assertEqual(_nonlocal_vars(greater_than_five),
1088 {'arg1': 5, 'func': less_than})
1089 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1090 {'x': 3})
1091 Y(check_y_combinator)
1092
1093 def test_getclosurevars_empty(self):
1094 def foo(): pass
1095 _empty = inspect.ClosureVars({}, {}, {}, set())
1096 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1097 self.assertEqual(inspect.getclosurevars(foo), _empty)
1098
1099 def test_getclosurevars_error(self):
1100 class T: pass
1101 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1102 self.assertRaises(TypeError, inspect.getclosurevars, list)
1103 self.assertRaises(TypeError, inspect.getclosurevars, {})
1104
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001105 def _private_globals(self):
1106 code = """def f(): print(path)"""
1107 ns = {}
1108 exec(code, ns)
1109 return ns["f"], ns
1110
1111 def test_builtins_fallback(self):
1112 f, ns = self._private_globals()
1113 ns.pop("__builtins__", None)
1114 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1115 self.assertEqual(inspect.getclosurevars(f), expected)
1116
1117 def test_builtins_as_dict(self):
1118 f, ns = self._private_globals()
1119 ns["__builtins__"] = {"path":1}
1120 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1121 self.assertEqual(inspect.getclosurevars(f), expected)
1122
1123 def test_builtins_as_module(self):
1124 f, ns = self._private_globals()
1125 ns["__builtins__"] = os
1126 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1127 self.assertEqual(inspect.getclosurevars(f), expected)
1128
Nick Coghlan2f92e542012-06-23 19:39:55 +10001129
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001130class TestGetcallargsFunctions(unittest.TestCase):
1131
1132 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1133 locs = dict(locs or {}, func=func)
1134 r1 = eval('func(%s)' % call_params_string, None, locs)
1135 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1136 locs)
1137 self.assertEqual(r1, r2)
1138
1139 def assertEqualException(self, func, call_param_string, locs=None):
1140 locs = dict(locs or {}, func=func)
1141 try:
1142 eval('func(%s)' % call_param_string, None, locs)
1143 except Exception as e:
1144 ex1 = e
1145 else:
1146 self.fail('Exception not raised')
1147 try:
1148 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1149 locs)
1150 except Exception as e:
1151 ex2 = e
1152 else:
1153 self.fail('Exception not raised')
1154 self.assertIs(type(ex1), type(ex2))
1155 self.assertEqual(str(ex1), str(ex2))
1156 del ex1, ex2
1157
1158 def makeCallable(self, signature):
1159 """Create a function that returns its locals()"""
1160 code = "lambda %s: locals()"
1161 return eval(code % signature)
1162
1163 def test_plain(self):
1164 f = self.makeCallable('a, b=1')
1165 self.assertEqualCallArgs(f, '2')
1166 self.assertEqualCallArgs(f, '2, 3')
1167 self.assertEqualCallArgs(f, 'a=2')
1168 self.assertEqualCallArgs(f, 'b=3, a=2')
1169 self.assertEqualCallArgs(f, '2, b=3')
1170 # expand *iterable / **mapping
1171 self.assertEqualCallArgs(f, '*(2,)')
1172 self.assertEqualCallArgs(f, '*[2]')
1173 self.assertEqualCallArgs(f, '*(2, 3)')
1174 self.assertEqualCallArgs(f, '*[2, 3]')
1175 self.assertEqualCallArgs(f, '**{"a":2}')
1176 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1177 self.assertEqualCallArgs(f, '2, **{"b":3}')
1178 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1179 # expand UserList / UserDict
1180 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1181 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1182 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1183 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1184 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1185
1186 def test_varargs(self):
1187 f = self.makeCallable('a, b=1, *c')
1188 self.assertEqualCallArgs(f, '2')
1189 self.assertEqualCallArgs(f, '2, 3')
1190 self.assertEqualCallArgs(f, '2, 3, 4')
1191 self.assertEqualCallArgs(f, '*(2,3,4)')
1192 self.assertEqualCallArgs(f, '2, *[3,4]')
1193 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1194
1195 def test_varkw(self):
1196 f = self.makeCallable('a, b=1, **c')
1197 self.assertEqualCallArgs(f, 'a=2')
1198 self.assertEqualCallArgs(f, '2, b=3, c=4')
1199 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1200 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1201 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1202 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1203 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1204 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1205 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1206
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001207 def test_varkw_only(self):
1208 # issue11256:
1209 f = self.makeCallable('**c')
1210 self.assertEqualCallArgs(f, '')
1211 self.assertEqualCallArgs(f, 'a=1')
1212 self.assertEqualCallArgs(f, 'a=1, b=2')
1213 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1214 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1215 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1216
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001217 def test_keyword_only(self):
1218 f = self.makeCallable('a=3, *, c, d=2')
1219 self.assertEqualCallArgs(f, 'c=3')
1220 self.assertEqualCallArgs(f, 'c=3, a=3')
1221 self.assertEqualCallArgs(f, 'a=2, c=4')
1222 self.assertEqualCallArgs(f, '4, c=4')
1223 self.assertEqualException(f, '')
1224 self.assertEqualException(f, '3')
1225 self.assertEqualException(f, 'a=3')
1226 self.assertEqualException(f, 'd=4')
1227
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001228 f = self.makeCallable('*, c, d=2')
1229 self.assertEqualCallArgs(f, 'c=3')
1230 self.assertEqualCallArgs(f, 'c=3, d=4')
1231 self.assertEqualCallArgs(f, 'd=4, c=3')
1232
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001233 def test_multiple_features(self):
1234 f = self.makeCallable('a, b=2, *f, **g')
1235 self.assertEqualCallArgs(f, '2, 3, 7')
1236 self.assertEqualCallArgs(f, '2, 3, x=8')
1237 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1238 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1239 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1240 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1241 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1242 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1243 '(4,[5,6])]), **collections.UserDict('
1244 'y=9, z=10)')
1245
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001246 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1247 self.assertEqualCallArgs(f, '2, 3, x=8')
1248 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1249 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1250 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1251 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1252 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1253 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1254 '(4,[5,6])]), q=0, **collections.UserDict('
1255 'y=9, z=10)')
1256
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001257 def test_errors(self):
1258 f0 = self.makeCallable('')
1259 f1 = self.makeCallable('a, b')
1260 f2 = self.makeCallable('a, b=1')
1261 # f0 takes no arguments
1262 self.assertEqualException(f0, '1')
1263 self.assertEqualException(f0, 'x=1')
1264 self.assertEqualException(f0, '1,x=1')
1265 # f1 takes exactly 2 arguments
1266 self.assertEqualException(f1, '')
1267 self.assertEqualException(f1, '1')
1268 self.assertEqualException(f1, 'a=2')
1269 self.assertEqualException(f1, 'b=3')
1270 # f2 takes at least 1 argument
1271 self.assertEqualException(f2, '')
1272 self.assertEqualException(f2, 'b=3')
1273 for f in f1, f2:
1274 # f1/f2 takes exactly/at most 2 arguments
1275 self.assertEqualException(f, '2, 3, 4')
1276 self.assertEqualException(f, '1, 2, 3, a=1')
1277 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001278 # XXX: success of this one depends on dict order
1279 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001280 # f got an unexpected keyword argument
1281 self.assertEqualException(f, 'c=2')
1282 self.assertEqualException(f, '2, c=3')
1283 self.assertEqualException(f, '2, 3, c=4')
1284 self.assertEqualException(f, '2, c=4, b=3')
1285 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1286 # f got multiple values for keyword argument
1287 self.assertEqualException(f, '1, a=2')
1288 self.assertEqualException(f, '1, **{"a":2}')
1289 self.assertEqualException(f, '1, 2, b=3')
1290 # XXX: Python inconsistency
1291 # - for functions and bound methods: unexpected keyword 'c'
1292 # - for unbound methods: multiple values for keyword 'a'
1293 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001294 # issue11256:
1295 f3 = self.makeCallable('**c')
1296 self.assertEqualException(f3, '1, 2')
1297 self.assertEqualException(f3, '1, 2, a=1, b=2')
1298 f4 = self.makeCallable('*, a, b=0')
1299 self.assertEqualException(f3, '1, 2')
1300 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001301
Yury Selivanov875df202014-03-27 18:23:03 -04001302 # issue #20816: getcallargs() fails to iterate over non-existent
1303 # kwonlydefaults and raises a wrong TypeError
1304 def f5(*, a): pass
1305 with self.assertRaisesRegex(TypeError,
1306 'missing 1 required keyword-only'):
1307 inspect.getcallargs(f5)
1308
1309
Yury Selivanovdccfa132014-03-27 18:42:52 -04001310 # issue20817:
1311 def f6(a, b, c):
1312 pass
1313 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1314 inspect.getcallargs(f6)
1315
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001316class TestGetcallargsMethods(TestGetcallargsFunctions):
1317
1318 def setUp(self):
1319 class Foo(object):
1320 pass
1321 self.cls = Foo
1322 self.inst = Foo()
1323
1324 def makeCallable(self, signature):
1325 assert 'self' not in signature
1326 mk = super(TestGetcallargsMethods, self).makeCallable
1327 self.cls.method = mk('self, ' + signature)
1328 return self.inst.method
1329
1330class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1331
1332 def makeCallable(self, signature):
1333 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1334 return self.cls.method
1335
1336 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1337 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1338 *self._getAssertEqualParams(func, call_params_string, locs))
1339
1340 def assertEqualException(self, func, call_params_string, locs=None):
1341 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1342 *self._getAssertEqualParams(func, call_params_string, locs))
1343
1344 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1345 assert 'inst' not in call_params_string
1346 locs = dict(locs or {}, inst=self.inst)
1347 return (func, 'inst,' + call_params_string, locs)
1348
Michael Foord95fc51d2010-11-20 15:07:30 +00001349
1350class TestGetattrStatic(unittest.TestCase):
1351
1352 def test_basic(self):
1353 class Thing(object):
1354 x = object()
1355
1356 thing = Thing()
1357 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1358 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1359 with self.assertRaises(AttributeError):
1360 inspect.getattr_static(thing, 'y')
1361
1362 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1363
1364 def test_inherited(self):
1365 class Thing(object):
1366 x = object()
1367 class OtherThing(Thing):
1368 pass
1369
1370 something = OtherThing()
1371 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1372
1373 def test_instance_attr(self):
1374 class Thing(object):
1375 x = 2
1376 def __init__(self, x):
1377 self.x = x
1378 thing = Thing(3)
1379 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1380 del thing.x
1381 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1382
1383 def test_property(self):
1384 class Thing(object):
1385 @property
1386 def x(self):
1387 raise AttributeError("I'm pretending not to exist")
1388 thing = Thing()
1389 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1390
Ezio Melotti75cbd732011-04-28 00:59:29 +03001391 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001392 class descriptor(object):
1393 def __get__(*_):
1394 raise AttributeError("I'm pretending not to exist")
1395 desc = descriptor()
1396 class Thing(object):
1397 x = desc
1398 thing = Thing()
1399 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1400
1401 def test_classAttribute(self):
1402 class Thing(object):
1403 x = object()
1404
1405 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1406
Ethan Furmane03ea372013-09-25 07:14:41 -07001407 def test_classVirtualAttribute(self):
1408 class Thing(object):
1409 @types.DynamicClassAttribute
1410 def x(self):
1411 return self._x
1412 _x = object()
1413
1414 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1415
Michael Foord95fc51d2010-11-20 15:07:30 +00001416 def test_inherited_classattribute(self):
1417 class Thing(object):
1418 x = object()
1419 class OtherThing(Thing):
1420 pass
1421
1422 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1423
1424 def test_slots(self):
1425 class Thing(object):
1426 y = 'bar'
1427 __slots__ = ['x']
1428 def __init__(self):
1429 self.x = 'foo'
1430 thing = Thing()
1431 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1432 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1433
1434 del thing.x
1435 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1436
1437 def test_metaclass(self):
1438 class meta(type):
1439 attr = 'foo'
1440 class Thing(object, metaclass=meta):
1441 pass
1442 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1443
1444 class sub(meta):
1445 pass
1446 class OtherThing(object, metaclass=sub):
1447 x = 3
1448 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1449
1450 class OtherOtherThing(OtherThing):
1451 pass
1452 # this test is odd, but it was added as it exposed a bug
1453 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1454
1455 def test_no_dict_no_slots(self):
1456 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1457 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1458
1459 def test_no_dict_no_slots_instance_member(self):
1460 # returns descriptor
1461 with open(__file__) as handle:
1462 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1463
1464 def test_inherited_slots(self):
1465 # returns descriptor
1466 class Thing(object):
1467 __slots__ = ['x']
1468 def __init__(self):
1469 self.x = 'foo'
1470
1471 class OtherThing(Thing):
1472 pass
1473 # it would be nice if this worked...
1474 # we get the descriptor instead of the instance attribute
1475 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1476
1477 def test_descriptor(self):
1478 class descriptor(object):
1479 def __get__(self, instance, owner):
1480 return 3
1481 class Foo(object):
1482 d = descriptor()
1483
1484 foo = Foo()
1485
1486 # for a non data descriptor we return the instance attribute
1487 foo.__dict__['d'] = 1
1488 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1489
1490 # if the descriptor is a data-desciptor we should return the
1491 # descriptor
1492 descriptor.__set__ = lambda s, i, v: None
1493 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1494
1495
1496 def test_metaclass_with_descriptor(self):
1497 class descriptor(object):
1498 def __get__(self, instance, owner):
1499 return 3
1500 class meta(type):
1501 d = descriptor()
1502 class Thing(object, metaclass=meta):
1503 pass
1504 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1505
1506
Michael Foordcc7ebb82010-11-20 16:20:16 +00001507 def test_class_as_property(self):
1508 class Base(object):
1509 foo = 3
1510
1511 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001512 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001513 @property
1514 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001515 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001516 return object
1517
Michael Foord35184ed2010-11-20 16:58:30 +00001518 instance = Something()
1519 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1520 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001521 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1522
Michael Foorde5162652010-11-20 16:40:44 +00001523 def test_mro_as_property(self):
1524 class Meta(type):
1525 @property
1526 def __mro__(self):
1527 return (object,)
1528
1529 class Base(object):
1530 foo = 3
1531
1532 class Something(Base, metaclass=Meta):
1533 pass
1534
1535 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1536 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1537
Michael Foorddcebe0f2011-03-15 19:20:44 -04001538 def test_dict_as_property(self):
1539 test = self
1540 test.called = False
1541
1542 class Foo(dict):
1543 a = 3
1544 @property
1545 def __dict__(self):
1546 test.called = True
1547 return {}
1548
1549 foo = Foo()
1550 foo.a = 4
1551 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1552 self.assertFalse(test.called)
1553
1554 def test_custom_object_dict(self):
1555 test = self
1556 test.called = False
1557
1558 class Custom(dict):
1559 def get(self, key, default=None):
1560 test.called = True
1561 super().get(key, default)
1562
1563 class Foo(object):
1564 a = 3
1565 foo = Foo()
1566 foo.__dict__ = Custom()
1567 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1568 self.assertFalse(test.called)
1569
1570 def test_metaclass_dict_as_property(self):
1571 class Meta(type):
1572 @property
1573 def __dict__(self):
1574 self.executed = True
1575
1576 class Thing(metaclass=Meta):
1577 executed = False
1578
1579 def __init__(self):
1580 self.spam = 42
1581
1582 instance = Thing()
1583 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1584 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001585
Michael Foorda51623b2011-12-18 22:01:40 +00001586 def test_module(self):
1587 sentinel = object()
1588 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1589 sentinel)
1590
Michael Foord3ba95f82011-12-22 01:13:37 +00001591 def test_metaclass_with_metaclass_with_dict_as_property(self):
1592 class MetaMeta(type):
1593 @property
1594 def __dict__(self):
1595 self.executed = True
1596 return dict(spam=42)
1597
1598 class Meta(type, metaclass=MetaMeta):
1599 executed = False
1600
1601 class Thing(metaclass=Meta):
1602 pass
1603
1604 with self.assertRaises(AttributeError):
1605 inspect.getattr_static(Thing, "spam")
1606 self.assertFalse(Thing.executed)
1607
Nick Coghlane0f04652010-11-21 03:44:04 +00001608class TestGetGeneratorState(unittest.TestCase):
1609
1610 def setUp(self):
1611 def number_generator():
1612 for number in range(5):
1613 yield number
1614 self.generator = number_generator()
1615
1616 def _generatorstate(self):
1617 return inspect.getgeneratorstate(self.generator)
1618
1619 def test_created(self):
1620 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1621
1622 def test_suspended(self):
1623 next(self.generator)
1624 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1625
1626 def test_closed_after_exhaustion(self):
1627 for i in self.generator:
1628 pass
1629 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1630
1631 def test_closed_after_immediate_exception(self):
1632 with self.assertRaises(RuntimeError):
1633 self.generator.throw(RuntimeError)
1634 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1635
1636 def test_running(self):
1637 # As mentioned on issue #10220, checking for the RUNNING state only
1638 # makes sense inside the generator itself.
1639 # The following generator checks for this by using the closure's
1640 # reference to self and the generator state checking helper method
1641 def running_check_generator():
1642 for number in range(5):
1643 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1644 yield number
1645 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1646 self.generator = running_check_generator()
1647 # Running up to the first yield
1648 next(self.generator)
1649 # Running after the first yield
1650 next(self.generator)
1651
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001652 def test_easy_debugging(self):
1653 # repr() and str() of a generator state should contain the state name
1654 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1655 for name in names:
1656 state = getattr(inspect, name)
1657 self.assertIn(name, repr(state))
1658 self.assertIn(name, str(state))
1659
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001660 def test_getgeneratorlocals(self):
1661 def each(lst, a=None):
1662 b=(1, 2, 3)
1663 for v in lst:
1664 if v == 3:
1665 c = 12
1666 yield v
1667
1668 numbers = each([1, 2, 3])
1669 self.assertEqual(inspect.getgeneratorlocals(numbers),
1670 {'a': None, 'lst': [1, 2, 3]})
1671 next(numbers)
1672 self.assertEqual(inspect.getgeneratorlocals(numbers),
1673 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1674 'b': (1, 2, 3)})
1675 next(numbers)
1676 self.assertEqual(inspect.getgeneratorlocals(numbers),
1677 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1678 'b': (1, 2, 3)})
1679 next(numbers)
1680 self.assertEqual(inspect.getgeneratorlocals(numbers),
1681 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1682 'b': (1, 2, 3), 'c': 12})
1683 try:
1684 next(numbers)
1685 except StopIteration:
1686 pass
1687 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1688
1689 def test_getgeneratorlocals_empty(self):
1690 def yield_one():
1691 yield 1
1692 one = yield_one()
1693 self.assertEqual(inspect.getgeneratorlocals(one), {})
1694 try:
1695 next(one)
1696 except StopIteration:
1697 pass
1698 self.assertEqual(inspect.getgeneratorlocals(one), {})
1699
1700 def test_getgeneratorlocals_error(self):
1701 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1702 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1703 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1704 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1705
Nick Coghlane0f04652010-11-21 03:44:04 +00001706
Yury Selivanov5376ba92015-06-22 12:19:30 -04001707class TestGetCoroutineState(unittest.TestCase):
1708
1709 def setUp(self):
1710 @types.coroutine
1711 def number_coroutine():
1712 for number in range(5):
1713 yield number
1714 async def coroutine():
1715 await number_coroutine()
1716 self.coroutine = coroutine()
1717
1718 def tearDown(self):
1719 self.coroutine.close()
1720
1721 def _coroutinestate(self):
1722 return inspect.getcoroutinestate(self.coroutine)
1723
1724 def test_created(self):
1725 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1726
1727 def test_suspended(self):
1728 self.coroutine.send(None)
1729 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1730
1731 def test_closed_after_exhaustion(self):
1732 while True:
1733 try:
1734 self.coroutine.send(None)
1735 except StopIteration:
1736 break
1737
1738 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1739
1740 def test_closed_after_immediate_exception(self):
1741 with self.assertRaises(RuntimeError):
1742 self.coroutine.throw(RuntimeError)
1743 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1744
1745 def test_easy_debugging(self):
1746 # repr() and str() of a coroutine state should contain the state name
1747 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1748 for name in names:
1749 state = getattr(inspect, name)
1750 self.assertIn(name, repr(state))
1751 self.assertIn(name, str(state))
1752
1753 def test_getcoroutinelocals(self):
1754 @types.coroutine
1755 def gencoro():
1756 yield
1757
1758 gencoro = gencoro()
1759 async def func(a=None):
1760 b = 'spam'
1761 await gencoro
1762
1763 coro = func()
1764 self.assertEqual(inspect.getcoroutinelocals(coro),
1765 {'a': None, 'gencoro': gencoro})
1766 coro.send(None)
1767 self.assertEqual(inspect.getcoroutinelocals(coro),
1768 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
1769
1770
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001771class MySignature(inspect.Signature):
1772 # Top-level to make it picklable;
1773 # used in test_signature_object_pickle
1774 pass
1775
1776class MyParameter(inspect.Parameter):
1777 # Top-level to make it picklable;
1778 # used in test_signature_object_pickle
1779 pass
1780
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001781
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001782
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001783class TestSignatureObject(unittest.TestCase):
1784 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04001785 def signature(func, **kw):
1786 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001787 return (tuple((param.name,
1788 (... if param.default is param.empty else param.default),
1789 (... if param.annotation is param.empty
1790 else param.annotation),
1791 str(param.kind).lower())
1792 for param in sig.parameters.values()),
1793 (... if sig.return_annotation is sig.empty
1794 else sig.return_annotation))
1795
1796 def test_signature_object(self):
1797 S = inspect.Signature
1798 P = inspect.Parameter
1799
1800 self.assertEqual(str(S()), '()')
1801
Yury Selivanov07a9e452014-01-29 10:58:16 -05001802 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001803 pass
1804 sig = inspect.signature(test)
1805 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001806 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001807 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001808 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001809 args = sig.parameters['args']
1810 ko = sig.parameters['ko']
1811 kwargs = sig.parameters['kwargs']
1812
1813 S((po, pk, args, ko, kwargs))
1814
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001815 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001816 S((pk, po, 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((po, args, pk, 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((args, po, 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((po, pk, args, kwargs, ko))
1826
1827 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001828 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001829 S((po, pk, args, kwargs2, ko))
1830
Yury Selivanov07a9e452014-01-29 10:58:16 -05001831 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1832 S((pod, po))
1833
1834 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1835 S((po, pkd, pk))
1836
1837 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1838 S((pkd, pk))
1839
Yury Selivanov374375d2014-03-27 12:41:53 -04001840 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04001841 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04001842
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001843 def test_signature_object_pickle(self):
1844 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1845 foo_partial = functools.partial(foo, a=1)
1846
1847 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001848
1849 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1850 with self.subTest(pickle_ver=ver, subclass=False):
1851 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1852 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001853
1854 # Test that basic sub-classing works
1855 sig = inspect.signature(foo)
1856 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1857 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1858 mysig = MySignature().replace(parameters=myparams.values(),
1859 return_annotation=sig.return_annotation)
1860 self.assertTrue(isinstance(mysig, MySignature))
1861 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1862
1863 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1864 with self.subTest(pickle_ver=ver, subclass=True):
1865 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1866 self.assertEqual(mysig, sig_pickled)
1867 self.assertTrue(isinstance(sig_pickled, MySignature))
1868 self.assertTrue(isinstance(sig_pickled.parameters['z'],
1869 MyParameter))
1870
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001871 def test_signature_immutability(self):
1872 def test(a):
1873 pass
1874 sig = inspect.signature(test)
1875
1876 with self.assertRaises(AttributeError):
1877 sig.foo = 'bar'
1878
1879 with self.assertRaises(TypeError):
1880 sig.parameters['a'] = None
1881
1882 def test_signature_on_noarg(self):
1883 def test():
1884 pass
1885 self.assertEqual(self.signature(test), ((), ...))
1886
1887 def test_signature_on_wargs(self):
1888 def test(a, b:'foo') -> 123:
1889 pass
1890 self.assertEqual(self.signature(test),
1891 ((('a', ..., ..., "positional_or_keyword"),
1892 ('b', ..., 'foo', "positional_or_keyword")),
1893 123))
1894
1895 def test_signature_on_wkwonly(self):
1896 def test(*, a:float, b:str) -> int:
1897 pass
1898 self.assertEqual(self.signature(test),
1899 ((('a', ..., float, "keyword_only"),
1900 ('b', ..., str, "keyword_only")),
1901 int))
1902
1903 def test_signature_on_complex_args(self):
1904 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1905 pass
1906 self.assertEqual(self.signature(test),
1907 ((('a', ..., ..., "positional_or_keyword"),
1908 ('b', 10, 'foo', "positional_or_keyword"),
1909 ('args', ..., 'bar', "var_positional"),
1910 ('spam', ..., 'baz', "keyword_only"),
1911 ('ham', 123, ..., "keyword_only"),
1912 ('kwargs', ..., int, "var_keyword")),
1913 ...))
1914
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001915 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001916 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1917 "Signature information for builtins requires docstrings")
1918 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001919 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001920
Larry Hastings5c661892014-01-24 06:17:25 -08001921 def test_unbound_method(o):
1922 """Use this to test unbound methods (things that should have a self)"""
1923 signature = inspect.signature(o)
1924 self.assertTrue(isinstance(signature, inspect.Signature))
1925 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1926 return signature
1927
1928 def test_callable(o):
1929 """Use this to test bound methods or normal callables (things that don't expect self)"""
1930 signature = inspect.signature(o)
1931 self.assertTrue(isinstance(signature, inspect.Signature))
1932 if signature.parameters:
1933 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1934 return signature
1935
1936 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001937 def p(name): return signature.parameters[name].default
1938 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001939 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001940 self.assertEqual(p('d'), 3.14)
1941 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001942 self.assertEqual(p('n'), None)
1943 self.assertEqual(p('t'), True)
1944 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001945 self.assertEqual(p('local'), 3)
1946 self.assertEqual(p('sys'), sys.maxsize)
1947 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001948
Larry Hastings5c661892014-01-24 06:17:25 -08001949 test_callable(object)
1950
1951 # normal method
1952 # (PyMethodDescr_Type, "method_descriptor")
1953 test_unbound_method(_pickle.Pickler.dump)
1954 d = _pickle.Pickler(io.StringIO())
1955 test_callable(d.dump)
1956
1957 # static method
1958 test_callable(str.maketrans)
1959 test_callable('abc'.maketrans)
1960
1961 # class method
1962 test_callable(dict.fromkeys)
1963 test_callable({}.fromkeys)
1964
1965 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1966 test_unbound_method(type.__call__)
1967 test_unbound_method(int.__add__)
1968 test_callable((3).__add__)
1969
1970 # _PyMethodWrapper_Type
1971 # support for 'method-wrapper'
1972 test_callable(min.__call__)
1973
Larry Hastings2623c8c2014-02-08 22:15:29 -08001974 # This doesn't work now.
1975 # (We don't have a valid signature for "type" in 3.4)
1976 with self.assertRaisesRegex(ValueError, "no signature found"):
1977 class ThisWorksNow:
1978 __call__ = type
1979 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001980
Yury Selivanov056e2652014-03-02 12:25:27 -05001981 # Regression test for issue #20786
1982 test_unbound_method(dict.__delitem__)
1983 test_unbound_method(property.__delete__)
1984
Zachary Ware8ef887c2015-04-13 18:22:35 -05001985 # Regression test for issue #20586
1986 test_callable(_testcapi.docstring_with_signature_but_no_doc)
1987
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001988 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001989 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1990 "Signature information for builtins requires docstrings")
1991 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001992 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001993 func = _testcapi.docstring_with_signature_with_defaults
1994
1995 def decorator(func):
1996 @functools.wraps(func)
1997 def wrapper(*args, **kwargs) -> int:
1998 return func(*args, **kwargs)
1999 return wrapper
2000
2001 decorated_func = decorator(func)
2002
2003 self.assertEqual(inspect.signature(func),
2004 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002005
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002006 def wrapper_like(*args, **kwargs) -> int: pass
2007 self.assertEqual(inspect.signature(decorated_func,
2008 follow_wrapped=False),
2009 inspect.signature(wrapper_like))
2010
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002011 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002012 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002013 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002014 with self.assertRaisesRegex(ValueError,
2015 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002016 inspect.signature(_testcapi.docstring_no_signature)
2017
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002018 with self.assertRaisesRegex(ValueError,
2019 'no signature found for builtin'):
2020 inspect.signature(str)
2021
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002022 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002023 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002024 inspect.signature(42)
2025
Yury Selivanov63da7c72014-01-31 14:48:37 -05002026 def test_signature_from_functionlike_object(self):
2027 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2028 pass
2029
2030 class funclike:
2031 # Has to be callable, and have correct
2032 # __code__, __annotations__, __defaults__, __name__,
2033 # and __kwdefaults__ attributes
2034
2035 def __init__(self, func):
2036 self.__name__ = func.__name__
2037 self.__code__ = func.__code__
2038 self.__annotations__ = func.__annotations__
2039 self.__defaults__ = func.__defaults__
2040 self.__kwdefaults__ = func.__kwdefaults__
2041 self.func = func
2042
2043 def __call__(self, *args, **kwargs):
2044 return self.func(*args, **kwargs)
2045
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002046 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002047
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002048 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002049 self.assertEqual(sig_funclike, sig_func)
2050
2051 sig_funclike = inspect.signature(funclike(func))
2052 self.assertEqual(sig_funclike, sig_func)
2053
2054 # If object is not a duck type of function, then
2055 # signature will try to get a signature for its '__call__'
2056 # method
2057 fl = funclike(func)
2058 del fl.__defaults__
2059 self.assertEqual(self.signature(fl),
2060 ((('args', ..., ..., "var_positional"),
2061 ('kwargs', ..., ..., "var_keyword")),
2062 ...))
2063
Yury Selivanova773de02014-02-21 18:30:53 -05002064 # Test with cython-like builtins:
2065 _orig_isdesc = inspect.ismethoddescriptor
2066 def _isdesc(obj):
2067 if hasattr(obj, '_builtinmock'):
2068 return True
2069 return _orig_isdesc(obj)
2070
2071 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2072 builtin_func = funclike(func)
2073 # Make sure that our mock setup is working
2074 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2075 builtin_func._builtinmock = True
2076 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2077 self.assertEqual(inspect.signature(builtin_func), sig_func)
2078
Yury Selivanov63da7c72014-01-31 14:48:37 -05002079 def test_signature_functionlike_class(self):
2080 # We only want to duck type function-like objects,
2081 # not classes.
2082
2083 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2084 pass
2085
2086 class funclike:
2087 def __init__(self, marker):
2088 pass
2089
2090 __name__ = func.__name__
2091 __code__ = func.__code__
2092 __annotations__ = func.__annotations__
2093 __defaults__ = func.__defaults__
2094 __kwdefaults__ = func.__kwdefaults__
2095
Yury Selivanov63da7c72014-01-31 14:48:37 -05002096 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2097
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002098 def test_signature_on_method(self):
2099 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002100 def __init__(*args):
2101 pass
2102 def m1(self, arg1, arg2=1) -> int:
2103 pass
2104 def m2(*args):
2105 pass
2106 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002107 pass
2108
Yury Selivanov62560fb2014-01-28 12:26:24 -05002109 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002110 ((('arg1', ..., ..., "positional_or_keyword"),
2111 ('arg2', 1, ..., "positional_or_keyword")),
2112 int))
2113
Yury Selivanov62560fb2014-01-28 12:26:24 -05002114 self.assertEqual(self.signature(Test().m2),
2115 ((('args', ..., ..., "var_positional"),),
2116 ...))
2117
2118 self.assertEqual(self.signature(Test),
2119 ((('args', ..., ..., "var_positional"),),
2120 ...))
2121
2122 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2123 self.signature(Test())
2124
Yury Selivanov46c759d2015-05-27 21:56:53 -04002125 def test_signature_wrapped_bound_method(self):
2126 # Issue 24298
2127 class Test:
2128 def m1(self, arg1, arg2=1) -> int:
2129 pass
2130 @functools.wraps(Test().m1)
2131 def m1d(*args, **kwargs):
2132 pass
2133 self.assertEqual(self.signature(m1d),
2134 ((('arg1', ..., ..., "positional_or_keyword"),
2135 ('arg2', 1, ..., "positional_or_keyword")),
2136 int))
2137
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002138 def test_signature_on_classmethod(self):
2139 class Test:
2140 @classmethod
2141 def foo(cls, arg1, *, arg2=1):
2142 pass
2143
2144 meth = Test().foo
2145 self.assertEqual(self.signature(meth),
2146 ((('arg1', ..., ..., "positional_or_keyword"),
2147 ('arg2', 1, ..., "keyword_only")),
2148 ...))
2149
2150 meth = Test.foo
2151 self.assertEqual(self.signature(meth),
2152 ((('arg1', ..., ..., "positional_or_keyword"),
2153 ('arg2', 1, ..., "keyword_only")),
2154 ...))
2155
2156 def test_signature_on_staticmethod(self):
2157 class Test:
2158 @staticmethod
2159 def foo(cls, *, arg):
2160 pass
2161
2162 meth = Test().foo
2163 self.assertEqual(self.signature(meth),
2164 ((('cls', ..., ..., "positional_or_keyword"),
2165 ('arg', ..., ..., "keyword_only")),
2166 ...))
2167
2168 meth = Test.foo
2169 self.assertEqual(self.signature(meth),
2170 ((('cls', ..., ..., "positional_or_keyword"),
2171 ('arg', ..., ..., "keyword_only")),
2172 ...))
2173
2174 def test_signature_on_partial(self):
2175 from functools import partial
2176
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002177 Parameter = inspect.Parameter
2178
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002179 def test():
2180 pass
2181
2182 self.assertEqual(self.signature(partial(test)), ((), ...))
2183
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002184 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002185 inspect.signature(partial(test, 1))
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, a=1))
2189
2190 def test(a, b, *, c, d):
2191 pass
2192
2193 self.assertEqual(self.signature(partial(test)),
2194 ((('a', ..., ..., "positional_or_keyword"),
2195 ('b', ..., ..., "positional_or_keyword"),
2196 ('c', ..., ..., "keyword_only"),
2197 ('d', ..., ..., "keyword_only")),
2198 ...))
2199
2200 self.assertEqual(self.signature(partial(test, 1)),
2201 ((('b', ..., ..., "positional_or_keyword"),
2202 ('c', ..., ..., "keyword_only"),
2203 ('d', ..., ..., "keyword_only")),
2204 ...))
2205
2206 self.assertEqual(self.signature(partial(test, 1, c=2)),
2207 ((('b', ..., ..., "positional_or_keyword"),
2208 ('c', 2, ..., "keyword_only"),
2209 ('d', ..., ..., "keyword_only")),
2210 ...))
2211
2212 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2213 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002214 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002215 ('c', 2, ..., "keyword_only"),
2216 ('d', ..., ..., "keyword_only")),
2217 ...))
2218
2219 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002220 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002221 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002222 ('d', ..., ..., "keyword_only")),
2223 ...))
2224
2225 self.assertEqual(self.signature(partial(test, a=1)),
2226 ((('a', 1, ..., "keyword_only"),
2227 ('b', ..., ..., "keyword_only"),
2228 ('c', ..., ..., "keyword_only"),
2229 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002230 ...))
2231
2232 def test(a, *args, b, **kwargs):
2233 pass
2234
2235 self.assertEqual(self.signature(partial(test, 1)),
2236 ((('args', ..., ..., "var_positional"),
2237 ('b', ..., ..., "keyword_only"),
2238 ('kwargs', ..., ..., "var_keyword")),
2239 ...))
2240
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002241 self.assertEqual(self.signature(partial(test, a=1)),
2242 ((('a', 1, ..., "keyword_only"),
2243 ('b', ..., ..., "keyword_only"),
2244 ('kwargs', ..., ..., "var_keyword")),
2245 ...))
2246
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002247 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2248 ((('args', ..., ..., "var_positional"),
2249 ('b', ..., ..., "keyword_only"),
2250 ('kwargs', ..., ..., "var_keyword")),
2251 ...))
2252
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002253 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2254 ((('args', ..., ..., "var_positional"),
2255 ('b', ..., ..., "keyword_only"),
2256 ('kwargs', ..., ..., "var_keyword")),
2257 ...))
2258
2259 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2260 ((('args', ..., ..., "var_positional"),
2261 ('b', 0, ..., "keyword_only"),
2262 ('kwargs', ..., ..., "var_keyword")),
2263 ...))
2264
2265 self.assertEqual(self.signature(partial(test, b=0)),
2266 ((('a', ..., ..., "positional_or_keyword"),
2267 ('args', ..., ..., "var_positional"),
2268 ('b', 0, ..., "keyword_only"),
2269 ('kwargs', ..., ..., "var_keyword")),
2270 ...))
2271
2272 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2273 ((('a', ..., ..., "positional_or_keyword"),
2274 ('args', ..., ..., "var_positional"),
2275 ('b', 0, ..., "keyword_only"),
2276 ('kwargs', ..., ..., "var_keyword")),
2277 ...))
2278
2279 def test(a, b, c:int) -> 42:
2280 pass
2281
2282 sig = test.__signature__ = inspect.signature(test)
2283
2284 self.assertEqual(self.signature(partial(partial(test, 1))),
2285 ((('b', ..., ..., "positional_or_keyword"),
2286 ('c', ..., int, "positional_or_keyword")),
2287 42))
2288
2289 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2290 ((('c', ..., int, "positional_or_keyword"),),
2291 42))
2292
2293 psig = inspect.signature(partial(partial(test, 1), 2))
2294
2295 def foo(a):
2296 return a
2297 _foo = partial(partial(foo, a=10), a=20)
2298 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002299 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002300 ...))
2301 # check that we don't have any side-effects in signature(),
2302 # and the partial object is still functioning
2303 self.assertEqual(_foo(), 20)
2304
2305 def foo(a, b, c):
2306 return a, b, c
2307 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002308
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002309 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002310 ((('b', 30, ..., "keyword_only"),
2311 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002312 ...))
2313 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002314
2315 def foo(a, b, c, *, d):
2316 return a, b, c, d
2317 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2318 self.assertEqual(self.signature(_foo),
2319 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002320 ('b', 10, ..., "keyword_only"),
2321 ('c', 20, ..., "keyword_only"),
2322 ('d', 30, ..., "keyword_only"),
2323 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002324 ...))
2325 ba = inspect.signature(_foo).bind(a=200, b=11)
2326 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2327
2328 def foo(a=1, b=2, c=3):
2329 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002330 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2331
2332 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002333 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002334
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002335 ba = inspect.signature(_foo).bind(11, 12)
2336 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002337
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002338 ba = inspect.signature(_foo).bind(11, b=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(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002342 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2343
2344 _foo = partial(_foo, b=10, c=20)
2345 ba = inspect.signature(_foo).bind(12)
2346 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2347
2348
2349 def foo(a, b, c, d, **kwargs):
2350 pass
2351 sig = inspect.signature(foo)
2352 params = sig.parameters.copy()
2353 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2354 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2355 foo.__signature__ = inspect.Signature(params.values())
2356 sig = inspect.signature(foo)
2357 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2358
2359 self.assertEqual(self.signature(partial(foo, 1)),
2360 ((('b', ..., ..., 'positional_only'),
2361 ('c', ..., ..., 'positional_or_keyword'),
2362 ('d', ..., ..., 'positional_or_keyword'),
2363 ('kwargs', ..., ..., 'var_keyword')),
2364 ...))
2365
2366 self.assertEqual(self.signature(partial(foo, 1, 2)),
2367 ((('c', ..., ..., 'positional_or_keyword'),
2368 ('d', ..., ..., 'positional_or_keyword'),
2369 ('kwargs', ..., ..., 'var_keyword')),
2370 ...))
2371
2372 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2373 ((('d', ..., ..., 'positional_or_keyword'),
2374 ('kwargs', ..., ..., 'var_keyword')),
2375 ...))
2376
2377 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2378 ((('c', 3, ..., 'keyword_only'),
2379 ('d', ..., ..., 'keyword_only'),
2380 ('kwargs', ..., ..., 'var_keyword')),
2381 ...))
2382
2383 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2384 ((('b', ..., ..., 'positional_only'),
2385 ('c', 3, ..., 'keyword_only'),
2386 ('d', ..., ..., 'keyword_only'),
2387 ('kwargs', ..., ..., 'var_keyword')),
2388 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002389
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002390 def test_signature_on_partialmethod(self):
2391 from functools import partialmethod
2392
2393 class Spam:
2394 def test():
2395 pass
2396 ham = partialmethod(test)
2397
2398 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2399 inspect.signature(Spam.ham)
2400
2401 class Spam:
2402 def test(it, a, *, c) -> 'spam':
2403 pass
2404 ham = partialmethod(test, c=1)
2405
2406 self.assertEqual(self.signature(Spam.ham),
2407 ((('it', ..., ..., 'positional_or_keyword'),
2408 ('a', ..., ..., 'positional_or_keyword'),
2409 ('c', 1, ..., 'keyword_only')),
2410 'spam'))
2411
2412 self.assertEqual(self.signature(Spam().ham),
2413 ((('a', ..., ..., 'positional_or_keyword'),
2414 ('c', 1, ..., 'keyword_only')),
2415 'spam'))
2416
Yury Selivanov0486f812014-01-29 12:18:59 -05002417 def test_signature_on_fake_partialmethod(self):
2418 def foo(a): pass
2419 foo._partialmethod = 'spam'
2420 self.assertEqual(str(inspect.signature(foo)), '(a)')
2421
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002422 def test_signature_on_decorated(self):
2423 import functools
2424
2425 def decorator(func):
2426 @functools.wraps(func)
2427 def wrapper(*args, **kwargs) -> int:
2428 return func(*args, **kwargs)
2429 return wrapper
2430
2431 class Foo:
2432 @decorator
2433 def bar(self, a, b):
2434 pass
2435
2436 self.assertEqual(self.signature(Foo.bar),
2437 ((('self', ..., ..., "positional_or_keyword"),
2438 ('a', ..., ..., "positional_or_keyword"),
2439 ('b', ..., ..., "positional_or_keyword")),
2440 ...))
2441
2442 self.assertEqual(self.signature(Foo().bar),
2443 ((('a', ..., ..., "positional_or_keyword"),
2444 ('b', ..., ..., "positional_or_keyword")),
2445 ...))
2446
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002447 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2448 ((('args', ..., ..., "var_positional"),
2449 ('kwargs', ..., ..., "var_keyword")),
2450 ...)) # functools.wraps will copy __annotations__
2451 # from "func" to "wrapper", hence no
2452 # return_annotation
2453
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002454 # Test that we handle method wrappers correctly
2455 def decorator(func):
2456 @functools.wraps(func)
2457 def wrapper(*args, **kwargs) -> int:
2458 return func(42, *args, **kwargs)
2459 sig = inspect.signature(func)
2460 new_params = tuple(sig.parameters.values())[1:]
2461 wrapper.__signature__ = sig.replace(parameters=new_params)
2462 return wrapper
2463
2464 class Foo:
2465 @decorator
2466 def __call__(self, a, b):
2467 pass
2468
2469 self.assertEqual(self.signature(Foo.__call__),
2470 ((('a', ..., ..., "positional_or_keyword"),
2471 ('b', ..., ..., "positional_or_keyword")),
2472 ...))
2473
2474 self.assertEqual(self.signature(Foo().__call__),
2475 ((('b', ..., ..., "positional_or_keyword"),),
2476 ...))
2477
Nick Coghlane8c45d62013-07-28 20:00:01 +10002478 # Test we handle __signature__ partway down the wrapper stack
2479 def wrapped_foo_call():
2480 pass
2481 wrapped_foo_call.__wrapped__ = Foo.__call__
2482
2483 self.assertEqual(self.signature(wrapped_foo_call),
2484 ((('a', ..., ..., "positional_or_keyword"),
2485 ('b', ..., ..., "positional_or_keyword")),
2486 ...))
2487
2488
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002489 def test_signature_on_class(self):
2490 class C:
2491 def __init__(self, a):
2492 pass
2493
2494 self.assertEqual(self.signature(C),
2495 ((('a', ..., ..., "positional_or_keyword"),),
2496 ...))
2497
2498 class CM(type):
2499 def __call__(cls, a):
2500 pass
2501 class C(metaclass=CM):
2502 def __init__(self, b):
2503 pass
2504
2505 self.assertEqual(self.signature(C),
2506 ((('a', ..., ..., "positional_or_keyword"),),
2507 ...))
2508
2509 class CM(type):
2510 def __new__(mcls, name, bases, dct, *, foo=1):
2511 return super().__new__(mcls, name, bases, dct)
2512 class C(metaclass=CM):
2513 def __init__(self, b):
2514 pass
2515
2516 self.assertEqual(self.signature(C),
2517 ((('b', ..., ..., "positional_or_keyword"),),
2518 ...))
2519
2520 self.assertEqual(self.signature(CM),
2521 ((('name', ..., ..., "positional_or_keyword"),
2522 ('bases', ..., ..., "positional_or_keyword"),
2523 ('dct', ..., ..., "positional_or_keyword"),
2524 ('foo', 1, ..., "keyword_only")),
2525 ...))
2526
2527 class CMM(type):
2528 def __new__(mcls, name, bases, dct, *, foo=1):
2529 return super().__new__(mcls, name, bases, dct)
2530 def __call__(cls, nm, bs, dt):
2531 return type(nm, bs, dt)
2532 class CM(type, metaclass=CMM):
2533 def __new__(mcls, name, bases, dct, *, bar=2):
2534 return super().__new__(mcls, name, bases, dct)
2535 class C(metaclass=CM):
2536 def __init__(self, b):
2537 pass
2538
2539 self.assertEqual(self.signature(CMM),
2540 ((('name', ..., ..., "positional_or_keyword"),
2541 ('bases', ..., ..., "positional_or_keyword"),
2542 ('dct', ..., ..., "positional_or_keyword"),
2543 ('foo', 1, ..., "keyword_only")),
2544 ...))
2545
2546 self.assertEqual(self.signature(CM),
2547 ((('nm', ..., ..., "positional_or_keyword"),
2548 ('bs', ..., ..., "positional_or_keyword"),
2549 ('dt', ..., ..., "positional_or_keyword")),
2550 ...))
2551
2552 self.assertEqual(self.signature(C),
2553 ((('b', ..., ..., "positional_or_keyword"),),
2554 ...))
2555
2556 class CM(type):
2557 def __init__(cls, name, bases, dct, *, bar=2):
2558 return super().__init__(name, bases, dct)
2559 class C(metaclass=CM):
2560 def __init__(self, b):
2561 pass
2562
2563 self.assertEqual(self.signature(CM),
2564 ((('name', ..., ..., "positional_or_keyword"),
2565 ('bases', ..., ..., "positional_or_keyword"),
2566 ('dct', ..., ..., "positional_or_keyword"),
2567 ('bar', 2, ..., "keyword_only")),
2568 ...))
2569
Yury Selivanov145dff82014-02-01 13:49:29 -05002570 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2571 "Signature information for builtins requires docstrings")
2572 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002573 # Test classes without user-defined __init__ or __new__
2574 class C: pass
2575 self.assertEqual(str(inspect.signature(C)), '()')
2576 class D(C): pass
2577 self.assertEqual(str(inspect.signature(D)), '()')
2578
2579 # Test meta-classes without user-defined __init__ or __new__
2580 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002581 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002582 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2583 self.assertEqual(inspect.signature(C), None)
2584 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2585 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002586
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002587 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2588 "Signature information for builtins requires docstrings")
2589 def test_signature_on_builtin_class(self):
2590 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2591 '(file, protocol=None, fix_imports=True)')
2592
2593 class P(_pickle.Pickler): pass
2594 class EmptyTrait: pass
2595 class P2(EmptyTrait, P): pass
2596 self.assertEqual(str(inspect.signature(P)),
2597 '(file, protocol=None, fix_imports=True)')
2598 self.assertEqual(str(inspect.signature(P2)),
2599 '(file, protocol=None, fix_imports=True)')
2600
2601 class P3(P2):
2602 def __init__(self, spam):
2603 pass
2604 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2605
2606 class MetaP(type):
2607 def __call__(cls, foo, bar):
2608 pass
2609 class P4(P2, metaclass=MetaP):
2610 pass
2611 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2612
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002613 def test_signature_on_callable_objects(self):
2614 class Foo:
2615 def __call__(self, a):
2616 pass
2617
2618 self.assertEqual(self.signature(Foo()),
2619 ((('a', ..., ..., "positional_or_keyword"),),
2620 ...))
2621
2622 class Spam:
2623 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002624 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002625 inspect.signature(Spam())
2626
2627 class Bar(Spam, Foo):
2628 pass
2629
2630 self.assertEqual(self.signature(Bar()),
2631 ((('a', ..., ..., "positional_or_keyword"),),
2632 ...))
2633
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002634 class Wrapped:
2635 pass
2636 Wrapped.__wrapped__ = lambda a: None
2637 self.assertEqual(self.signature(Wrapped),
2638 ((('a', ..., ..., "positional_or_keyword"),),
2639 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002640 # wrapper loop:
2641 Wrapped.__wrapped__ = Wrapped
2642 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2643 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002644
2645 def test_signature_on_lambdas(self):
2646 self.assertEqual(self.signature((lambda a=10: a)),
2647 ((('a', 10, ..., "positional_or_keyword"),),
2648 ...))
2649
2650 def test_signature_equality(self):
2651 def foo(a, *, b:int) -> float: pass
2652 self.assertNotEqual(inspect.signature(foo), 42)
2653
2654 def bar(a, *, b:int) -> float: pass
2655 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002656 self.assertEqual(
2657 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002658
2659 def bar(a, *, b:int) -> int: pass
2660 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002661 self.assertNotEqual(
2662 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002663
2664 def bar(a, *, b:int): pass
2665 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002666 self.assertNotEqual(
2667 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002668
2669 def bar(a, *, b:int=42) -> float: pass
2670 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002671 self.assertNotEqual(
2672 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002673
2674 def bar(a, *, c) -> float: pass
2675 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002676 self.assertNotEqual(
2677 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002678
2679 def bar(a, b:int) -> float: pass
2680 self.assertNotEqual(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 def spam(b:int, a) -> float: pass
2684 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002685 self.assertNotEqual(
2686 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002687
2688 def foo(*, a, b, c): pass
2689 def bar(*, c, b, a): pass
2690 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002691 self.assertEqual(
2692 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002693
2694 def foo(*, a=1, b, c): pass
2695 def bar(*, c, b, a=1): pass
2696 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002697 self.assertEqual(
2698 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002699
2700 def foo(pos, *, a=1, b, c): pass
2701 def bar(pos, *, c, b, a=1): pass
2702 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002703 self.assertEqual(
2704 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002705
2706 def foo(pos, *, a, b, c): pass
2707 def bar(pos, *, c, b, a=1): pass
2708 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002709 self.assertNotEqual(
2710 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002711
2712 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2713 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2714 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002715 self.assertEqual(
2716 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002717
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002718 def test_signature_hashable(self):
2719 S = inspect.Signature
2720 P = inspect.Parameter
2721
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002722 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002723 foo_sig = inspect.signature(foo)
2724
2725 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2726
2727 self.assertEqual(hash(foo_sig), hash(manual_sig))
2728 self.assertNotEqual(hash(foo_sig),
2729 hash(manual_sig.replace(return_annotation='spam')))
2730
2731 def bar(a) -> 1: pass
2732 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2733
2734 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002735 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002736 hash(inspect.signature(foo))
2737
2738 def foo(a) -> {}: pass
2739 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2740 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002741
2742 def test_signature_str(self):
2743 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2744 pass
2745 self.assertEqual(str(inspect.signature(foo)),
2746 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2747
2748 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2749 pass
2750 self.assertEqual(str(inspect.signature(foo)),
2751 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2752
2753 def foo():
2754 pass
2755 self.assertEqual(str(inspect.signature(foo)), '()')
2756
2757 def test_signature_str_positional_only(self):
2758 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002759 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002760
2761 def test(a_po, *, b, **kwargs):
2762 return a_po, kwargs
2763
2764 sig = inspect.signature(test)
2765 new_params = list(sig.parameters.values())
2766 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2767 test.__signature__ = sig.replace(parameters=new_params)
2768
2769 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002770 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002771
Yury Selivanov2393dca2014-01-27 15:07:58 -05002772 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2773 '(foo, /)')
2774
2775 self.assertEqual(str(S(parameters=[
2776 P('foo', P.POSITIONAL_ONLY),
2777 P('bar', P.VAR_KEYWORD)])),
2778 '(foo, /, **bar)')
2779
2780 self.assertEqual(str(S(parameters=[
2781 P('foo', P.POSITIONAL_ONLY),
2782 P('bar', P.VAR_POSITIONAL)])),
2783 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002784
2785 def test_signature_replace_anno(self):
2786 def test() -> 42:
2787 pass
2788
2789 sig = inspect.signature(test)
2790 sig = sig.replace(return_annotation=None)
2791 self.assertIs(sig.return_annotation, None)
2792 sig = sig.replace(return_annotation=sig.empty)
2793 self.assertIs(sig.return_annotation, sig.empty)
2794 sig = sig.replace(return_annotation=42)
2795 self.assertEqual(sig.return_annotation, 42)
2796 self.assertEqual(sig, inspect.signature(test))
2797
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002798 def test_signature_on_mangled_parameters(self):
2799 class Spam:
2800 def foo(self, __p1:1=2, *, __p2:2=3):
2801 pass
2802 class Ham(Spam):
2803 pass
2804
2805 self.assertEqual(self.signature(Spam.foo),
2806 ((('self', ..., ..., "positional_or_keyword"),
2807 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2808 ('_Spam__p2', 3, 2, "keyword_only")),
2809 ...))
2810
2811 self.assertEqual(self.signature(Spam.foo),
2812 self.signature(Ham.foo))
2813
Yury Selivanovda396452014-03-27 12:09:24 -04002814 def test_signature_from_callable_python_obj(self):
2815 class MySignature(inspect.Signature): pass
2816 def foo(a, *, b:1): pass
2817 foo_sig = MySignature.from_callable(foo)
2818 self.assertTrue(isinstance(foo_sig, MySignature))
2819
2820 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2821 "Signature information for builtins requires docstrings")
2822 def test_signature_from_callable_builtin_obj(self):
2823 class MySignature(inspect.Signature): pass
2824 sig = MySignature.from_callable(_pickle.Pickler)
2825 self.assertTrue(isinstance(sig, MySignature))
2826
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002827
2828class TestParameterObject(unittest.TestCase):
2829 def test_signature_parameter_kinds(self):
2830 P = inspect.Parameter
2831 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2832 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2833
2834 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2835 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2836
2837 def test_signature_parameter_object(self):
2838 p = inspect.Parameter('foo', default=10,
2839 kind=inspect.Parameter.POSITIONAL_ONLY)
2840 self.assertEqual(p.name, 'foo')
2841 self.assertEqual(p.default, 10)
2842 self.assertIs(p.annotation, p.empty)
2843 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2844
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002845 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002846 inspect.Parameter('foo', default=10, kind='123')
2847
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002848 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002849 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2850
Yury Selivanov2393dca2014-01-27 15:07:58 -05002851 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002852 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2853
Yury Selivanov2393dca2014-01-27 15:07:58 -05002854 with self.assertRaisesRegex(ValueError,
2855 'is not a valid parameter name'):
2856 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2857
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002858 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002859 inspect.Parameter('a', default=42,
2860 kind=inspect.Parameter.VAR_KEYWORD)
2861
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002862 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002863 inspect.Parameter('a', default=42,
2864 kind=inspect.Parameter.VAR_POSITIONAL)
2865
2866 p = inspect.Parameter('a', default=42,
2867 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002868 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002869 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2870
2871 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04002872 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002873
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002874 def test_signature_parameter_hashable(self):
2875 P = inspect.Parameter
2876 foo = P('foo', kind=P.POSITIONAL_ONLY)
2877 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
2878 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
2879 default=42)))
2880 self.assertNotEqual(hash(foo),
2881 hash(foo.replace(kind=P.VAR_POSITIONAL)))
2882
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002883 def test_signature_parameter_equality(self):
2884 P = inspect.Parameter
2885 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2886
2887 self.assertEqual(p, p)
2888 self.assertNotEqual(p, 42)
2889
2890 self.assertEqual(p, P('foo', default=42,
2891 kind=inspect.Parameter.KEYWORD_ONLY))
2892
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002893 def test_signature_parameter_replace(self):
2894 p = inspect.Parameter('foo', default=42,
2895 kind=inspect.Parameter.KEYWORD_ONLY)
2896
2897 self.assertIsNot(p, p.replace())
2898 self.assertEqual(p, p.replace())
2899
2900 p2 = p.replace(annotation=1)
2901 self.assertEqual(p2.annotation, 1)
2902 p2 = p2.replace(annotation=p2.empty)
2903 self.assertEqual(p, p2)
2904
2905 p2 = p2.replace(name='bar')
2906 self.assertEqual(p2.name, 'bar')
2907 self.assertNotEqual(p2, p)
2908
Yury Selivanov2393dca2014-01-27 15:07:58 -05002909 with self.assertRaisesRegex(ValueError,
2910 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002911 p2 = p2.replace(name=p2.empty)
2912
2913 p2 = p2.replace(name='foo', default=None)
2914 self.assertIs(p2.default, None)
2915 self.assertNotEqual(p2, p)
2916
2917 p2 = p2.replace(name='foo', default=p2.empty)
2918 self.assertIs(p2.default, p2.empty)
2919
2920
2921 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2922 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2923 self.assertNotEqual(p2, p)
2924
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002925 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002926 p2 = p2.replace(kind=p2.empty)
2927
2928 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2929 self.assertEqual(p2, p)
2930
2931 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002932 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2933 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002934
2935 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002936 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002937
2938 with self.assertRaises(AttributeError):
2939 p.foo = 'bar'
2940
2941 with self.assertRaises(AttributeError):
2942 p.kind = 123
2943
2944
2945class TestSignatureBind(unittest.TestCase):
2946 @staticmethod
2947 def call(func, *args, **kwargs):
2948 sig = inspect.signature(func)
2949 ba = sig.bind(*args, **kwargs)
2950 return func(*ba.args, **ba.kwargs)
2951
2952 def test_signature_bind_empty(self):
2953 def test():
2954 return 42
2955
2956 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002957 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002958 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002959 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002960 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04002961 with self.assertRaisesRegex(
2962 TypeError, "got an unexpected keyword argument 'spam'"):
2963
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002964 self.call(test, spam=1)
2965
2966 def test_signature_bind_var(self):
2967 def test(*args, **kwargs):
2968 return args, kwargs
2969
2970 self.assertEqual(self.call(test), ((), {}))
2971 self.assertEqual(self.call(test, 1), ((1,), {}))
2972 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2973 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2974 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2975 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2976 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2977 ((1, 2), {'foo': 'bar'}))
2978
2979 def test_signature_bind_just_args(self):
2980 def test(a, b, c):
2981 return a, b, c
2982
2983 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2984
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002985 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002986 self.call(test, 1, 2, 3, 4)
2987
Yury Selivanov86872752015-05-19 00:27:49 -04002988 with self.assertRaisesRegex(TypeError,
2989 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002990 self.call(test, 1)
2991
Yury Selivanov86872752015-05-19 00:27:49 -04002992 with self.assertRaisesRegex(TypeError,
2993 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002994 self.call(test)
2995
2996 def test(a, b, c=10):
2997 return a, b, c
2998 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2999 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3000
3001 def test(a=1, b=2, c=3):
3002 return a, b, c
3003 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3004 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3005 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3006
3007 def test_signature_bind_varargs_order(self):
3008 def test(*args):
3009 return args
3010
3011 self.assertEqual(self.call(test), ())
3012 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3013
3014 def test_signature_bind_args_and_varargs(self):
3015 def test(a, b, c=3, *args):
3016 return a, b, c, args
3017
3018 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3019 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3020 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3021 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3022
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003023 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003024 "multiple values for argument 'c'"):
3025 self.call(test, 1, 2, 3, c=4)
3026
3027 def test_signature_bind_just_kwargs(self):
3028 def test(**kwargs):
3029 return kwargs
3030
3031 self.assertEqual(self.call(test), {})
3032 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3033 {'foo': 'bar', 'spam': 'ham'})
3034
3035 def test_signature_bind_args_and_kwargs(self):
3036 def test(a, b, c=3, **kwargs):
3037 return a, b, c, kwargs
3038
3039 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3040 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3041 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3042 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3043 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3044 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3045 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3046 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3047 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3048 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3049 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3050 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3051 (1, 2, 4, {'foo': 'bar'}))
3052 self.assertEqual(self.call(test, c=5, a=4, b=3),
3053 (4, 3, 5, {}))
3054
3055 def test_signature_bind_kwonly(self):
3056 def test(*, foo):
3057 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003058 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003059 'too many positional arguments'):
3060 self.call(test, 1)
3061 self.assertEqual(self.call(test, foo=1), 1)
3062
3063 def test(a, *, foo=1, bar):
3064 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003065 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003066 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003067 self.call(test, 1)
3068
3069 def test(foo, *, bar):
3070 return foo, bar
3071 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3072 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3073
Yury Selivanov86872752015-05-19 00:27:49 -04003074 with self.assertRaisesRegex(
3075 TypeError, "got an unexpected keyword argument 'spam'"):
3076
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003077 self.call(test, bar=2, foo=1, spam=10)
3078
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003079 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003080 'too many positional arguments'):
3081 self.call(test, 1, 2)
3082
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003083 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003084 'too many positional arguments'):
3085 self.call(test, 1, 2, bar=2)
3086
Yury Selivanov86872752015-05-19 00:27:49 -04003087 with self.assertRaisesRegex(
3088 TypeError, "got an unexpected keyword argument 'spam'"):
3089
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003090 self.call(test, 1, bar=2, spam='ham')
3091
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003092 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003093 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003094 self.call(test, 1)
3095
3096 def test(foo, *, bar, **bin):
3097 return foo, bar, bin
3098 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3099 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3100 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3101 (1, 2, {'spam': 'ham'}))
3102 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3103 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003104 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003105 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003106 self.call(test, spam='ham', bar=2)
3107 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3108 (1, 2, {'bin': 1, 'spam': 10}))
3109
3110 def test_signature_bind_arguments(self):
3111 def test(a, *args, b, z=100, **kwargs):
3112 pass
3113 sig = inspect.signature(test)
3114 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3115 # we won't have 'z' argument in the bound arguments object, as we didn't
3116 # pass it to the 'bind'
3117 self.assertEqual(tuple(ba.arguments.items()),
3118 (('a', 10), ('args', (20,)), ('b', 30),
3119 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3120 self.assertEqual(ba.kwargs,
3121 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3122 self.assertEqual(ba.args, (10, 20))
3123
3124 def test_signature_bind_positional_only(self):
3125 P = inspect.Parameter
3126
3127 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3128 return a_po, b_po, c_po, foo, bar, kwargs
3129
3130 sig = inspect.signature(test)
3131 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3132 for name in ('a_po', 'b_po', 'c_po'):
3133 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3134 new_sig = sig.replace(parameters=new_params.values())
3135 test.__signature__ = new_sig
3136
3137 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3138 (1, 2, 4, 5, 6, {}))
3139
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003140 self.assertEqual(self.call(test, 1, 2),
3141 (1, 2, 3, 42, 50, {}))
3142
3143 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3144 (1, 2, 3, 4, 5, {}))
3145
3146 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3147 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3148
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003149 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003150 self.call(test, 1, 2, c_po=4)
3151
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003152 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003153 self.call(test, a_po=1, b_po=2)
3154
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003155 def test_signature_bind_with_self_arg(self):
3156 # Issue #17071: one of the parameters is named "self
3157 def test(a, self, b):
3158 pass
3159 sig = inspect.signature(test)
3160 ba = sig.bind(1, 2, 3)
3161 self.assertEqual(ba.args, (1, 2, 3))
3162 ba = sig.bind(1, self=2, b=3)
3163 self.assertEqual(ba.args, (1, 2, 3))
3164
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003165 def test_signature_bind_vararg_name(self):
3166 def test(a, *args):
3167 return a, args
3168 sig = inspect.signature(test)
3169
Yury Selivanov86872752015-05-19 00:27:49 -04003170 with self.assertRaisesRegex(
3171 TypeError, "got an unexpected keyword argument 'args'"):
3172
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003173 sig.bind(a=0, args=1)
3174
3175 def test(*args, **kwargs):
3176 return args, kwargs
3177 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3178
3179 sig = inspect.signature(test)
3180 ba = sig.bind(args=1)
3181 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3182
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003183
3184class TestBoundArguments(unittest.TestCase):
3185 def test_signature_bound_arguments_unhashable(self):
3186 def foo(a): pass
3187 ba = inspect.signature(foo).bind(1)
3188
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003189 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003190 hash(ba)
3191
3192 def test_signature_bound_arguments_equality(self):
3193 def foo(a): pass
3194 ba = inspect.signature(foo).bind(1)
3195 self.assertEqual(ba, ba)
3196
3197 ba2 = inspect.signature(foo).bind(1)
3198 self.assertEqual(ba, ba2)
3199
3200 ba3 = inspect.signature(foo).bind(2)
3201 self.assertNotEqual(ba, ba3)
3202 ba3.arguments['a'] = 1
3203 self.assertEqual(ba, ba3)
3204
3205 def bar(b): pass
3206 ba4 = inspect.signature(bar).bind(1)
3207 self.assertNotEqual(ba, ba4)
3208
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003209 def foo(*, a, b): pass
3210 sig = inspect.signature(foo)
3211 ba1 = sig.bind(a=1, b=2)
3212 ba2 = sig.bind(b=2, a=1)
3213 self.assertEqual(ba1, ba2)
3214
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003215 def test_signature_bound_arguments_pickle(self):
3216 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3217 sig = inspect.signature(foo)
3218 ba = sig.bind(20, 30, z={})
3219
3220 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3221 with self.subTest(pickle_ver=ver):
3222 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3223 self.assertEqual(ba, ba_pickled)
3224
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003225 def test_signature_bound_arguments_repr(self):
3226 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3227 sig = inspect.signature(foo)
3228 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003229 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003230
Yury Selivanovb907a512015-05-16 13:45:09 -04003231 def test_signature_bound_arguments_apply_defaults(self):
3232 def foo(a, b=1, *args, c:1={}, **kw): pass
3233 sig = inspect.signature(foo)
3234
3235 ba = sig.bind(20)
3236 ba.apply_defaults()
3237 self.assertEqual(
3238 list(ba.arguments.items()),
3239 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3240
3241 # Make sure that we preserve the order:
3242 # i.e. 'c' should be *before* 'kw'.
3243 ba = sig.bind(10, 20, 30, d=1)
3244 ba.apply_defaults()
3245 self.assertEqual(
3246 list(ba.arguments.items()),
3247 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3248
3249 # Make sure that BoundArguments produced by bind_partial()
3250 # are supported.
3251 def foo(a, b): pass
3252 sig = inspect.signature(foo)
3253 ba = sig.bind_partial(20)
3254 ba.apply_defaults()
3255 self.assertEqual(
3256 list(ba.arguments.items()),
3257 [('a', 20)])
3258
3259 # Test no args
3260 def foo(): pass
3261 sig = inspect.signature(foo)
3262 ba = sig.bind()
3263 ba.apply_defaults()
3264 self.assertEqual(list(ba.arguments.items()), [])
3265
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003266
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003267class TestSignaturePrivateHelpers(unittest.TestCase):
3268 def test_signature_get_bound_param(self):
3269 getter = inspect._signature_get_bound_param
3270
3271 self.assertEqual(getter('($self)'), 'self')
3272 self.assertEqual(getter('($self, obj)'), 'self')
3273 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3274
Larry Hastings2623c8c2014-02-08 22:15:29 -08003275 def _strip_non_python_syntax(self, input,
3276 clean_signature, self_parameter, last_positional_only):
3277 computed_clean_signature, \
3278 computed_self_parameter, \
3279 computed_last_positional_only = \
3280 inspect._signature_strip_non_python_syntax(input)
3281 self.assertEqual(computed_clean_signature, clean_signature)
3282 self.assertEqual(computed_self_parameter, self_parameter)
3283 self.assertEqual(computed_last_positional_only, last_positional_only)
3284
3285 def test_signature_strip_non_python_syntax(self):
3286 self._strip_non_python_syntax(
3287 "($module, /, path, mode, *, dir_fd=None, " +
3288 "effective_ids=False,\n follow_symlinks=True)",
3289 "(module, path, mode, *, dir_fd=None, " +
3290 "effective_ids=False, follow_symlinks=True)",
3291 0,
3292 0)
3293
3294 self._strip_non_python_syntax(
3295 "($module, word, salt, /)",
3296 "(module, word, salt)",
3297 0,
3298 2)
3299
3300 self._strip_non_python_syntax(
3301 "(x, y=None, z=None, /)",
3302 "(x, y=None, z=None)",
3303 None,
3304 2)
3305
3306 self._strip_non_python_syntax(
3307 "(x, y=None, z=None)",
3308 "(x, y=None, z=None)",
3309 None,
3310 None)
3311
3312 self._strip_non_python_syntax(
3313 "(x,\n y=None,\n z = None )",
3314 "(x, y=None, z=None)",
3315 None,
3316 None)
3317
3318 self._strip_non_python_syntax(
3319 "",
3320 "",
3321 None,
3322 None)
3323
3324 self._strip_non_python_syntax(
3325 None,
3326 None,
3327 None,
3328 None)
3329
Nick Coghlan9c680b02015-04-13 12:54:54 -04003330class TestSignatureDefinitions(unittest.TestCase):
3331 # This test case provides a home for checking that particular APIs
3332 # have signatures available for introspection
3333
3334 @cpython_only
3335 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3336 "Signature information for builtins requires docstrings")
3337 def test_builtins_have_signatures(self):
3338 # This checks all builtin callables in CPython have signatures
3339 # A few have signatures Signature can't yet handle, so we skip those
3340 # since they will have to wait until PEP 457 adds the required
3341 # introspection support to the inspect module
3342 # Some others also haven't been converted yet for various other
3343 # reasons, so we also skip those for the time being, but design
3344 # the test to fail in order to indicate when it needs to be
3345 # updated.
3346 no_signature = set()
3347 # These need PEP 457 groups
3348 needs_groups = {"range", "slice", "dir", "getattr",
3349 "next", "iter", "vars"}
3350 no_signature |= needs_groups
3351 # These need PEP 457 groups or a signature change to accept None
3352 needs_semantic_update = {"round"}
3353 no_signature |= needs_semantic_update
3354 # These need *args support in Argument Clinic
3355 needs_varargs = {"min", "max", "print", "__build_class__"}
3356 no_signature |= needs_varargs
3357 # These simply weren't covered in the initial AC conversion
3358 # for builtin callables
3359 not_converted_yet = {"open", "__import__"}
3360 no_signature |= not_converted_yet
3361 # These builtin types are expected to provide introspection info
3362 types_with_signatures = set()
3363 # Check the signatures we expect to be there
3364 ns = vars(builtins)
3365 for name, obj in sorted(ns.items()):
3366 if not callable(obj):
3367 continue
3368 # The builtin types haven't been converted to AC yet
3369 if isinstance(obj, type) and (name not in types_with_signatures):
3370 # Note that this also skips all the exception types
3371 no_signature.add(name)
3372 if (name in no_signature):
3373 # Not yet converted
3374 continue
3375 with self.subTest(builtin=name):
3376 self.assertIsNotNone(inspect.signature(obj))
3377 # Check callables that haven't been converted don't claim a signature
3378 # This ensures this test will start failing as more signatures are
3379 # added, so the affected items can be moved into the scope of the
3380 # regression test above
3381 for name in no_signature:
3382 with self.subTest(builtin=name):
3383 self.assertIsNone(obj.__text_signature__)
3384
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003385
Nick Coghlane8c45d62013-07-28 20:00:01 +10003386class TestUnwrap(unittest.TestCase):
3387
3388 def test_unwrap_one(self):
3389 def func(a, b):
3390 return a + b
3391 wrapper = functools.lru_cache(maxsize=20)(func)
3392 self.assertIs(inspect.unwrap(wrapper), func)
3393
3394 def test_unwrap_several(self):
3395 def func(a, b):
3396 return a + b
3397 wrapper = func
3398 for __ in range(10):
3399 @functools.wraps(wrapper)
3400 def wrapper():
3401 pass
3402 self.assertIsNot(wrapper.__wrapped__, func)
3403 self.assertIs(inspect.unwrap(wrapper), func)
3404
3405 def test_stop(self):
3406 def func1(a, b):
3407 return a + b
3408 @functools.wraps(func1)
3409 def func2():
3410 pass
3411 @functools.wraps(func2)
3412 def wrapper():
3413 pass
3414 func2.stop_here = 1
3415 unwrapped = inspect.unwrap(wrapper,
3416 stop=(lambda f: hasattr(f, "stop_here")))
3417 self.assertIs(unwrapped, func2)
3418
3419 def test_cycle(self):
3420 def func1(): pass
3421 func1.__wrapped__ = func1
3422 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3423 inspect.unwrap(func1)
3424
3425 def func2(): pass
3426 func2.__wrapped__ = func1
3427 func1.__wrapped__ = func2
3428 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3429 inspect.unwrap(func1)
3430 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3431 inspect.unwrap(func2)
3432
3433 def test_unhashable(self):
3434 def func(): pass
3435 func.__wrapped__ = None
3436 class C:
3437 __hash__ = None
3438 __wrapped__ = func
3439 self.assertIsNone(inspect.unwrap(C()))
3440
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003441class TestMain(unittest.TestCase):
3442 def test_only_source(self):
3443 module = importlib.import_module('unittest')
3444 rc, out, err = assert_python_ok('-m', 'inspect',
3445 'unittest')
3446 lines = out.decode().splitlines()
3447 # ignore the final newline
3448 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3449 self.assertEqual(err, b'')
3450
Yury Selivanov42407ab2014-06-23 10:23:50 -07003451 def test_custom_getattr(self):
3452 def foo():
3453 pass
3454 foo.__signature__ = 42
3455 with self.assertRaises(TypeError):
3456 inspect.signature(foo)
3457
Brett Cannon634a8fc2013-10-02 10:25:42 -04003458 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003459 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003460 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003461 rc, out, err = assert_python_ok('-m', 'inspect',
3462 'concurrent.futures:ThreadPoolExecutor')
3463 lines = out.decode().splitlines()
3464 # ignore the final newline
3465 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003466 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003467 self.assertEqual(err, b'')
3468
3469 def test_builtins(self):
3470 module = importlib.import_module('unittest')
3471 _, out, err = assert_python_failure('-m', 'inspect',
3472 'sys')
3473 lines = err.decode().splitlines()
3474 self.assertEqual(lines, ["Can't get info for builtin modules."])
3475
3476 def test_details(self):
3477 module = importlib.import_module('unittest')
3478 rc, out, err = assert_python_ok('-m', 'inspect',
3479 'unittest', '--details')
3480 output = out.decode()
3481 # Just a quick sanity check on the output
3482 self.assertIn(module.__name__, output)
3483 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003484 if not sys.flags.optimize:
3485 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003486 self.assertEqual(err, b'')
3487
3488
Yury Selivanovef1e7502014-12-08 16:05:34 -05003489class TestReload(unittest.TestCase):
3490
3491 src_before = textwrap.dedent("""\
3492def foo():
3493 print("Bla")
3494 """)
3495
3496 src_after = textwrap.dedent("""\
3497def foo():
3498 print("Oh no!")
3499 """)
3500
3501 def assertInspectEqual(self, path, source):
3502 inspected_src = inspect.getsource(source)
3503 with open(path) as src:
3504 self.assertEqual(
3505 src.read().splitlines(True),
3506 inspected_src.splitlines(True)
3507 )
3508
3509 def test_getsource_reload(self):
3510 # see issue 1218234
3511 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3512 module = importlib.import_module(name)
3513 self.assertInspectEqual(path, module)
3514 with open(path, 'w') as src:
3515 src.write(self.src_after)
3516 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003517
Nick Coghlane8c45d62013-07-28 20:00:01 +10003518
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003519def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003520 run_unittest(
3521 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3522 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3523 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003524 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003525 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003526 TestBoundArguments, TestSignaturePrivateHelpers,
3527 TestSignatureDefinitions,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003528 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
3529 TestGetCoroutineState
Michael Foord95fc51d2010-11-20 15:07:30 +00003530 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003531
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003532if __name__ == "__main__":
3533 test_main()