blob: 3481a57ec833607b8d9a9e1044edb1573976e3e5 [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 shutil
14import sys
15import types
Yury Selivanovef1e7502014-12-08 16:05:34 -050016import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080017import unicodedata
18import unittest
Yury Selivanova773de02014-02-21 18:30:53 -050019import unittest.mock
Yury Selivanov75445082015-05-11 22:57:16 -040020import warnings
Larry Hastings5c661892014-01-24 06:17:25 -080021
Brett Cannon634a8fc2013-10-02 10:25:42 -040022try:
23 from concurrent.futures import ThreadPoolExecutor
24except ImportError:
25 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000026
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020027from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Nick Coghlanf9e227e2014-08-17 14:01:19 +100028from test.support import MISSING_C_DOCSTRINGS, cpython_only
Berker Peksagce643912015-05-06 06:33:17 +030029from test.support.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000030from test import inspect_fodder as mod
31from test import inspect_fodder2 as mod2
Victor Stinner9def2842016-01-18 12:15:08 +010032from test import support
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,
Berker Peksagfa3922c2015-07-31 04:11:29 +030041# getclasstree, getargvalues, formatargspec, formatargvalues,
Christian Heimes7131fd92008-02-19 14:21:46 +000042# 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
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000058git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000059
larryhastingsf36ba122018-01-28 11:13:09 -080060
61def signatures_with_lexicographic_keyword_only_parameters():
62 """
63 Yields a whole bunch of functions with only keyword-only parameters,
64 where those parameters are always in lexicographically sorted order.
65 """
66 parameters = ['a', 'bar', 'c', 'delta', 'ephraim', 'magical', 'yoyo', 'z']
67 for i in range(1, 2**len(parameters)):
68 p = []
69 bit = 1
70 for j in range(len(parameters)):
71 if i & (bit << j):
72 p.append(parameters[j])
73 fn_text = "def foo(*, " + ", ".join(p) + "): pass"
74 symbols = {}
75 exec(fn_text, symbols, symbols)
76 yield symbols['foo']
77
78
79def unsorted_keyword_only_parameters_fn(*, throw, out, the, baby, with_,
80 the_, bathwater):
81 pass
82
83unsorted_keyword_only_parameters = 'throw out the baby with_ the_ bathwater'.split()
84
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000085class IsTestBase(unittest.TestCase):
86 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
87 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000088 inspect.ismodule, inspect.istraceback,
Yury Selivanov75445082015-05-11 22:57:16 -040089 inspect.isgenerator, inspect.isgeneratorfunction,
Yury Selivanoveb636452016-09-08 22:01:51 -070090 inspect.iscoroutine, inspect.iscoroutinefunction,
91 inspect.isasyncgen, inspect.isasyncgenfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000092
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000093 def istest(self, predicate, exp):
94 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000095 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000096
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000097 for other in self.predicates - set([predicate]):
Yury Selivanov75445082015-05-11 22:57:16 -040098 if (predicate == inspect.isgeneratorfunction or \
Yury Selivanoveb636452016-09-08 22:01:51 -070099 predicate == inspect.isasyncgenfunction or \
Yury Selivanov75445082015-05-11 22:57:16 -0400100 predicate == inspect.iscoroutinefunction) and \
Christian Heimes7131fd92008-02-19 14:21:46 +0000101 other == inspect.isfunction:
102 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000103 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000104
Christian Heimes7131fd92008-02-19 14:21:46 +0000105def generator_function_example(self):
106 for i in range(2):
107 yield i
108
Yury Selivanoveb636452016-09-08 22:01:51 -0700109async def async_generator_function_example(self):
110 async for i in range(2):
111 yield i
112
Yury Selivanov75445082015-05-11 22:57:16 -0400113async def coroutine_function_example(self):
114 return 'spam'
115
116@types.coroutine
117def gen_coroutine_function_example(self):
118 yield
119 return 'spam'
120
Serhiy Storchaka3018cc42015-07-18 23:19:05 +0300121class EqualsToAll:
122 def __eq__(self, other):
123 return True
Yury Selivanova5d63dd2014-03-27 11:31:43 -0400124
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000125class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +0000126
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000127 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200128 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000129 self.istest(inspect.isbuiltin, 'sys.exit')
130 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +0000131 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200132 try:
133 1/0
134 except:
135 tb = sys.exc_info()[2]
136 self.istest(inspect.isframe, 'tb.tb_frame')
137 self.istest(inspect.istraceback, 'tb')
138 if hasattr(types, 'GetSetDescriptorType'):
139 self.istest(inspect.isgetsetdescriptor,
140 'type(tb.tb_frame).f_locals')
141 else:
142 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
143 finally:
144 # Clear traceback and all the frames and local variables hanging to it.
145 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000146 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000147 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000148 self.istest(inspect.ismethod, 'git.argue')
149 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000150 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000151 self.istest(inspect.isgenerator, '(x for x in range(2))')
152 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanoveb636452016-09-08 22:01:51 -0700153 self.istest(inspect.isasyncgen,
154 'async_generator_function_example(1)')
155 self.istest(inspect.isasyncgenfunction,
156 'async_generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400157
158 with warnings.catch_warnings():
159 warnings.simplefilter("ignore")
160 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
161 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
162
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000163 if hasattr(types, 'MemberDescriptorType'):
164 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
165 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000166 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000167
Yury Selivanov75445082015-05-11 22:57:16 -0400168 def test_iscoroutine(self):
169 gen_coro = gen_coroutine_function_example(1)
170 coro = coroutine_function_example(1)
171
Yury Selivanov5376ba92015-06-22 12:19:30 -0400172 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400173 inspect.iscoroutinefunction(gen_coroutine_function_example))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400174 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400175
176 self.assertTrue(
177 inspect.isgeneratorfunction(gen_coroutine_function_example))
178 self.assertTrue(inspect.isgenerator(gen_coro))
179
180 self.assertTrue(
181 inspect.iscoroutinefunction(coroutine_function_example))
182 self.assertTrue(inspect.iscoroutine(coro))
183
184 self.assertFalse(
185 inspect.isgeneratorfunction(coroutine_function_example))
186 self.assertFalse(inspect.isgenerator(coro))
187
188 coro.close(); gen_coro.close() # silence warnings
189
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400190 def test_isawaitable(self):
191 def gen(): yield
192 self.assertFalse(inspect.isawaitable(gen()))
193
194 coro = coroutine_function_example(1)
195 gen_coro = gen_coroutine_function_example(1)
196
197 self.assertTrue(inspect.isawaitable(coro))
198 self.assertTrue(inspect.isawaitable(gen_coro))
199
200 class Future:
201 def __await__():
202 pass
203 self.assertTrue(inspect.isawaitable(Future()))
204 self.assertFalse(inspect.isawaitable(Future))
205
206 class NotFuture: pass
207 not_fut = NotFuture()
208 not_fut.__await__ = lambda: None
209 self.assertFalse(inspect.isawaitable(not_fut))
210
211 coro.close(); gen_coro.close() # silence warnings
212
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000213 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000214 self.assertTrue(inspect.isroutine(mod.spam))
215 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000216
Benjamin Petersonc4656002009-01-17 22:41:18 +0000217 def test_isclass(self):
218 self.istest(inspect.isclass, 'mod.StupidGit')
219 self.assertTrue(inspect.isclass(list))
220
221 class CustomGetattr(object):
222 def __getattr__(self, attr):
223 return None
224 self.assertFalse(inspect.isclass(CustomGetattr()))
225
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000226 def test_get_slot_members(self):
227 class C(object):
228 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000229 x = C()
230 x.a = 42
231 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000232 self.assertIn('a', members)
233 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000234
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000235 def test_isabstract(self):
236 from abc import ABCMeta, abstractmethod
237
238 class AbstractClassExample(metaclass=ABCMeta):
239
240 @abstractmethod
241 def foo(self):
242 pass
243
244 class ClassExample(AbstractClassExample):
245 def foo(self):
246 pass
247
248 a = ClassExample()
249
250 # Test general behaviour.
251 self.assertTrue(inspect.isabstract(AbstractClassExample))
252 self.assertFalse(inspect.isabstract(ClassExample))
253 self.assertFalse(inspect.isabstract(a))
254 self.assertFalse(inspect.isabstract(int))
255 self.assertFalse(inspect.isabstract(5))
256
Natefcfe80e2017-04-24 10:06:15 -0700257 def test_isabstract_during_init_subclass(self):
258 from abc import ABCMeta, abstractmethod
259 isabstract_checks = []
260 class AbstractChecker(metaclass=ABCMeta):
261 def __init_subclass__(cls):
262 isabstract_checks.append(inspect.isabstract(cls))
263 class AbstractClassExample(AbstractChecker):
264 @abstractmethod
265 def foo(self):
266 pass
267 class ClassExample(AbstractClassExample):
268 def foo(self):
269 pass
270 self.assertEqual(isabstract_checks, [True, False])
271
272 isabstract_checks.clear()
273 class AbstractChild(AbstractClassExample):
274 pass
275 class AbstractGrandchild(AbstractChild):
276 pass
277 class ConcreteGrandchild(ClassExample):
278 pass
279 self.assertEqual(isabstract_checks, [True, True, False])
280
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000281
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000282class TestInterpreterStack(IsTestBase):
283 def __init__(self, *args, **kwargs):
284 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000285
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000286 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000287
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000288 def test_abuse_done(self):
289 self.istest(inspect.istraceback, 'git.ex[2]')
290 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000291
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000292 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000293 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000294 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000295 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000296 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000297 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000298 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000299 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000300 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000301 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400302 # Test named tuple fields
303 record = mod.st[0]
304 self.assertIs(record.frame, mod.fr)
305 self.assertEqual(record.lineno, 16)
306 self.assertEqual(record.filename, mod.__file__)
307 self.assertEqual(record.function, 'eggs')
308 self.assertIn('inspect.stack()', record.code_context[0])
309 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000310
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000311 def test_trace(self):
312 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000313 self.assertEqual(revise(*git.tr[0][1:]),
314 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
315 self.assertEqual(revise(*git.tr[1][1:]),
316 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
317 self.assertEqual(revise(*git.tr[2][1:]),
318 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000319
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000320 def test_frame(self):
321 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
322 self.assertEqual(args, ['x', 'y'])
323 self.assertEqual(varargs, None)
324 self.assertEqual(varkw, None)
325 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
326 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
327 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000328
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000329 def test_previous_frame(self):
330 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000331 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000332 self.assertEqual(varargs, 'g')
333 self.assertEqual(varkw, 'h')
334 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000335 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000336
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000337class GetSourceBase(unittest.TestCase):
338 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000339 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000340
Yury Selivanov6738b112015-05-16 10:10:21 -0400341 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000342 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000343 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000344
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000345 def sourcerange(self, top, bottom):
346 lines = self.source.split("\n")
347 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000348
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000349 def assertSourceEqual(self, obj, top, bottom):
350 self.assertEqual(inspect.getsource(obj),
351 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000352
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000353class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000354 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000355
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000356 def test_getclasses(self):
357 classes = inspect.getmembers(mod, inspect.isclass)
358 self.assertEqual(classes,
359 [('FesteringGob', mod.FesteringGob),
360 ('MalodorousPervert', mod.MalodorousPervert),
361 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300362 ('StupidGit', mod.StupidGit),
363 ('Tit', mod.MalodorousPervert),
364 ])
365 tree = inspect.getclasstree([cls[1] for cls in classes])
366 self.assertEqual(tree,
367 [(object, ()),
368 [(mod.ParrotDroppings, (object,)),
369 [(mod.FesteringGob, (mod.MalodorousPervert,
370 mod.ParrotDroppings))
371 ],
372 (mod.StupidGit, (object,)),
373 [(mod.MalodorousPervert, (mod.StupidGit,)),
374 [(mod.FesteringGob, (mod.MalodorousPervert,
375 mod.ParrotDroppings))
376 ]
377 ]
378 ]
379 ])
380 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000381 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000382 [(object, ()),
383 [(mod.ParrotDroppings, (object,)),
384 (mod.StupidGit, (object,)),
385 [(mod.MalodorousPervert, (mod.StupidGit,)),
386 [(mod.FesteringGob, (mod.MalodorousPervert,
387 mod.ParrotDroppings))
388 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000389 ]
390 ]
391 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000392
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000393 def test_getfunctions(self):
394 functions = inspect.getmembers(mod, inspect.isfunction)
395 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300396 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000397 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000398
R. David Murray378c0cf2010-02-24 01:46:21 +0000399 @unittest.skipIf(sys.flags.optimize >= 2,
400 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000401 def test_getdoc(self):
402 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
403 self.assertEqual(inspect.getdoc(mod.StupidGit),
404 'A longer,\n\nindented\n\ndocstring.')
405 self.assertEqual(inspect.getdoc(git.abuse),
406 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000407
Serhiy Storchaka5cf2b7252015-04-03 22:38:53 +0300408 @unittest.skipIf(sys.flags.optimize >= 2,
409 "Docstrings are omitted with -O2 and above")
410 def test_getdoc_inherited(self):
411 self.assertEqual(inspect.getdoc(mod.FesteringGob),
412 'A longer,\n\nindented\n\ndocstring.')
413 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
414 'Another\n\ndocstring\n\ncontaining\n\ntabs')
415 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
416 'Another\n\ndocstring\n\ncontaining\n\ntabs')
417 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
418 'The automatic gainsaying.')
419
420 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
421 def test_finddoc(self):
422 finddoc = inspect._finddoc
423 self.assertEqual(finddoc(int), int.__doc__)
424 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
425 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
426 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
427 self.assertEqual(finddoc(int.real), int.real.__doc__)
428
Georg Brandl0c77a822008-06-10 16:37:50 +0000429 def test_cleandoc(self):
430 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
431 'An\nindented\ndocstring.')
432
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000433 def test_getcomments(self):
434 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
435 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Marco Buttu3f2155f2017-03-17 09:50:23 +0100436 # If the object source file is not available, return None.
437 co = compile('x=1', '_non_existing_filename.py', 'exec')
438 self.assertIsNone(inspect.getcomments(co))
439 # If the object has been defined in C, return None.
440 self.assertIsNone(inspect.getcomments(list))
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000441
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000442 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000443 # Check actual module
444 self.assertEqual(inspect.getmodule(mod), mod)
445 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000446 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000447 # Check a method (no __module__ attribute, falls back to filename)
448 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
449 # Do it again (check the caching isn't broken)
450 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
451 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000452 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000453 # Check filename override
454 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000455
Berker Peksagff0e3b72017-01-02 06:57:43 +0300456 def test_getframeinfo_get_first_line(self):
457 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
458 self.assertEqual(frame_info.code_context[0], "# line 1\n")
459 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
460
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000461 def test_getsource(self):
462 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200463 self.assertSourceEqual(mod.StupidGit, 21, 51)
464 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000465
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000466 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000467 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
468 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000469 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100470 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000471 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000472 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200473 try:
474 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
475 finally:
476 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000477
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000478 def test_getfile(self):
479 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000480
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500481 def test_getfile_class_without_module(self):
482 class CM(type):
483 @property
484 def __module__(cls):
485 raise AttributeError
486 class C(metaclass=CM):
487 pass
488 with self.assertRaises(TypeError):
489 inspect.getfile(C)
490
Thomas Kluyvere968bc732017-10-24 13:42:36 +0100491 def test_getfile_broken_repr(self):
492 class ErrorRepr:
493 def __repr__(self):
494 raise Exception('xyz')
495 er = ErrorRepr()
496 with self.assertRaises(TypeError):
497 inspect.getfile(er)
498
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000499 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000500 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000501 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000502 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000503 m.__file__ = "<string>" # hopefully not a real filename...
504 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000505 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000506 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000507 del sys.modules[name]
508 inspect.getmodule(compile('a=10','','single'))
509
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500510 def test_proceed_with_fake_filename(self):
511 '''doctest monkeypatches linecache to enable inspection'''
512 fn, source = '<test>', 'def x(): pass\n'
513 getlines = linecache.getlines
514 def monkey(filename, module_globals=None):
515 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300516 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500517 else:
518 return getlines(filename, module_globals)
519 linecache.getlines = monkey
520 try:
521 ns = {}
522 exec(compile(source, fn, 'single'), ns)
523 inspect.getsource(ns["x"])
524 finally:
525 linecache.getlines = getlines
526
Antoine Pitroua8723a02015-04-15 00:41:29 +0200527 def test_getsource_on_code_object(self):
528 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
529
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000530class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000531 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000532
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000533 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000534 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000535
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000536 def test_replacing_decorator(self):
537 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000538
Yury Selivanov081bbf62014-09-26 17:34:54 -0400539 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200540 self.assertSourceEqual(mod2.real, 130, 132)
541
542 def test_decorator_with_lambda(self):
543 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400544
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000545class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000546 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000547 def test_oneline_lambda(self):
548 # Test inspect.getsource with a one-line lambda function.
549 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000550
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000551 def test_threeline_lambda(self):
552 # Test inspect.getsource with a three-line lambda function,
553 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000554 self.assertSourceEqual(mod2.tll, 28, 30)
555
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000556 def test_twoline_indented_lambda(self):
557 # Test inspect.getsource with a two-line lambda function,
558 # where the second line _is_ indented.
559 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000560
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000561 def test_onelinefunc(self):
562 # Test inspect.getsource with a regular one-line function.
563 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000564
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000565 def test_manyargs(self):
566 # Test inspect.getsource with a regular function where
567 # the arguments are on two lines and _not_ indented and
568 # the body on the second line with the last arguments.
569 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000570
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000571 def test_twolinefunc(self):
572 # Test inspect.getsource with a regular function where
573 # the body is on two lines, following the argument list and
574 # continued on the next line by a \\.
575 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000576
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000577 def test_lambda_in_list(self):
578 # Test inspect.getsource with a one-line lambda function
579 # defined in a list, indented.
580 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000581
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000582 def test_anonymous(self):
583 # Test inspect.getsource with a lambda function defined
584 # as argument to another function.
585 self.assertSourceEqual(mod2.anonymous, 55, 55)
586
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000587class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000588 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000589
590 def test_with_comment(self):
591 self.assertSourceEqual(mod2.with_comment, 58, 59)
592
593 def test_multiline_sig(self):
594 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
595
Armin Rigodd5c0232005-09-25 11:45:45 +0000596 def test_nested_class(self):
597 self.assertSourceEqual(mod2.func69().func71, 71, 72)
598
599 def test_one_liner_followed_by_non_name(self):
600 self.assertSourceEqual(mod2.func77, 77, 77)
601
602 def test_one_liner_dedent_non_name(self):
603 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
604
605 def test_with_comment_instead_of_docstring(self):
606 self.assertSourceEqual(mod2.func88, 88, 90)
607
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000608 def test_method_in_dynamic_class(self):
609 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
610
R David Murray32562d72014-10-03 11:15:38 -0400611 # This should not skip for CPython, but might on a repackaged python where
612 # unicodedata is not an external module, or on pypy.
613 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
614 unicodedata.__file__.endswith('.py'),
615 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000616 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200617 self.assertRaises(OSError, inspect.getsource, unicodedata)
618 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000619
R. David Murraya1b37402010-06-17 02:04:29 +0000620 def test_findsource_code_in_linecache(self):
621 lines = ["x=1"]
622 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200623 self.assertRaises(OSError, inspect.findsource, co)
624 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000625 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200626 try:
627 self.assertEqual(inspect.findsource(co), (lines,0))
628 self.assertEqual(inspect.getsource(co), lines[0])
629 finally:
630 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000631
Ezio Melotti1b145922013-03-30 05:17:24 +0200632 def test_findsource_without_filename(self):
633 for fname in ['', '<string>']:
634 co = compile('x=1', fname, "exec")
635 self.assertRaises(IOError, inspect.findsource, co)
636 self.assertRaises(IOError, inspect.getsource, co)
637
Antoine Pitroua8723a02015-04-15 00:41:29 +0200638 def test_getsource_on_method(self):
639 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
640
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300641 def test_nested_func(self):
642 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
643
644
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000645class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400646 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000647 self.tempdir = TESTFN + '_dir'
648 os.mkdir(self.tempdir)
649 with open(os.path.join(self.tempdir,
650 'inspect_fodder3%spy' % os.extsep), 'w') as f:
651 f.write("class X:\n pass # No EOL")
652 with DirsOnSysPath(self.tempdir):
653 import inspect_fodder3 as mod3
654 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400655 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000656
657 def tearDown(self):
658 shutil.rmtree(self.tempdir)
659
660 def test_class(self):
661 self.assertSourceEqual(self.fodderModule.X, 1, 2)
662
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100663
664class _BrokenDataDescriptor(object):
665 """
666 A broken data descriptor. See bug #1785.
667 """
668 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700669 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100670
671 def __set__(*args):
672 raise RuntimeError
673
674 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700675 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100676
677
678class _BrokenMethodDescriptor(object):
679 """
680 A broken method descriptor. See bug #1785.
681 """
682 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700683 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100684
685 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700686 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100687
688
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000689# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000690def attrs_wo_objs(cls):
691 return [t[:3] for t in inspect.classify_class_attrs(cls)]
692
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100693
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000694class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000695 def test_newstyle_mro(self):
696 # The same w/ new-class MRO.
697 class A(object): pass
698 class B(A): pass
699 class C(A): pass
700 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000701
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000702 expected = (D, B, C, A, object)
703 got = inspect.getmro(D)
704 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000705
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500706 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
707 varkw_e=None, defaults_e=None, formatted=None):
708 with self.assertWarns(DeprecationWarning):
709 args, varargs, varkw, defaults = inspect.getargspec(routine)
710 self.assertEqual(args, args_e)
711 self.assertEqual(varargs, varargs_e)
712 self.assertEqual(varkw, varkw_e)
713 self.assertEqual(defaults, defaults_e)
714 if formatted is not None:
715 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
716 formatted)
717
Christian Heimes3795b532007-11-08 13:48:53 +0000718 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
719 varkw_e=None, defaults_e=None,
720 kwonlyargs_e=[], kwonlydefaults_e=None,
721 ann_e={}, formatted=None):
722 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
723 inspect.getfullargspec(routine)
724 self.assertEqual(args, args_e)
725 self.assertEqual(varargs, varargs_e)
726 self.assertEqual(varkw, varkw_e)
727 self.assertEqual(defaults, defaults_e)
728 self.assertEqual(kwonlyargs, kwonlyargs_e)
729 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
730 self.assertEqual(ann, ann_e)
731 if formatted is not None:
732 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
733 kwonlyargs, kwonlydefaults, ann),
734 formatted)
735
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500736 def test_getargspec(self):
737 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
738
739 self.assertArgSpecEquals(mod.spam,
740 ['a', 'b', 'c', 'd', 'e', 'f'],
741 'g', 'h', (3, 4, 5),
742 '(a, b, c, d=3, e=4, f=5, *g, **h)')
743
744 self.assertRaises(ValueError, self.assertArgSpecEquals,
745 mod2.keyworded, [])
746
747 self.assertRaises(ValueError, self.assertArgSpecEquals,
748 mod2.annotated, [])
749 self.assertRaises(ValueError, self.assertArgSpecEquals,
750 mod2.keyword_only_arg, [])
751
752
Christian Heimes3795b532007-11-08 13:48:53 +0000753 def test_getfullargspec(self):
754 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
755 kwonlyargs_e=['arg2'],
756 kwonlydefaults_e={'arg2':1},
757 formatted='(*arg1, arg2=1)')
758
759 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000760 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000761 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000762 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
763 kwonlyargs_e=['arg'],
764 formatted='(*, arg)')
765
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500766 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500767 # Issue 20684: low level introspection API must ignore __wrapped__
768 @functools.wraps(mod.spam)
769 def ham(x, y):
770 pass
771 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500772 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500773 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
774 self.assertFullArgSpecEquals(functools.partial(ham),
775 ['x', 'y'], formatted='(x, y)')
776 # Other variants
777 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500778 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
779 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500780 class C:
781 @functools.wraps(mod.spam)
782 def ham(self, x, y):
783 pass
784 pham = functools.partialmethod(ham)
785 @functools.wraps(mod.spam)
786 def __call__(self, x, y):
787 pass
788 check_method(C())
789 check_method(C.ham)
790 check_method(C().ham)
791 check_method(C.pham)
792 check_method(C().pham)
793
794 class C_new:
795 @functools.wraps(mod.spam)
796 def __new__(self, x, y):
797 pass
798 check_method(C_new)
799
800 class C_init:
801 @functools.wraps(mod.spam)
802 def __init__(self, x, y):
803 pass
804 check_method(C_init)
805
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500806 def test_getfullargspec_signature_attr(self):
807 def test():
808 pass
809 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
810 test.__signature__ = inspect.Signature(parameters=(spam_param,))
811
812 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
813
Yury Selivanov4cb93912014-01-29 11:54:12 -0500814 def test_getfullargspec_signature_annos(self):
815 def test(a:'spam') -> 'ham': pass
816 spec = inspect.getfullargspec(test)
817 self.assertEqual(test.__annotations__, spec.annotations)
818
819 def test(): pass
820 spec = inspect.getfullargspec(test)
821 self.assertEqual(test.__annotations__, spec.annotations)
822
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500823 @unittest.skipIf(MISSING_C_DOCSTRINGS,
824 "Signature information for builtins requires docstrings")
825 def test_getfullargspec_builtin_methods(self):
826 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
827 args_e=['self', 'obj'], formatted='(self, obj)')
828
829 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
830 args_e=['self', 'obj'], formatted='(self, obj)')
831
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500832 self.assertFullArgSpecEquals(
833 os.stat,
834 args_e=['path'],
835 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
836 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
837 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
838
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200839 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500840 @unittest.skipIf(MISSING_C_DOCSTRINGS,
841 "Signature information for builtins requires docstrings")
842 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200843 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500844 builtin = _testcapi.docstring_with_signature_with_defaults
845 spec = inspect.getfullargspec(builtin)
846 self.assertEqual(spec.defaults[0], 'avocado')
847
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200848 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500849 @unittest.skipIf(MISSING_C_DOCSTRINGS,
850 "Signature information for builtins requires docstrings")
851 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200852 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500853 builtin = _testcapi.docstring_no_signature
854 with self.assertRaises(TypeError):
855 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000856
larryhastingsf36ba122018-01-28 11:13:09 -0800857 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
858 for fn in signatures_with_lexicographic_keyword_only_parameters():
859 signature = inspect.getfullargspec(fn)
860 l = list(signature.kwonlyargs)
861 sorted_l = sorted(l)
862 self.assertTrue(l)
863 self.assertEqual(l, sorted_l)
864 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
865 l = list(signature.kwonlyargs)
866 self.assertEqual(l, unsorted_keyword_only_parameters)
867
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500868 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000869 class A(object):
870 def m(self):
871 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500872 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000873
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000874 def test_classify_newstyle(self):
875 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000876
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000877 def s(): pass
878 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000879
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000880 def c(cls): pass
881 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000882
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000883 def getp(self): pass
884 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000885
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000886 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000887
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000888 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000889
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000890 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000891
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100892 dd = _BrokenDataDescriptor()
893 md = _BrokenMethodDescriptor()
894
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000895 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500896
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +0200897 self.assertIn(('__new__', 'static method', object), attrs,
898 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500899 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
900
Benjamin Peterson577473f2010-01-19 00:09:57 +0000901 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
902 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
903 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000904 self.assertIn(('m', 'method', A), attrs,
905 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000906 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
907 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100908 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
909 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000910
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000911 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000912
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000913 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000914
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000915 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000916 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
917 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
918 self.assertIn(('p', 'property', A), attrs, 'missing property')
919 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
920 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
921 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100922 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
923 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000924
925
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000926 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000927
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000928 def m(self): pass
929 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000930
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000931 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000932 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
933 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
934 self.assertIn(('p', 'property', A), attrs, 'missing property')
935 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
936 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
937 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100938 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
939 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000940
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000941 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000942
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000943 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000944
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000945 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000946 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
947 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
948 self.assertIn(('p', 'property', A), attrs, 'missing property')
949 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
950 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
951 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100952 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
953 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
954
955 def test_classify_builtin_types(self):
956 # Simple sanity check that all built-in types can have their
957 # attributes classified.
958 for name in dir(__builtins__):
959 builtin = getattr(__builtins__, name)
960 if isinstance(builtin, type):
961 inspect.classify_class_attrs(builtin)
962
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +0200963 attrs = attrs_wo_objs(bool)
964 self.assertIn(('__new__', 'static method', bool), attrs,
965 'missing __new__')
966 self.assertIn(('from_bytes', 'class method', int), attrs,
967 'missing class method')
968 self.assertIn(('to_bytes', 'method', int), attrs,
969 'missing plain method')
970 self.assertIn(('__add__', 'method', int), attrs,
971 'missing plain method')
972 self.assertIn(('__and__', 'method', bool), attrs,
973 'missing plain method')
974
Ethan Furman63c141c2013-10-18 00:27:39 -0700975 def test_classify_DynamicClassAttribute(self):
976 class Meta(type):
977 def __getattr__(self, name):
978 if name == 'ham':
979 return 'spam'
980 return super().__getattr__(name)
981 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700982 @types.DynamicClassAttribute
983 def ham(self):
984 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700985 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
986 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700987 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700988 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
989
Yury Selivanovbf341fb2015-05-21 15:41:57 -0400990 def test_classify_overrides_bool(self):
991 class NoBool(object):
992 def __eq__(self, other):
993 return NoBool()
994
995 def __bool__(self):
996 raise NotImplementedError(
997 "This object does not specify a boolean value")
998
999 class HasNB(object):
1000 dd = NoBool()
1001
1002 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1003 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1004
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001005 def test_classify_metaclass_class_attribute(self):
1006 class Meta(type):
1007 fish = 'slap'
1008 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001009 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001010 class Class(metaclass=Meta):
1011 pass
1012 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1013 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1014
Ethan Furman63c141c2013-10-18 00:27:39 -07001015 def test_classify_VirtualAttribute(self):
1016 class Meta(type):
1017 def __dir__(cls):
1018 return ['__class__', '__module__', '__name__', 'BOOM']
1019 def __getattr__(self, name):
1020 if name =='BOOM':
1021 return 42
1022 return super().__getattr(name)
1023 class Class(metaclass=Meta):
1024 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001025 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001026 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1027
1028 def test_classify_VirtualAttribute_multi_classes(self):
1029 class Meta1(type):
1030 def __dir__(cls):
1031 return ['__class__', '__module__', '__name__', 'one']
1032 def __getattr__(self, name):
1033 if name =='one':
1034 return 1
1035 return super().__getattr__(name)
1036 class Meta2(type):
1037 def __dir__(cls):
1038 return ['__class__', '__module__', '__name__', 'two']
1039 def __getattr__(self, name):
1040 if name =='two':
1041 return 2
1042 return super().__getattr__(name)
1043 class Meta3(Meta1, Meta2):
1044 def __dir__(cls):
1045 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1046 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1047 def __getattr__(self, name):
1048 if name =='three':
1049 return 3
1050 return super().__getattr__(name)
1051 class Class1(metaclass=Meta1):
1052 pass
1053 class Class2(Class1, metaclass=Meta3):
1054 pass
1055
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001056 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1057 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1058 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001059 cca = inspect.classify_class_attrs(Class2)
1060 for sf in (should_find1, should_find2, should_find3):
1061 self.assertIn(sf, cca)
1062
1063 def test_classify_class_attrs_with_buggy_dir(self):
1064 class M(type):
1065 def __dir__(cls):
1066 return ['__class__', '__name__', 'missing']
1067 class C(metaclass=M):
1068 pass
1069 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1070 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001071
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001072 def test_getmembers_descriptors(self):
1073 class A(object):
1074 dd = _BrokenDataDescriptor()
1075 md = _BrokenMethodDescriptor()
1076
1077 def pred_wrapper(pred):
1078 # A quick'n'dirty way to discard standard attributes of new-style
1079 # classes.
1080 class Empty(object):
1081 pass
1082 def wrapped(x):
1083 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1084 return False
1085 return pred(x)
1086 return wrapped
1087
1088 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1089 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1090
1091 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1092 [('md', A.__dict__['md'])])
1093 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1094 [('dd', A.__dict__['dd'])])
1095
1096 class B(A):
1097 pass
1098
1099 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1100 [('md', A.__dict__['md'])])
1101 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1102 [('dd', A.__dict__['dd'])])
1103
Antoine Pitrou0c603812012-01-18 17:40:18 +01001104 def test_getmembers_method(self):
1105 class B:
1106 def f(self):
1107 pass
1108
1109 self.assertIn(('f', B.f), inspect.getmembers(B))
1110 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1111 b = B()
1112 self.assertIn(('f', b.f), inspect.getmembers(b))
1113 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1114
Ethan Furmane03ea372013-09-25 07:14:41 -07001115 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001116 class M(type):
1117 def __getattr__(cls, name):
1118 if name == 'eggs':
1119 return 'scrambled'
1120 return super().__getattr__(name)
1121 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001122 @types.DynamicClassAttribute
1123 def eggs(self):
1124 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001125 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1126 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1127
1128 def test_getmembers_with_buggy_dir(self):
1129 class M(type):
1130 def __dir__(cls):
1131 return ['__class__', '__name__', 'missing']
1132 class C(metaclass=M):
1133 pass
1134 attrs = [a[0] for a in inspect.getmembers(C)]
1135 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001136
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001137
Nick Coghlan2f92e542012-06-23 19:39:55 +10001138_global_ref = object()
1139class TestGetClosureVars(unittest.TestCase):
1140
1141 def test_name_resolution(self):
1142 # Basic test of the 4 different resolution mechanisms
1143 def f(nonlocal_ref):
1144 def g(local_ref):
1145 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1146 return g
1147 _arg = object()
1148 nonlocal_vars = {"nonlocal_ref": _arg}
1149 global_vars = {"_global_ref": _global_ref}
1150 builtin_vars = {"print": print}
1151 unbound_names = {"unbound_ref"}
1152 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1153 builtin_vars, unbound_names)
1154 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1155
1156 def test_generator_closure(self):
1157 def f(nonlocal_ref):
1158 def g(local_ref):
1159 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1160 yield
1161 return g
1162 _arg = object()
1163 nonlocal_vars = {"nonlocal_ref": _arg}
1164 global_vars = {"_global_ref": _global_ref}
1165 builtin_vars = {"print": print}
1166 unbound_names = {"unbound_ref"}
1167 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1168 builtin_vars, unbound_names)
1169 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1170
1171 def test_method_closure(self):
1172 class C:
1173 def f(self, nonlocal_ref):
1174 def g(local_ref):
1175 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1176 return g
1177 _arg = object()
1178 nonlocal_vars = {"nonlocal_ref": _arg}
1179 global_vars = {"_global_ref": _global_ref}
1180 builtin_vars = {"print": print}
1181 unbound_names = {"unbound_ref"}
1182 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1183 builtin_vars, unbound_names)
1184 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1185
1186 def test_nonlocal_vars(self):
1187 # More complex tests of nonlocal resolution
1188 def _nonlocal_vars(f):
1189 return inspect.getclosurevars(f).nonlocals
1190
1191 def make_adder(x):
1192 def add(y):
1193 return x + y
1194 return add
1195
1196 def curry(func, arg1):
1197 return lambda arg2: func(arg1, arg2)
1198
1199 def less_than(a, b):
1200 return a < b
1201
1202 # The infamous Y combinator.
1203 def Y(le):
1204 def g(f):
1205 return le(lambda x: f(f)(x))
1206 Y.g_ref = g
1207 return g(g)
1208
1209 def check_y_combinator(func):
1210 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1211
1212 inc = make_adder(1)
1213 add_two = make_adder(2)
1214 greater_than_five = curry(less_than, 5)
1215
1216 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1217 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1218 self.assertEqual(_nonlocal_vars(greater_than_five),
1219 {'arg1': 5, 'func': less_than})
1220 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1221 {'x': 3})
1222 Y(check_y_combinator)
1223
1224 def test_getclosurevars_empty(self):
1225 def foo(): pass
1226 _empty = inspect.ClosureVars({}, {}, {}, set())
1227 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1228 self.assertEqual(inspect.getclosurevars(foo), _empty)
1229
1230 def test_getclosurevars_error(self):
1231 class T: pass
1232 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1233 self.assertRaises(TypeError, inspect.getclosurevars, list)
1234 self.assertRaises(TypeError, inspect.getclosurevars, {})
1235
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001236 def _private_globals(self):
1237 code = """def f(): print(path)"""
1238 ns = {}
1239 exec(code, ns)
1240 return ns["f"], ns
1241
1242 def test_builtins_fallback(self):
1243 f, ns = self._private_globals()
1244 ns.pop("__builtins__", None)
1245 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1246 self.assertEqual(inspect.getclosurevars(f), expected)
1247
1248 def test_builtins_as_dict(self):
1249 f, ns = self._private_globals()
1250 ns["__builtins__"] = {"path":1}
1251 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1252 self.assertEqual(inspect.getclosurevars(f), expected)
1253
1254 def test_builtins_as_module(self):
1255 f, ns = self._private_globals()
1256 ns["__builtins__"] = os
1257 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1258 self.assertEqual(inspect.getclosurevars(f), expected)
1259
Nick Coghlan2f92e542012-06-23 19:39:55 +10001260
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001261class TestGetcallargsFunctions(unittest.TestCase):
1262
1263 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1264 locs = dict(locs or {}, func=func)
1265 r1 = eval('func(%s)' % call_params_string, None, locs)
1266 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1267 locs)
1268 self.assertEqual(r1, r2)
1269
1270 def assertEqualException(self, func, call_param_string, locs=None):
1271 locs = dict(locs or {}, func=func)
1272 try:
1273 eval('func(%s)' % call_param_string, None, locs)
1274 except Exception as e:
1275 ex1 = e
1276 else:
1277 self.fail('Exception not raised')
1278 try:
1279 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1280 locs)
1281 except Exception as e:
1282 ex2 = e
1283 else:
1284 self.fail('Exception not raised')
1285 self.assertIs(type(ex1), type(ex2))
1286 self.assertEqual(str(ex1), str(ex2))
1287 del ex1, ex2
1288
1289 def makeCallable(self, signature):
1290 """Create a function that returns its locals()"""
1291 code = "lambda %s: locals()"
1292 return eval(code % signature)
1293
1294 def test_plain(self):
1295 f = self.makeCallable('a, b=1')
1296 self.assertEqualCallArgs(f, '2')
1297 self.assertEqualCallArgs(f, '2, 3')
1298 self.assertEqualCallArgs(f, 'a=2')
1299 self.assertEqualCallArgs(f, 'b=3, a=2')
1300 self.assertEqualCallArgs(f, '2, b=3')
1301 # expand *iterable / **mapping
1302 self.assertEqualCallArgs(f, '*(2,)')
1303 self.assertEqualCallArgs(f, '*[2]')
1304 self.assertEqualCallArgs(f, '*(2, 3)')
1305 self.assertEqualCallArgs(f, '*[2, 3]')
1306 self.assertEqualCallArgs(f, '**{"a":2}')
1307 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1308 self.assertEqualCallArgs(f, '2, **{"b":3}')
1309 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1310 # expand UserList / UserDict
1311 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1312 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1313 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1314 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1315 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1316
1317 def test_varargs(self):
1318 f = self.makeCallable('a, b=1, *c')
1319 self.assertEqualCallArgs(f, '2')
1320 self.assertEqualCallArgs(f, '2, 3')
1321 self.assertEqualCallArgs(f, '2, 3, 4')
1322 self.assertEqualCallArgs(f, '*(2,3,4)')
1323 self.assertEqualCallArgs(f, '2, *[3,4]')
1324 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1325
1326 def test_varkw(self):
1327 f = self.makeCallable('a, b=1, **c')
1328 self.assertEqualCallArgs(f, 'a=2')
1329 self.assertEqualCallArgs(f, '2, b=3, c=4')
1330 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1331 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1332 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1333 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1334 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1335 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1336 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1337
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001338 def test_varkw_only(self):
1339 # issue11256:
1340 f = self.makeCallable('**c')
1341 self.assertEqualCallArgs(f, '')
1342 self.assertEqualCallArgs(f, 'a=1')
1343 self.assertEqualCallArgs(f, 'a=1, b=2')
1344 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1345 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1346 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1347
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001348 def test_keyword_only(self):
1349 f = self.makeCallable('a=3, *, c, d=2')
1350 self.assertEqualCallArgs(f, 'c=3')
1351 self.assertEqualCallArgs(f, 'c=3, a=3')
1352 self.assertEqualCallArgs(f, 'a=2, c=4')
1353 self.assertEqualCallArgs(f, '4, c=4')
1354 self.assertEqualException(f, '')
1355 self.assertEqualException(f, '3')
1356 self.assertEqualException(f, 'a=3')
1357 self.assertEqualException(f, 'd=4')
1358
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001359 f = self.makeCallable('*, c, d=2')
1360 self.assertEqualCallArgs(f, 'c=3')
1361 self.assertEqualCallArgs(f, 'c=3, d=4')
1362 self.assertEqualCallArgs(f, 'd=4, c=3')
1363
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001364 def test_multiple_features(self):
1365 f = self.makeCallable('a, b=2, *f, **g')
1366 self.assertEqualCallArgs(f, '2, 3, 7')
1367 self.assertEqualCallArgs(f, '2, 3, x=8')
1368 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1369 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1370 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1371 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1372 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1373 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1374 '(4,[5,6])]), **collections.UserDict('
1375 'y=9, z=10)')
1376
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001377 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1378 self.assertEqualCallArgs(f, '2, 3, x=8')
1379 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1380 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1381 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1382 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1383 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1384 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1385 '(4,[5,6])]), q=0, **collections.UserDict('
1386 'y=9, z=10)')
1387
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001388 def test_errors(self):
1389 f0 = self.makeCallable('')
1390 f1 = self.makeCallable('a, b')
1391 f2 = self.makeCallable('a, b=1')
1392 # f0 takes no arguments
1393 self.assertEqualException(f0, '1')
1394 self.assertEqualException(f0, 'x=1')
1395 self.assertEqualException(f0, '1,x=1')
1396 # f1 takes exactly 2 arguments
1397 self.assertEqualException(f1, '')
1398 self.assertEqualException(f1, '1')
1399 self.assertEqualException(f1, 'a=2')
1400 self.assertEqualException(f1, 'b=3')
1401 # f2 takes at least 1 argument
1402 self.assertEqualException(f2, '')
1403 self.assertEqualException(f2, 'b=3')
1404 for f in f1, f2:
1405 # f1/f2 takes exactly/at most 2 arguments
1406 self.assertEqualException(f, '2, 3, 4')
1407 self.assertEqualException(f, '1, 2, 3, a=1')
1408 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001409 # XXX: success of this one depends on dict order
1410 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001411 # f got an unexpected keyword argument
1412 self.assertEqualException(f, 'c=2')
1413 self.assertEqualException(f, '2, c=3')
1414 self.assertEqualException(f, '2, 3, c=4')
1415 self.assertEqualException(f, '2, c=4, b=3')
1416 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1417 # f got multiple values for keyword argument
1418 self.assertEqualException(f, '1, a=2')
1419 self.assertEqualException(f, '1, **{"a":2}')
1420 self.assertEqualException(f, '1, 2, b=3')
1421 # XXX: Python inconsistency
1422 # - for functions and bound methods: unexpected keyword 'c'
1423 # - for unbound methods: multiple values for keyword 'a'
1424 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001425 # issue11256:
1426 f3 = self.makeCallable('**c')
1427 self.assertEqualException(f3, '1, 2')
1428 self.assertEqualException(f3, '1, 2, a=1, b=2')
1429 f4 = self.makeCallable('*, a, b=0')
1430 self.assertEqualException(f3, '1, 2')
1431 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001432
Yury Selivanov875df202014-03-27 18:23:03 -04001433 # issue #20816: getcallargs() fails to iterate over non-existent
1434 # kwonlydefaults and raises a wrong TypeError
1435 def f5(*, a): pass
1436 with self.assertRaisesRegex(TypeError,
1437 'missing 1 required keyword-only'):
1438 inspect.getcallargs(f5)
1439
1440
Yury Selivanovdccfa132014-03-27 18:42:52 -04001441 # issue20817:
1442 def f6(a, b, c):
1443 pass
1444 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1445 inspect.getcallargs(f6)
1446
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001447class TestGetcallargsMethods(TestGetcallargsFunctions):
1448
1449 def setUp(self):
1450 class Foo(object):
1451 pass
1452 self.cls = Foo
1453 self.inst = Foo()
1454
1455 def makeCallable(self, signature):
1456 assert 'self' not in signature
1457 mk = super(TestGetcallargsMethods, self).makeCallable
1458 self.cls.method = mk('self, ' + signature)
1459 return self.inst.method
1460
1461class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1462
1463 def makeCallable(self, signature):
1464 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1465 return self.cls.method
1466
1467 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1468 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1469 *self._getAssertEqualParams(func, call_params_string, locs))
1470
1471 def assertEqualException(self, func, call_params_string, locs=None):
1472 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1473 *self._getAssertEqualParams(func, call_params_string, locs))
1474
1475 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1476 assert 'inst' not in call_params_string
1477 locs = dict(locs or {}, inst=self.inst)
1478 return (func, 'inst,' + call_params_string, locs)
1479
Michael Foord95fc51d2010-11-20 15:07:30 +00001480
1481class TestGetattrStatic(unittest.TestCase):
1482
1483 def test_basic(self):
1484 class Thing(object):
1485 x = object()
1486
1487 thing = Thing()
1488 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1489 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1490 with self.assertRaises(AttributeError):
1491 inspect.getattr_static(thing, 'y')
1492
1493 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1494
1495 def test_inherited(self):
1496 class Thing(object):
1497 x = object()
1498 class OtherThing(Thing):
1499 pass
1500
1501 something = OtherThing()
1502 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1503
1504 def test_instance_attr(self):
1505 class Thing(object):
1506 x = 2
1507 def __init__(self, x):
1508 self.x = x
1509 thing = Thing(3)
1510 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1511 del thing.x
1512 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1513
1514 def test_property(self):
1515 class Thing(object):
1516 @property
1517 def x(self):
1518 raise AttributeError("I'm pretending not to exist")
1519 thing = Thing()
1520 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1521
Ezio Melotti75cbd732011-04-28 00:59:29 +03001522 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001523 class descriptor(object):
1524 def __get__(*_):
1525 raise AttributeError("I'm pretending not to exist")
1526 desc = descriptor()
1527 class Thing(object):
1528 x = desc
1529 thing = Thing()
1530 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1531
1532 def test_classAttribute(self):
1533 class Thing(object):
1534 x = object()
1535
1536 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1537
Ethan Furmane03ea372013-09-25 07:14:41 -07001538 def test_classVirtualAttribute(self):
1539 class Thing(object):
1540 @types.DynamicClassAttribute
1541 def x(self):
1542 return self._x
1543 _x = object()
1544
1545 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1546
Michael Foord95fc51d2010-11-20 15:07:30 +00001547 def test_inherited_classattribute(self):
1548 class Thing(object):
1549 x = object()
1550 class OtherThing(Thing):
1551 pass
1552
1553 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1554
1555 def test_slots(self):
1556 class Thing(object):
1557 y = 'bar'
1558 __slots__ = ['x']
1559 def __init__(self):
1560 self.x = 'foo'
1561 thing = Thing()
1562 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1563 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1564
1565 del thing.x
1566 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1567
1568 def test_metaclass(self):
1569 class meta(type):
1570 attr = 'foo'
1571 class Thing(object, metaclass=meta):
1572 pass
1573 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1574
1575 class sub(meta):
1576 pass
1577 class OtherThing(object, metaclass=sub):
1578 x = 3
1579 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1580
1581 class OtherOtherThing(OtherThing):
1582 pass
1583 # this test is odd, but it was added as it exposed a bug
1584 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1585
1586 def test_no_dict_no_slots(self):
1587 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1588 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1589
1590 def test_no_dict_no_slots_instance_member(self):
1591 # returns descriptor
1592 with open(__file__) as handle:
1593 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1594
1595 def test_inherited_slots(self):
1596 # returns descriptor
1597 class Thing(object):
1598 __slots__ = ['x']
1599 def __init__(self):
1600 self.x = 'foo'
1601
1602 class OtherThing(Thing):
1603 pass
1604 # it would be nice if this worked...
1605 # we get the descriptor instead of the instance attribute
1606 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1607
1608 def test_descriptor(self):
1609 class descriptor(object):
1610 def __get__(self, instance, owner):
1611 return 3
1612 class Foo(object):
1613 d = descriptor()
1614
1615 foo = Foo()
1616
1617 # for a non data descriptor we return the instance attribute
1618 foo.__dict__['d'] = 1
1619 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1620
Mike53f7a7c2017-12-14 14:04:53 +03001621 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001622 # descriptor
1623 descriptor.__set__ = lambda s, i, v: None
1624 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1625
1626
1627 def test_metaclass_with_descriptor(self):
1628 class descriptor(object):
1629 def __get__(self, instance, owner):
1630 return 3
1631 class meta(type):
1632 d = descriptor()
1633 class Thing(object, metaclass=meta):
1634 pass
1635 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1636
1637
Michael Foordcc7ebb82010-11-20 16:20:16 +00001638 def test_class_as_property(self):
1639 class Base(object):
1640 foo = 3
1641
1642 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001643 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001644 @property
1645 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001646 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001647 return object
1648
Michael Foord35184ed2010-11-20 16:58:30 +00001649 instance = Something()
1650 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1651 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001652 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1653
Michael Foorde5162652010-11-20 16:40:44 +00001654 def test_mro_as_property(self):
1655 class Meta(type):
1656 @property
1657 def __mro__(self):
1658 return (object,)
1659
1660 class Base(object):
1661 foo = 3
1662
1663 class Something(Base, metaclass=Meta):
1664 pass
1665
1666 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1667 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1668
Michael Foorddcebe0f2011-03-15 19:20:44 -04001669 def test_dict_as_property(self):
1670 test = self
1671 test.called = False
1672
1673 class Foo(dict):
1674 a = 3
1675 @property
1676 def __dict__(self):
1677 test.called = True
1678 return {}
1679
1680 foo = Foo()
1681 foo.a = 4
1682 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1683 self.assertFalse(test.called)
1684
1685 def test_custom_object_dict(self):
1686 test = self
1687 test.called = False
1688
1689 class Custom(dict):
1690 def get(self, key, default=None):
1691 test.called = True
1692 super().get(key, default)
1693
1694 class Foo(object):
1695 a = 3
1696 foo = Foo()
1697 foo.__dict__ = Custom()
1698 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1699 self.assertFalse(test.called)
1700
1701 def test_metaclass_dict_as_property(self):
1702 class Meta(type):
1703 @property
1704 def __dict__(self):
1705 self.executed = True
1706
1707 class Thing(metaclass=Meta):
1708 executed = False
1709
1710 def __init__(self):
1711 self.spam = 42
1712
1713 instance = Thing()
1714 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1715 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001716
Michael Foorda51623b2011-12-18 22:01:40 +00001717 def test_module(self):
1718 sentinel = object()
1719 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1720 sentinel)
1721
Michael Foord3ba95f82011-12-22 01:13:37 +00001722 def test_metaclass_with_metaclass_with_dict_as_property(self):
1723 class MetaMeta(type):
1724 @property
1725 def __dict__(self):
1726 self.executed = True
1727 return dict(spam=42)
1728
1729 class Meta(type, metaclass=MetaMeta):
1730 executed = False
1731
1732 class Thing(metaclass=Meta):
1733 pass
1734
1735 with self.assertRaises(AttributeError):
1736 inspect.getattr_static(Thing, "spam")
1737 self.assertFalse(Thing.executed)
1738
Nick Coghlane0f04652010-11-21 03:44:04 +00001739class TestGetGeneratorState(unittest.TestCase):
1740
1741 def setUp(self):
1742 def number_generator():
1743 for number in range(5):
1744 yield number
1745 self.generator = number_generator()
1746
1747 def _generatorstate(self):
1748 return inspect.getgeneratorstate(self.generator)
1749
1750 def test_created(self):
1751 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1752
1753 def test_suspended(self):
1754 next(self.generator)
1755 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1756
1757 def test_closed_after_exhaustion(self):
1758 for i in self.generator:
1759 pass
1760 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1761
1762 def test_closed_after_immediate_exception(self):
1763 with self.assertRaises(RuntimeError):
1764 self.generator.throw(RuntimeError)
1765 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1766
1767 def test_running(self):
1768 # As mentioned on issue #10220, checking for the RUNNING state only
1769 # makes sense inside the generator itself.
1770 # The following generator checks for this by using the closure's
1771 # reference to self and the generator state checking helper method
1772 def running_check_generator():
1773 for number in range(5):
1774 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1775 yield number
1776 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1777 self.generator = running_check_generator()
1778 # Running up to the first yield
1779 next(self.generator)
1780 # Running after the first yield
1781 next(self.generator)
1782
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001783 def test_easy_debugging(self):
1784 # repr() and str() of a generator state should contain the state name
1785 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1786 for name in names:
1787 state = getattr(inspect, name)
1788 self.assertIn(name, repr(state))
1789 self.assertIn(name, str(state))
1790
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001791 def test_getgeneratorlocals(self):
1792 def each(lst, a=None):
1793 b=(1, 2, 3)
1794 for v in lst:
1795 if v == 3:
1796 c = 12
1797 yield v
1798
1799 numbers = each([1, 2, 3])
1800 self.assertEqual(inspect.getgeneratorlocals(numbers),
1801 {'a': None, 'lst': [1, 2, 3]})
1802 next(numbers)
1803 self.assertEqual(inspect.getgeneratorlocals(numbers),
1804 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1805 'b': (1, 2, 3)})
1806 next(numbers)
1807 self.assertEqual(inspect.getgeneratorlocals(numbers),
1808 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1809 'b': (1, 2, 3)})
1810 next(numbers)
1811 self.assertEqual(inspect.getgeneratorlocals(numbers),
1812 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1813 'b': (1, 2, 3), 'c': 12})
1814 try:
1815 next(numbers)
1816 except StopIteration:
1817 pass
1818 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1819
1820 def test_getgeneratorlocals_empty(self):
1821 def yield_one():
1822 yield 1
1823 one = yield_one()
1824 self.assertEqual(inspect.getgeneratorlocals(one), {})
1825 try:
1826 next(one)
1827 except StopIteration:
1828 pass
1829 self.assertEqual(inspect.getgeneratorlocals(one), {})
1830
1831 def test_getgeneratorlocals_error(self):
1832 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1833 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1834 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1835 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1836
Nick Coghlane0f04652010-11-21 03:44:04 +00001837
Yury Selivanov5376ba92015-06-22 12:19:30 -04001838class TestGetCoroutineState(unittest.TestCase):
1839
1840 def setUp(self):
1841 @types.coroutine
1842 def number_coroutine():
1843 for number in range(5):
1844 yield number
1845 async def coroutine():
1846 await number_coroutine()
1847 self.coroutine = coroutine()
1848
1849 def tearDown(self):
1850 self.coroutine.close()
1851
1852 def _coroutinestate(self):
1853 return inspect.getcoroutinestate(self.coroutine)
1854
1855 def test_created(self):
1856 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1857
1858 def test_suspended(self):
1859 self.coroutine.send(None)
1860 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1861
1862 def test_closed_after_exhaustion(self):
1863 while True:
1864 try:
1865 self.coroutine.send(None)
1866 except StopIteration:
1867 break
1868
1869 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1870
1871 def test_closed_after_immediate_exception(self):
1872 with self.assertRaises(RuntimeError):
1873 self.coroutine.throw(RuntimeError)
1874 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1875
1876 def test_easy_debugging(self):
1877 # repr() and str() of a coroutine state should contain the state name
1878 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1879 for name in names:
1880 state = getattr(inspect, name)
1881 self.assertIn(name, repr(state))
1882 self.assertIn(name, str(state))
1883
1884 def test_getcoroutinelocals(self):
1885 @types.coroutine
1886 def gencoro():
1887 yield
1888
1889 gencoro = gencoro()
1890 async def func(a=None):
1891 b = 'spam'
1892 await gencoro
1893
1894 coro = func()
1895 self.assertEqual(inspect.getcoroutinelocals(coro),
1896 {'a': None, 'gencoro': gencoro})
1897 coro.send(None)
1898 self.assertEqual(inspect.getcoroutinelocals(coro),
1899 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
1900
1901
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001902class MySignature(inspect.Signature):
1903 # Top-level to make it picklable;
1904 # used in test_signature_object_pickle
1905 pass
1906
1907class MyParameter(inspect.Parameter):
1908 # Top-level to make it picklable;
1909 # used in test_signature_object_pickle
1910 pass
1911
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001912
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001913
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001914class TestSignatureObject(unittest.TestCase):
1915 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04001916 def signature(func, **kw):
1917 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001918 return (tuple((param.name,
1919 (... if param.default is param.empty else param.default),
1920 (... if param.annotation is param.empty
1921 else param.annotation),
1922 str(param.kind).lower())
1923 for param in sig.parameters.values()),
1924 (... if sig.return_annotation is sig.empty
1925 else sig.return_annotation))
1926
1927 def test_signature_object(self):
1928 S = inspect.Signature
1929 P = inspect.Parameter
1930
1931 self.assertEqual(str(S()), '()')
1932
Yury Selivanov07a9e452014-01-29 10:58:16 -05001933 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001934 pass
1935 sig = inspect.signature(test)
1936 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001937 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001938 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001939 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001940 args = sig.parameters['args']
1941 ko = sig.parameters['ko']
1942 kwargs = sig.parameters['kwargs']
1943
1944 S((po, pk, args, ko, kwargs))
1945
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001946 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001947 S((pk, po, args, ko, kwargs))
1948
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001949 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001950 S((po, args, pk, ko, kwargs))
1951
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001952 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001953 S((args, po, pk, ko, kwargs))
1954
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001955 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001956 S((po, pk, args, kwargs, ko))
1957
1958 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001959 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001960 S((po, pk, args, kwargs2, ko))
1961
Yury Selivanov07a9e452014-01-29 10:58:16 -05001962 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1963 S((pod, po))
1964
1965 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1966 S((po, pkd, pk))
1967
1968 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1969 S((pkd, pk))
1970
Yury Selivanov374375d2014-03-27 12:41:53 -04001971 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04001972 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04001973
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001974 def test_signature_object_pickle(self):
1975 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1976 foo_partial = functools.partial(foo, a=1)
1977
1978 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001979
1980 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1981 with self.subTest(pickle_ver=ver, subclass=False):
1982 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1983 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001984
1985 # Test that basic sub-classing works
1986 sig = inspect.signature(foo)
1987 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
1988 myparams = collections.OrderedDict(sig.parameters, a=myparam)
1989 mysig = MySignature().replace(parameters=myparams.values(),
1990 return_annotation=sig.return_annotation)
1991 self.assertTrue(isinstance(mysig, MySignature))
1992 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
1993
1994 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1995 with self.subTest(pickle_ver=ver, subclass=True):
1996 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
1997 self.assertEqual(mysig, sig_pickled)
1998 self.assertTrue(isinstance(sig_pickled, MySignature))
1999 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2000 MyParameter))
2001
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002002 def test_signature_immutability(self):
2003 def test(a):
2004 pass
2005 sig = inspect.signature(test)
2006
2007 with self.assertRaises(AttributeError):
2008 sig.foo = 'bar'
2009
2010 with self.assertRaises(TypeError):
2011 sig.parameters['a'] = None
2012
2013 def test_signature_on_noarg(self):
2014 def test():
2015 pass
2016 self.assertEqual(self.signature(test), ((), ...))
2017
2018 def test_signature_on_wargs(self):
2019 def test(a, b:'foo') -> 123:
2020 pass
2021 self.assertEqual(self.signature(test),
2022 ((('a', ..., ..., "positional_or_keyword"),
2023 ('b', ..., 'foo', "positional_or_keyword")),
2024 123))
2025
2026 def test_signature_on_wkwonly(self):
2027 def test(*, a:float, b:str) -> int:
2028 pass
2029 self.assertEqual(self.signature(test),
2030 ((('a', ..., float, "keyword_only"),
2031 ('b', ..., str, "keyword_only")),
2032 int))
2033
2034 def test_signature_on_complex_args(self):
2035 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2036 pass
2037 self.assertEqual(self.signature(test),
2038 ((('a', ..., ..., "positional_or_keyword"),
2039 ('b', 10, 'foo', "positional_or_keyword"),
2040 ('args', ..., 'bar', "var_positional"),
2041 ('spam', ..., 'baz', "keyword_only"),
2042 ('ham', 123, ..., "keyword_only"),
2043 ('kwargs', ..., int, "var_keyword")),
2044 ...))
2045
Dong-hee Na378d7062017-05-18 04:00:51 +09002046 def test_signature_without_self(self):
2047 def test_args_only(*args): # NOQA
2048 pass
2049
2050 def test_args_kwargs_only(*args, **kwargs): # NOQA
2051 pass
2052
2053 class A:
2054 @classmethod
2055 def test_classmethod(*args): # NOQA
2056 pass
2057
2058 @staticmethod
2059 def test_staticmethod(*args): # NOQA
2060 pass
2061
2062 f1 = functools.partialmethod((test_classmethod), 1)
2063 f2 = functools.partialmethod((test_args_only), 1)
2064 f3 = functools.partialmethod((test_staticmethod), 1)
2065 f4 = functools.partialmethod((test_args_kwargs_only),1)
2066
2067 self.assertEqual(self.signature(test_args_only),
2068 ((('args', ..., ..., 'var_positional'),), ...))
2069 self.assertEqual(self.signature(test_args_kwargs_only),
2070 ((('args', ..., ..., 'var_positional'),
2071 ('kwargs', ..., ..., 'var_keyword')), ...))
2072 self.assertEqual(self.signature(A.f1),
2073 ((('args', ..., ..., 'var_positional'),), ...))
2074 self.assertEqual(self.signature(A.f2),
2075 ((('args', ..., ..., 'var_positional'),), ...))
2076 self.assertEqual(self.signature(A.f3),
2077 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002078 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002079 ((('args', ..., ..., 'var_positional'),
2080 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002081 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002082 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2083 "Signature information for builtins requires docstrings")
2084 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002085 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002086
Larry Hastings5c661892014-01-24 06:17:25 -08002087 def test_unbound_method(o):
2088 """Use this to test unbound methods (things that should have a self)"""
2089 signature = inspect.signature(o)
2090 self.assertTrue(isinstance(signature, inspect.Signature))
2091 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2092 return signature
2093
2094 def test_callable(o):
2095 """Use this to test bound methods or normal callables (things that don't expect self)"""
2096 signature = inspect.signature(o)
2097 self.assertTrue(isinstance(signature, inspect.Signature))
2098 if signature.parameters:
2099 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2100 return signature
2101
2102 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002103 def p(name): return signature.parameters[name].default
2104 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002105 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002106 self.assertEqual(p('d'), 3.14)
2107 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002108 self.assertEqual(p('n'), None)
2109 self.assertEqual(p('t'), True)
2110 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002111 self.assertEqual(p('local'), 3)
2112 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002113 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002114
Larry Hastings5c661892014-01-24 06:17:25 -08002115 test_callable(object)
2116
2117 # normal method
2118 # (PyMethodDescr_Type, "method_descriptor")
2119 test_unbound_method(_pickle.Pickler.dump)
2120 d = _pickle.Pickler(io.StringIO())
2121 test_callable(d.dump)
2122
2123 # static method
2124 test_callable(str.maketrans)
2125 test_callable('abc'.maketrans)
2126
2127 # class method
2128 test_callable(dict.fromkeys)
2129 test_callable({}.fromkeys)
2130
2131 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2132 test_unbound_method(type.__call__)
2133 test_unbound_method(int.__add__)
2134 test_callable((3).__add__)
2135
2136 # _PyMethodWrapper_Type
2137 # support for 'method-wrapper'
2138 test_callable(min.__call__)
2139
Larry Hastings2623c8c2014-02-08 22:15:29 -08002140 # This doesn't work now.
2141 # (We don't have a valid signature for "type" in 3.4)
2142 with self.assertRaisesRegex(ValueError, "no signature found"):
2143 class ThisWorksNow:
2144 __call__ = type
2145 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002146
Yury Selivanov056e2652014-03-02 12:25:27 -05002147 # Regression test for issue #20786
2148 test_unbound_method(dict.__delitem__)
2149 test_unbound_method(property.__delete__)
2150
Zachary Ware8ef887c2015-04-13 18:22:35 -05002151 # Regression test for issue #20586
2152 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2153
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002154 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002155 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2156 "Signature information for builtins requires docstrings")
2157 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002158 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002159 func = _testcapi.docstring_with_signature_with_defaults
2160
2161 def decorator(func):
2162 @functools.wraps(func)
2163 def wrapper(*args, **kwargs) -> int:
2164 return func(*args, **kwargs)
2165 return wrapper
2166
2167 decorated_func = decorator(func)
2168
2169 self.assertEqual(inspect.signature(func),
2170 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002171
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002172 def wrapper_like(*args, **kwargs) -> int: pass
2173 self.assertEqual(inspect.signature(decorated_func,
2174 follow_wrapped=False),
2175 inspect.signature(wrapper_like))
2176
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002177 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002178 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002179 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002180 with self.assertRaisesRegex(ValueError,
2181 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002182 inspect.signature(_testcapi.docstring_no_signature)
2183
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002184 with self.assertRaisesRegex(ValueError,
2185 'no signature found for builtin'):
2186 inspect.signature(str)
2187
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002188 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002189 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002190 inspect.signature(42)
2191
Yury Selivanov63da7c72014-01-31 14:48:37 -05002192 def test_signature_from_functionlike_object(self):
2193 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2194 pass
2195
2196 class funclike:
2197 # Has to be callable, and have correct
2198 # __code__, __annotations__, __defaults__, __name__,
2199 # and __kwdefaults__ attributes
2200
2201 def __init__(self, func):
2202 self.__name__ = func.__name__
2203 self.__code__ = func.__code__
2204 self.__annotations__ = func.__annotations__
2205 self.__defaults__ = func.__defaults__
2206 self.__kwdefaults__ = func.__kwdefaults__
2207 self.func = func
2208
2209 def __call__(self, *args, **kwargs):
2210 return self.func(*args, **kwargs)
2211
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002212 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002213
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002214 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002215 self.assertEqual(sig_funclike, sig_func)
2216
2217 sig_funclike = inspect.signature(funclike(func))
2218 self.assertEqual(sig_funclike, sig_func)
2219
2220 # If object is not a duck type of function, then
2221 # signature will try to get a signature for its '__call__'
2222 # method
2223 fl = funclike(func)
2224 del fl.__defaults__
2225 self.assertEqual(self.signature(fl),
2226 ((('args', ..., ..., "var_positional"),
2227 ('kwargs', ..., ..., "var_keyword")),
2228 ...))
2229
Yury Selivanova773de02014-02-21 18:30:53 -05002230 # Test with cython-like builtins:
2231 _orig_isdesc = inspect.ismethoddescriptor
2232 def _isdesc(obj):
2233 if hasattr(obj, '_builtinmock'):
2234 return True
2235 return _orig_isdesc(obj)
2236
2237 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2238 builtin_func = funclike(func)
2239 # Make sure that our mock setup is working
2240 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2241 builtin_func._builtinmock = True
2242 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2243 self.assertEqual(inspect.signature(builtin_func), sig_func)
2244
Yury Selivanov63da7c72014-01-31 14:48:37 -05002245 def test_signature_functionlike_class(self):
2246 # We only want to duck type function-like objects,
2247 # not classes.
2248
2249 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2250 pass
2251
2252 class funclike:
2253 def __init__(self, marker):
2254 pass
2255
2256 __name__ = func.__name__
2257 __code__ = func.__code__
2258 __annotations__ = func.__annotations__
2259 __defaults__ = func.__defaults__
2260 __kwdefaults__ = func.__kwdefaults__
2261
Yury Selivanov63da7c72014-01-31 14:48:37 -05002262 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2263
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002264 def test_signature_on_method(self):
2265 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002266 def __init__(*args):
2267 pass
2268 def m1(self, arg1, arg2=1) -> int:
2269 pass
2270 def m2(*args):
2271 pass
2272 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002273 pass
2274
Yury Selivanov62560fb2014-01-28 12:26:24 -05002275 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002276 ((('arg1', ..., ..., "positional_or_keyword"),
2277 ('arg2', 1, ..., "positional_or_keyword")),
2278 int))
2279
Yury Selivanov62560fb2014-01-28 12:26:24 -05002280 self.assertEqual(self.signature(Test().m2),
2281 ((('args', ..., ..., "var_positional"),),
2282 ...))
2283
2284 self.assertEqual(self.signature(Test),
2285 ((('args', ..., ..., "var_positional"),),
2286 ...))
2287
2288 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2289 self.signature(Test())
2290
Yury Selivanov46c759d2015-05-27 21:56:53 -04002291 def test_signature_wrapped_bound_method(self):
2292 # Issue 24298
2293 class Test:
2294 def m1(self, arg1, arg2=1) -> int:
2295 pass
2296 @functools.wraps(Test().m1)
2297 def m1d(*args, **kwargs):
2298 pass
2299 self.assertEqual(self.signature(m1d),
2300 ((('arg1', ..., ..., "positional_or_keyword"),
2301 ('arg2', 1, ..., "positional_or_keyword")),
2302 int))
2303
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002304 def test_signature_on_classmethod(self):
2305 class Test:
2306 @classmethod
2307 def foo(cls, arg1, *, arg2=1):
2308 pass
2309
2310 meth = Test().foo
2311 self.assertEqual(self.signature(meth),
2312 ((('arg1', ..., ..., "positional_or_keyword"),
2313 ('arg2', 1, ..., "keyword_only")),
2314 ...))
2315
2316 meth = Test.foo
2317 self.assertEqual(self.signature(meth),
2318 ((('arg1', ..., ..., "positional_or_keyword"),
2319 ('arg2', 1, ..., "keyword_only")),
2320 ...))
2321
2322 def test_signature_on_staticmethod(self):
2323 class Test:
2324 @staticmethod
2325 def foo(cls, *, arg):
2326 pass
2327
2328 meth = Test().foo
2329 self.assertEqual(self.signature(meth),
2330 ((('cls', ..., ..., "positional_or_keyword"),
2331 ('arg', ..., ..., "keyword_only")),
2332 ...))
2333
2334 meth = Test.foo
2335 self.assertEqual(self.signature(meth),
2336 ((('cls', ..., ..., "positional_or_keyword"),
2337 ('arg', ..., ..., "keyword_only")),
2338 ...))
2339
2340 def test_signature_on_partial(self):
2341 from functools import partial
2342
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002343 Parameter = inspect.Parameter
2344
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002345 def test():
2346 pass
2347
2348 self.assertEqual(self.signature(partial(test)), ((), ...))
2349
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002350 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002351 inspect.signature(partial(test, 1))
2352
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002353 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002354 inspect.signature(partial(test, a=1))
2355
2356 def test(a, b, *, c, d):
2357 pass
2358
2359 self.assertEqual(self.signature(partial(test)),
2360 ((('a', ..., ..., "positional_or_keyword"),
2361 ('b', ..., ..., "positional_or_keyword"),
2362 ('c', ..., ..., "keyword_only"),
2363 ('d', ..., ..., "keyword_only")),
2364 ...))
2365
2366 self.assertEqual(self.signature(partial(test, 1)),
2367 ((('b', ..., ..., "positional_or_keyword"),
2368 ('c', ..., ..., "keyword_only"),
2369 ('d', ..., ..., "keyword_only")),
2370 ...))
2371
2372 self.assertEqual(self.signature(partial(test, 1, c=2)),
2373 ((('b', ..., ..., "positional_or_keyword"),
2374 ('c', 2, ..., "keyword_only"),
2375 ('d', ..., ..., "keyword_only")),
2376 ...))
2377
2378 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2379 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002380 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002381 ('c', 2, ..., "keyword_only"),
2382 ('d', ..., ..., "keyword_only")),
2383 ...))
2384
2385 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002386 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002387 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002388 ('d', ..., ..., "keyword_only")),
2389 ...))
2390
2391 self.assertEqual(self.signature(partial(test, a=1)),
2392 ((('a', 1, ..., "keyword_only"),
2393 ('b', ..., ..., "keyword_only"),
2394 ('c', ..., ..., "keyword_only"),
2395 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002396 ...))
2397
2398 def test(a, *args, b, **kwargs):
2399 pass
2400
2401 self.assertEqual(self.signature(partial(test, 1)),
2402 ((('args', ..., ..., "var_positional"),
2403 ('b', ..., ..., "keyword_only"),
2404 ('kwargs', ..., ..., "var_keyword")),
2405 ...))
2406
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002407 self.assertEqual(self.signature(partial(test, a=1)),
2408 ((('a', 1, ..., "keyword_only"),
2409 ('b', ..., ..., "keyword_only"),
2410 ('kwargs', ..., ..., "var_keyword")),
2411 ...))
2412
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002413 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2414 ((('args', ..., ..., "var_positional"),
2415 ('b', ..., ..., "keyword_only"),
2416 ('kwargs', ..., ..., "var_keyword")),
2417 ...))
2418
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002419 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2420 ((('args', ..., ..., "var_positional"),
2421 ('b', ..., ..., "keyword_only"),
2422 ('kwargs', ..., ..., "var_keyword")),
2423 ...))
2424
2425 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2426 ((('args', ..., ..., "var_positional"),
2427 ('b', 0, ..., "keyword_only"),
2428 ('kwargs', ..., ..., "var_keyword")),
2429 ...))
2430
2431 self.assertEqual(self.signature(partial(test, b=0)),
2432 ((('a', ..., ..., "positional_or_keyword"),
2433 ('args', ..., ..., "var_positional"),
2434 ('b', 0, ..., "keyword_only"),
2435 ('kwargs', ..., ..., "var_keyword")),
2436 ...))
2437
2438 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2439 ((('a', ..., ..., "positional_or_keyword"),
2440 ('args', ..., ..., "var_positional"),
2441 ('b', 0, ..., "keyword_only"),
2442 ('kwargs', ..., ..., "var_keyword")),
2443 ...))
2444
2445 def test(a, b, c:int) -> 42:
2446 pass
2447
2448 sig = test.__signature__ = inspect.signature(test)
2449
2450 self.assertEqual(self.signature(partial(partial(test, 1))),
2451 ((('b', ..., ..., "positional_or_keyword"),
2452 ('c', ..., int, "positional_or_keyword")),
2453 42))
2454
2455 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2456 ((('c', ..., int, "positional_or_keyword"),),
2457 42))
2458
2459 psig = inspect.signature(partial(partial(test, 1), 2))
2460
2461 def foo(a):
2462 return a
2463 _foo = partial(partial(foo, a=10), a=20)
2464 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002465 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002466 ...))
2467 # check that we don't have any side-effects in signature(),
2468 # and the partial object is still functioning
2469 self.assertEqual(_foo(), 20)
2470
2471 def foo(a, b, c):
2472 return a, b, c
2473 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002474
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002475 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002476 ((('b', 30, ..., "keyword_only"),
2477 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002478 ...))
2479 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002480
2481 def foo(a, b, c, *, d):
2482 return a, b, c, d
2483 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2484 self.assertEqual(self.signature(_foo),
2485 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002486 ('b', 10, ..., "keyword_only"),
2487 ('c', 20, ..., "keyword_only"),
2488 ('d', 30, ..., "keyword_only"),
2489 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002490 ...))
2491 ba = inspect.signature(_foo).bind(a=200, b=11)
2492 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2493
2494 def foo(a=1, b=2, c=3):
2495 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002496 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2497
2498 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002499 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002500
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002501 ba = inspect.signature(_foo).bind(11, 12)
2502 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002503
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002504 ba = inspect.signature(_foo).bind(11, b=12)
2505 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002506
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002507 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002508 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2509
2510 _foo = partial(_foo, b=10, c=20)
2511 ba = inspect.signature(_foo).bind(12)
2512 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2513
2514
2515 def foo(a, b, c, d, **kwargs):
2516 pass
2517 sig = inspect.signature(foo)
2518 params = sig.parameters.copy()
2519 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2520 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2521 foo.__signature__ = inspect.Signature(params.values())
2522 sig = inspect.signature(foo)
2523 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2524
2525 self.assertEqual(self.signature(partial(foo, 1)),
2526 ((('b', ..., ..., 'positional_only'),
2527 ('c', ..., ..., 'positional_or_keyword'),
2528 ('d', ..., ..., 'positional_or_keyword'),
2529 ('kwargs', ..., ..., 'var_keyword')),
2530 ...))
2531
2532 self.assertEqual(self.signature(partial(foo, 1, 2)),
2533 ((('c', ..., ..., 'positional_or_keyword'),
2534 ('d', ..., ..., 'positional_or_keyword'),
2535 ('kwargs', ..., ..., 'var_keyword')),
2536 ...))
2537
2538 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2539 ((('d', ..., ..., 'positional_or_keyword'),
2540 ('kwargs', ..., ..., 'var_keyword')),
2541 ...))
2542
2543 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2544 ((('c', 3, ..., 'keyword_only'),
2545 ('d', ..., ..., 'keyword_only'),
2546 ('kwargs', ..., ..., 'var_keyword')),
2547 ...))
2548
2549 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2550 ((('b', ..., ..., 'positional_only'),
2551 ('c', 3, ..., 'keyword_only'),
2552 ('d', ..., ..., 'keyword_only'),
2553 ('kwargs', ..., ..., 'var_keyword')),
2554 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002555
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002556 def test_signature_on_partialmethod(self):
2557 from functools import partialmethod
2558
2559 class Spam:
2560 def test():
2561 pass
2562 ham = partialmethod(test)
2563
2564 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2565 inspect.signature(Spam.ham)
2566
2567 class Spam:
2568 def test(it, a, *, c) -> 'spam':
2569 pass
2570 ham = partialmethod(test, c=1)
2571
2572 self.assertEqual(self.signature(Spam.ham),
2573 ((('it', ..., ..., 'positional_or_keyword'),
2574 ('a', ..., ..., 'positional_or_keyword'),
2575 ('c', 1, ..., 'keyword_only')),
2576 'spam'))
2577
2578 self.assertEqual(self.signature(Spam().ham),
2579 ((('a', ..., ..., 'positional_or_keyword'),
2580 ('c', 1, ..., 'keyword_only')),
2581 'spam'))
2582
Miss Islington (bot)112f7992018-03-06 10:23:48 -08002583 class Spam:
2584 def test(self: 'anno', x):
2585 pass
2586
2587 g = partialmethod(test, 1)
2588
2589 self.assertEqual(self.signature(Spam.g),
2590 ((('self', ..., 'anno', 'positional_or_keyword'),),
2591 ...))
2592
Yury Selivanov0486f812014-01-29 12:18:59 -05002593 def test_signature_on_fake_partialmethod(self):
2594 def foo(a): pass
2595 foo._partialmethod = 'spam'
2596 self.assertEqual(str(inspect.signature(foo)), '(a)')
2597
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002598 def test_signature_on_decorated(self):
2599 import functools
2600
2601 def decorator(func):
2602 @functools.wraps(func)
2603 def wrapper(*args, **kwargs) -> int:
2604 return func(*args, **kwargs)
2605 return wrapper
2606
2607 class Foo:
2608 @decorator
2609 def bar(self, a, b):
2610 pass
2611
2612 self.assertEqual(self.signature(Foo.bar),
2613 ((('self', ..., ..., "positional_or_keyword"),
2614 ('a', ..., ..., "positional_or_keyword"),
2615 ('b', ..., ..., "positional_or_keyword")),
2616 ...))
2617
2618 self.assertEqual(self.signature(Foo().bar),
2619 ((('a', ..., ..., "positional_or_keyword"),
2620 ('b', ..., ..., "positional_or_keyword")),
2621 ...))
2622
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002623 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2624 ((('args', ..., ..., "var_positional"),
2625 ('kwargs', ..., ..., "var_keyword")),
2626 ...)) # functools.wraps will copy __annotations__
2627 # from "func" to "wrapper", hence no
2628 # return_annotation
2629
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002630 # Test that we handle method wrappers correctly
2631 def decorator(func):
2632 @functools.wraps(func)
2633 def wrapper(*args, **kwargs) -> int:
2634 return func(42, *args, **kwargs)
2635 sig = inspect.signature(func)
2636 new_params = tuple(sig.parameters.values())[1:]
2637 wrapper.__signature__ = sig.replace(parameters=new_params)
2638 return wrapper
2639
2640 class Foo:
2641 @decorator
2642 def __call__(self, a, b):
2643 pass
2644
2645 self.assertEqual(self.signature(Foo.__call__),
2646 ((('a', ..., ..., "positional_or_keyword"),
2647 ('b', ..., ..., "positional_or_keyword")),
2648 ...))
2649
2650 self.assertEqual(self.signature(Foo().__call__),
2651 ((('b', ..., ..., "positional_or_keyword"),),
2652 ...))
2653
Nick Coghlane8c45d62013-07-28 20:00:01 +10002654 # Test we handle __signature__ partway down the wrapper stack
2655 def wrapped_foo_call():
2656 pass
2657 wrapped_foo_call.__wrapped__ = Foo.__call__
2658
2659 self.assertEqual(self.signature(wrapped_foo_call),
2660 ((('a', ..., ..., "positional_or_keyword"),
2661 ('b', ..., ..., "positional_or_keyword")),
2662 ...))
2663
2664
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002665 def test_signature_on_class(self):
2666 class C:
2667 def __init__(self, a):
2668 pass
2669
2670 self.assertEqual(self.signature(C),
2671 ((('a', ..., ..., "positional_or_keyword"),),
2672 ...))
2673
2674 class CM(type):
2675 def __call__(cls, a):
2676 pass
2677 class C(metaclass=CM):
2678 def __init__(self, b):
2679 pass
2680
2681 self.assertEqual(self.signature(C),
2682 ((('a', ..., ..., "positional_or_keyword"),),
2683 ...))
2684
2685 class CM(type):
2686 def __new__(mcls, name, bases, dct, *, foo=1):
2687 return super().__new__(mcls, name, bases, dct)
2688 class C(metaclass=CM):
2689 def __init__(self, b):
2690 pass
2691
2692 self.assertEqual(self.signature(C),
2693 ((('b', ..., ..., "positional_or_keyword"),),
2694 ...))
2695
2696 self.assertEqual(self.signature(CM),
2697 ((('name', ..., ..., "positional_or_keyword"),
2698 ('bases', ..., ..., "positional_or_keyword"),
2699 ('dct', ..., ..., "positional_or_keyword"),
2700 ('foo', 1, ..., "keyword_only")),
2701 ...))
2702
2703 class CMM(type):
2704 def __new__(mcls, name, bases, dct, *, foo=1):
2705 return super().__new__(mcls, name, bases, dct)
2706 def __call__(cls, nm, bs, dt):
2707 return type(nm, bs, dt)
2708 class CM(type, metaclass=CMM):
2709 def __new__(mcls, name, bases, dct, *, bar=2):
2710 return super().__new__(mcls, name, bases, dct)
2711 class C(metaclass=CM):
2712 def __init__(self, b):
2713 pass
2714
2715 self.assertEqual(self.signature(CMM),
2716 ((('name', ..., ..., "positional_or_keyword"),
2717 ('bases', ..., ..., "positional_or_keyword"),
2718 ('dct', ..., ..., "positional_or_keyword"),
2719 ('foo', 1, ..., "keyword_only")),
2720 ...))
2721
2722 self.assertEqual(self.signature(CM),
2723 ((('nm', ..., ..., "positional_or_keyword"),
2724 ('bs', ..., ..., "positional_or_keyword"),
2725 ('dt', ..., ..., "positional_or_keyword")),
2726 ...))
2727
2728 self.assertEqual(self.signature(C),
2729 ((('b', ..., ..., "positional_or_keyword"),),
2730 ...))
2731
2732 class CM(type):
2733 def __init__(cls, name, bases, dct, *, bar=2):
2734 return super().__init__(name, bases, dct)
2735 class C(metaclass=CM):
2736 def __init__(self, b):
2737 pass
2738
2739 self.assertEqual(self.signature(CM),
2740 ((('name', ..., ..., "positional_or_keyword"),
2741 ('bases', ..., ..., "positional_or_keyword"),
2742 ('dct', ..., ..., "positional_or_keyword"),
2743 ('bar', 2, ..., "keyword_only")),
2744 ...))
2745
Yury Selivanov145dff82014-02-01 13:49:29 -05002746 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2747 "Signature information for builtins requires docstrings")
2748 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002749 # Test classes without user-defined __init__ or __new__
2750 class C: pass
2751 self.assertEqual(str(inspect.signature(C)), '()')
2752 class D(C): pass
2753 self.assertEqual(str(inspect.signature(D)), '()')
2754
2755 # Test meta-classes without user-defined __init__ or __new__
2756 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002757 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002758 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2759 self.assertEqual(inspect.signature(C), None)
2760 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2761 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002762
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002763 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2764 "Signature information for builtins requires docstrings")
2765 def test_signature_on_builtin_class(self):
2766 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2767 '(file, protocol=None, fix_imports=True)')
2768
2769 class P(_pickle.Pickler): pass
2770 class EmptyTrait: pass
2771 class P2(EmptyTrait, P): pass
2772 self.assertEqual(str(inspect.signature(P)),
2773 '(file, protocol=None, fix_imports=True)')
2774 self.assertEqual(str(inspect.signature(P2)),
2775 '(file, protocol=None, fix_imports=True)')
2776
2777 class P3(P2):
2778 def __init__(self, spam):
2779 pass
2780 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2781
2782 class MetaP(type):
2783 def __call__(cls, foo, bar):
2784 pass
2785 class P4(P2, metaclass=MetaP):
2786 pass
2787 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2788
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002789 def test_signature_on_callable_objects(self):
2790 class Foo:
2791 def __call__(self, a):
2792 pass
2793
2794 self.assertEqual(self.signature(Foo()),
2795 ((('a', ..., ..., "positional_or_keyword"),),
2796 ...))
2797
2798 class Spam:
2799 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002800 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002801 inspect.signature(Spam())
2802
2803 class Bar(Spam, Foo):
2804 pass
2805
2806 self.assertEqual(self.signature(Bar()),
2807 ((('a', ..., ..., "positional_or_keyword"),),
2808 ...))
2809
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002810 class Wrapped:
2811 pass
2812 Wrapped.__wrapped__ = lambda a: None
2813 self.assertEqual(self.signature(Wrapped),
2814 ((('a', ..., ..., "positional_or_keyword"),),
2815 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002816 # wrapper loop:
2817 Wrapped.__wrapped__ = Wrapped
2818 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2819 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002820
2821 def test_signature_on_lambdas(self):
2822 self.assertEqual(self.signature((lambda a=10: a)),
2823 ((('a', 10, ..., "positional_or_keyword"),),
2824 ...))
2825
2826 def test_signature_equality(self):
2827 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002828 self.assertFalse(inspect.signature(foo) == 42)
2829 self.assertTrue(inspect.signature(foo) != 42)
2830 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2831 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002832
2833 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002834 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2835 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002836 self.assertEqual(
2837 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002838
2839 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002840 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2841 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002842 self.assertNotEqual(
2843 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002844
2845 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002846 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2847 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002848 self.assertNotEqual(
2849 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002850
2851 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002852 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2853 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002854 self.assertNotEqual(
2855 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002856
2857 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002858 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2859 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002860 self.assertNotEqual(
2861 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002862
2863 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002864 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2865 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002866 self.assertNotEqual(
2867 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002868 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002869 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
2870 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002871 self.assertNotEqual(
2872 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002873
2874 def foo(*, a, b, c): pass
2875 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002876 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2877 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002878 self.assertEqual(
2879 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002880
2881 def foo(*, a=1, b, c): pass
2882 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002883 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2884 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002885 self.assertEqual(
2886 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002887
2888 def foo(pos, *, a=1, b, c): pass
2889 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002890 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2891 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002892 self.assertEqual(
2893 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002894
2895 def foo(pos, *, a, b, c): pass
2896 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002897 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2898 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002899 self.assertNotEqual(
2900 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002901
2902 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2903 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002904 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2905 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002906 self.assertEqual(
2907 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002908
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002909 def test_signature_hashable(self):
2910 S = inspect.Signature
2911 P = inspect.Parameter
2912
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002913 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002914 foo_sig = inspect.signature(foo)
2915
2916 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2917
2918 self.assertEqual(hash(foo_sig), hash(manual_sig))
2919 self.assertNotEqual(hash(foo_sig),
2920 hash(manual_sig.replace(return_annotation='spam')))
2921
2922 def bar(a) -> 1: pass
2923 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2924
2925 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002926 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002927 hash(inspect.signature(foo))
2928
2929 def foo(a) -> {}: pass
2930 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2931 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002932
2933 def test_signature_str(self):
2934 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2935 pass
2936 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09002937 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002938
2939 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2940 pass
2941 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09002942 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002943
2944 def foo():
2945 pass
2946 self.assertEqual(str(inspect.signature(foo)), '()')
2947
2948 def test_signature_str_positional_only(self):
2949 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002950 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002951
2952 def test(a_po, *, b, **kwargs):
2953 return a_po, kwargs
2954
2955 sig = inspect.signature(test)
2956 new_params = list(sig.parameters.values())
2957 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2958 test.__signature__ = sig.replace(parameters=new_params)
2959
2960 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002961 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002962
Yury Selivanov2393dca2014-01-27 15:07:58 -05002963 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2964 '(foo, /)')
2965
2966 self.assertEqual(str(S(parameters=[
2967 P('foo', P.POSITIONAL_ONLY),
2968 P('bar', P.VAR_KEYWORD)])),
2969 '(foo, /, **bar)')
2970
2971 self.assertEqual(str(S(parameters=[
2972 P('foo', P.POSITIONAL_ONLY),
2973 P('bar', P.VAR_POSITIONAL)])),
2974 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002975
2976 def test_signature_replace_anno(self):
2977 def test() -> 42:
2978 pass
2979
2980 sig = inspect.signature(test)
2981 sig = sig.replace(return_annotation=None)
2982 self.assertIs(sig.return_annotation, None)
2983 sig = sig.replace(return_annotation=sig.empty)
2984 self.assertIs(sig.return_annotation, sig.empty)
2985 sig = sig.replace(return_annotation=42)
2986 self.assertEqual(sig.return_annotation, 42)
2987 self.assertEqual(sig, inspect.signature(test))
2988
Yury Selivanov34ce99f2014-02-18 12:49:41 -05002989 def test_signature_on_mangled_parameters(self):
2990 class Spam:
2991 def foo(self, __p1:1=2, *, __p2:2=3):
2992 pass
2993 class Ham(Spam):
2994 pass
2995
2996 self.assertEqual(self.signature(Spam.foo),
2997 ((('self', ..., ..., "positional_or_keyword"),
2998 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2999 ('_Spam__p2', 3, 2, "keyword_only")),
3000 ...))
3001
3002 self.assertEqual(self.signature(Spam.foo),
3003 self.signature(Ham.foo))
3004
Yury Selivanovda396452014-03-27 12:09:24 -04003005 def test_signature_from_callable_python_obj(self):
3006 class MySignature(inspect.Signature): pass
3007 def foo(a, *, b:1): pass
3008 foo_sig = MySignature.from_callable(foo)
3009 self.assertTrue(isinstance(foo_sig, MySignature))
3010
3011 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3012 "Signature information for builtins requires docstrings")
3013 def test_signature_from_callable_builtin_obj(self):
3014 class MySignature(inspect.Signature): pass
3015 sig = MySignature.from_callable(_pickle.Pickler)
3016 self.assertTrue(isinstance(sig, MySignature))
3017
larryhastingsf36ba122018-01-28 11:13:09 -08003018 def test_signature_definition_order_preserved_on_kwonly(self):
3019 for fn in signatures_with_lexicographic_keyword_only_parameters():
3020 signature = inspect.signature(fn)
3021 l = list(signature.parameters)
3022 sorted_l = sorted(l)
3023 self.assertTrue(l)
3024 self.assertEqual(l, sorted_l)
3025 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3026 l = list(signature.parameters)
3027 self.assertEqual(l, unsorted_keyword_only_parameters)
3028
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003029
3030class TestParameterObject(unittest.TestCase):
3031 def test_signature_parameter_kinds(self):
3032 P = inspect.Parameter
3033 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3034 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3035
3036 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3037 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3038
3039 def test_signature_parameter_object(self):
3040 p = inspect.Parameter('foo', default=10,
3041 kind=inspect.Parameter.POSITIONAL_ONLY)
3042 self.assertEqual(p.name, 'foo')
3043 self.assertEqual(p.default, 10)
3044 self.assertIs(p.annotation, p.empty)
3045 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3046
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003047 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003048 inspect.Parameter('foo', default=10, kind='123')
3049
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003050 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003051 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3052
Yury Selivanov2393dca2014-01-27 15:07:58 -05003053 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003054 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3055
Yury Selivanov2393dca2014-01-27 15:07:58 -05003056 with self.assertRaisesRegex(ValueError,
3057 'is not a valid parameter name'):
3058 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3059
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003060 with self.assertRaisesRegex(ValueError,
3061 'is not a valid parameter name'):
3062 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3063
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003064 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003065 inspect.Parameter('a', default=42,
3066 kind=inspect.Parameter.VAR_KEYWORD)
3067
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003068 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003069 inspect.Parameter('a', default=42,
3070 kind=inspect.Parameter.VAR_POSITIONAL)
3071
3072 p = inspect.Parameter('a', default=42,
3073 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003074 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003075 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3076
3077 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003078 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003079
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003080 def test_signature_parameter_hashable(self):
3081 P = inspect.Parameter
3082 foo = P('foo', kind=P.POSITIONAL_ONLY)
3083 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3084 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3085 default=42)))
3086 self.assertNotEqual(hash(foo),
3087 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3088
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003089 def test_signature_parameter_equality(self):
3090 P = inspect.Parameter
3091 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3092
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003093 self.assertTrue(p == p)
3094 self.assertFalse(p != p)
3095 self.assertFalse(p == 42)
3096 self.assertTrue(p != 42)
3097 self.assertTrue(p == EqualsToAll())
3098 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003099
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003100 self.assertTrue(p == P('foo', default=42,
3101 kind=inspect.Parameter.KEYWORD_ONLY))
3102 self.assertFalse(p != P('foo', default=42,
3103 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003104
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003105 def test_signature_parameter_replace(self):
3106 p = inspect.Parameter('foo', default=42,
3107 kind=inspect.Parameter.KEYWORD_ONLY)
3108
3109 self.assertIsNot(p, p.replace())
3110 self.assertEqual(p, p.replace())
3111
3112 p2 = p.replace(annotation=1)
3113 self.assertEqual(p2.annotation, 1)
3114 p2 = p2.replace(annotation=p2.empty)
3115 self.assertEqual(p, p2)
3116
3117 p2 = p2.replace(name='bar')
3118 self.assertEqual(p2.name, 'bar')
3119 self.assertNotEqual(p2, p)
3120
Yury Selivanov2393dca2014-01-27 15:07:58 -05003121 with self.assertRaisesRegex(ValueError,
3122 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003123 p2 = p2.replace(name=p2.empty)
3124
3125 p2 = p2.replace(name='foo', default=None)
3126 self.assertIs(p2.default, None)
3127 self.assertNotEqual(p2, p)
3128
3129 p2 = p2.replace(name='foo', default=p2.empty)
3130 self.assertIs(p2.default, p2.empty)
3131
3132
3133 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3134 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3135 self.assertNotEqual(p2, p)
3136
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003137 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003138 p2 = p2.replace(kind=p2.empty)
3139
3140 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3141 self.assertEqual(p2, p)
3142
3143 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003144 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3145 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003146
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003147 @cpython_only
3148 def test_signature_parameter_implicit(self):
3149 with self.assertRaisesRegex(ValueError,
3150 'implicit arguments must be passed in as'):
3151 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3152
3153 param = inspect.Parameter(
3154 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3155 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3156 self.assertEqual(param.name, 'implicit0')
3157
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003158 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003159 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003160
3161 with self.assertRaises(AttributeError):
3162 p.foo = 'bar'
3163
3164 with self.assertRaises(AttributeError):
3165 p.kind = 123
3166
3167
3168class TestSignatureBind(unittest.TestCase):
3169 @staticmethod
3170 def call(func, *args, **kwargs):
3171 sig = inspect.signature(func)
3172 ba = sig.bind(*args, **kwargs)
3173 return func(*ba.args, **ba.kwargs)
3174
3175 def test_signature_bind_empty(self):
3176 def test():
3177 return 42
3178
3179 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003180 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003181 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003182 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003183 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003184 with self.assertRaisesRegex(
3185 TypeError, "got an unexpected keyword argument 'spam'"):
3186
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003187 self.call(test, spam=1)
3188
3189 def test_signature_bind_var(self):
3190 def test(*args, **kwargs):
3191 return args, kwargs
3192
3193 self.assertEqual(self.call(test), ((), {}))
3194 self.assertEqual(self.call(test, 1), ((1,), {}))
3195 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3196 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3197 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3198 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3199 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3200 ((1, 2), {'foo': 'bar'}))
3201
3202 def test_signature_bind_just_args(self):
3203 def test(a, b, c):
3204 return a, b, c
3205
3206 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3207
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003208 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003209 self.call(test, 1, 2, 3, 4)
3210
Yury Selivanov86872752015-05-19 00:27:49 -04003211 with self.assertRaisesRegex(TypeError,
3212 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003213 self.call(test, 1)
3214
Yury Selivanov86872752015-05-19 00:27:49 -04003215 with self.assertRaisesRegex(TypeError,
3216 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003217 self.call(test)
3218
3219 def test(a, b, c=10):
3220 return a, b, c
3221 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3222 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3223
3224 def test(a=1, b=2, c=3):
3225 return a, b, c
3226 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3227 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3228 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3229
3230 def test_signature_bind_varargs_order(self):
3231 def test(*args):
3232 return args
3233
3234 self.assertEqual(self.call(test), ())
3235 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3236
3237 def test_signature_bind_args_and_varargs(self):
3238 def test(a, b, c=3, *args):
3239 return a, b, c, args
3240
3241 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3242 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3243 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3244 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3245
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003246 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003247 "multiple values for argument 'c'"):
3248 self.call(test, 1, 2, 3, c=4)
3249
3250 def test_signature_bind_just_kwargs(self):
3251 def test(**kwargs):
3252 return kwargs
3253
3254 self.assertEqual(self.call(test), {})
3255 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3256 {'foo': 'bar', 'spam': 'ham'})
3257
3258 def test_signature_bind_args_and_kwargs(self):
3259 def test(a, b, c=3, **kwargs):
3260 return a, b, c, kwargs
3261
3262 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3263 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3264 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3265 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3266 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3267 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3268 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3269 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3270 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3271 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3272 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3273 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3274 (1, 2, 4, {'foo': 'bar'}))
3275 self.assertEqual(self.call(test, c=5, a=4, b=3),
3276 (4, 3, 5, {}))
3277
3278 def test_signature_bind_kwonly(self):
3279 def test(*, foo):
3280 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003281 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003282 'too many positional arguments'):
3283 self.call(test, 1)
3284 self.assertEqual(self.call(test, foo=1), 1)
3285
3286 def test(a, *, foo=1, bar):
3287 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003288 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003289 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003290 self.call(test, 1)
3291
3292 def test(foo, *, bar):
3293 return foo, bar
3294 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3295 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3296
Yury Selivanov86872752015-05-19 00:27:49 -04003297 with self.assertRaisesRegex(
3298 TypeError, "got an unexpected keyword argument 'spam'"):
3299
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003300 self.call(test, bar=2, foo=1, spam=10)
3301
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003302 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003303 'too many positional arguments'):
3304 self.call(test, 1, 2)
3305
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003306 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003307 'too many positional arguments'):
3308 self.call(test, 1, 2, bar=2)
3309
Yury Selivanov86872752015-05-19 00:27:49 -04003310 with self.assertRaisesRegex(
3311 TypeError, "got an unexpected keyword argument 'spam'"):
3312
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003313 self.call(test, 1, bar=2, spam='ham')
3314
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003315 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003316 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003317 self.call(test, 1)
3318
3319 def test(foo, *, bar, **bin):
3320 return foo, bar, bin
3321 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3322 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3323 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3324 (1, 2, {'spam': 'ham'}))
3325 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3326 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003327 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003328 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003329 self.call(test, spam='ham', bar=2)
3330 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3331 (1, 2, {'bin': 1, 'spam': 10}))
3332
3333 def test_signature_bind_arguments(self):
3334 def test(a, *args, b, z=100, **kwargs):
3335 pass
3336 sig = inspect.signature(test)
3337 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3338 # we won't have 'z' argument in the bound arguments object, as we didn't
3339 # pass it to the 'bind'
3340 self.assertEqual(tuple(ba.arguments.items()),
3341 (('a', 10), ('args', (20,)), ('b', 30),
3342 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3343 self.assertEqual(ba.kwargs,
3344 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3345 self.assertEqual(ba.args, (10, 20))
3346
3347 def test_signature_bind_positional_only(self):
3348 P = inspect.Parameter
3349
3350 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3351 return a_po, b_po, c_po, foo, bar, kwargs
3352
3353 sig = inspect.signature(test)
3354 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3355 for name in ('a_po', 'b_po', 'c_po'):
3356 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3357 new_sig = sig.replace(parameters=new_params.values())
3358 test.__signature__ = new_sig
3359
3360 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3361 (1, 2, 4, 5, 6, {}))
3362
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003363 self.assertEqual(self.call(test, 1, 2),
3364 (1, 2, 3, 42, 50, {}))
3365
3366 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3367 (1, 2, 3, 4, 5, {}))
3368
3369 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3370 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3371
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003372 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003373 self.call(test, 1, 2, c_po=4)
3374
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003375 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003376 self.call(test, a_po=1, b_po=2)
3377
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003378 def test_signature_bind_with_self_arg(self):
3379 # Issue #17071: one of the parameters is named "self
3380 def test(a, self, b):
3381 pass
3382 sig = inspect.signature(test)
3383 ba = sig.bind(1, 2, 3)
3384 self.assertEqual(ba.args, (1, 2, 3))
3385 ba = sig.bind(1, self=2, b=3)
3386 self.assertEqual(ba.args, (1, 2, 3))
3387
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003388 def test_signature_bind_vararg_name(self):
3389 def test(a, *args):
3390 return a, args
3391 sig = inspect.signature(test)
3392
Yury Selivanov86872752015-05-19 00:27:49 -04003393 with self.assertRaisesRegex(
3394 TypeError, "got an unexpected keyword argument 'args'"):
3395
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003396 sig.bind(a=0, args=1)
3397
3398 def test(*args, **kwargs):
3399 return args, kwargs
3400 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3401
3402 sig = inspect.signature(test)
3403 ba = sig.bind(args=1)
3404 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3405
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003406 @cpython_only
3407 def test_signature_bind_implicit_arg(self):
3408 # Issue #19611: getcallargs should work with set comprehensions
3409 def make_set():
3410 return {z * z for z in range(5)}
3411 setcomp_code = make_set.__code__.co_consts[1]
3412 setcomp_func = types.FunctionType(setcomp_code, {})
3413
3414 iterator = iter(range(5))
3415 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3416
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003417
3418class TestBoundArguments(unittest.TestCase):
3419 def test_signature_bound_arguments_unhashable(self):
3420 def foo(a): pass
3421 ba = inspect.signature(foo).bind(1)
3422
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003423 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003424 hash(ba)
3425
3426 def test_signature_bound_arguments_equality(self):
3427 def foo(a): pass
3428 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003429 self.assertTrue(ba == ba)
3430 self.assertFalse(ba != ba)
3431 self.assertTrue(ba == EqualsToAll())
3432 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003433
3434 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003435 self.assertTrue(ba == ba2)
3436 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003437
3438 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003439 self.assertFalse(ba == ba3)
3440 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003441 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003442 self.assertTrue(ba == ba3)
3443 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003444
3445 def bar(b): pass
3446 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003447 self.assertFalse(ba == ba4)
3448 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003449
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003450 def foo(*, a, b): pass
3451 sig = inspect.signature(foo)
3452 ba1 = sig.bind(a=1, b=2)
3453 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003454 self.assertTrue(ba1 == ba2)
3455 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003456
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003457 def test_signature_bound_arguments_pickle(self):
3458 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3459 sig = inspect.signature(foo)
3460 ba = sig.bind(20, 30, z={})
3461
3462 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3463 with self.subTest(pickle_ver=ver):
3464 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3465 self.assertEqual(ba, ba_pickled)
3466
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003467 def test_signature_bound_arguments_repr(self):
3468 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3469 sig = inspect.signature(foo)
3470 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003471 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003472
Yury Selivanovb907a512015-05-16 13:45:09 -04003473 def test_signature_bound_arguments_apply_defaults(self):
3474 def foo(a, b=1, *args, c:1={}, **kw): pass
3475 sig = inspect.signature(foo)
3476
3477 ba = sig.bind(20)
3478 ba.apply_defaults()
3479 self.assertEqual(
3480 list(ba.arguments.items()),
3481 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3482
3483 # Make sure that we preserve the order:
3484 # i.e. 'c' should be *before* 'kw'.
3485 ba = sig.bind(10, 20, 30, d=1)
3486 ba.apply_defaults()
3487 self.assertEqual(
3488 list(ba.arguments.items()),
3489 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3490
3491 # Make sure that BoundArguments produced by bind_partial()
3492 # are supported.
3493 def foo(a, b): pass
3494 sig = inspect.signature(foo)
3495 ba = sig.bind_partial(20)
3496 ba.apply_defaults()
3497 self.assertEqual(
3498 list(ba.arguments.items()),
3499 [('a', 20)])
3500
3501 # Test no args
3502 def foo(): pass
3503 sig = inspect.signature(foo)
3504 ba = sig.bind()
3505 ba.apply_defaults()
3506 self.assertEqual(list(ba.arguments.items()), [])
3507
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003508 # Make sure a no-args binding still acquires proper defaults.
3509 def foo(a='spam'): pass
3510 sig = inspect.signature(foo)
3511 ba = sig.bind()
3512 ba.apply_defaults()
3513 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3514
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003515
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003516class TestSignaturePrivateHelpers(unittest.TestCase):
3517 def test_signature_get_bound_param(self):
3518 getter = inspect._signature_get_bound_param
3519
3520 self.assertEqual(getter('($self)'), 'self')
3521 self.assertEqual(getter('($self, obj)'), 'self')
3522 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3523
Larry Hastings2623c8c2014-02-08 22:15:29 -08003524 def _strip_non_python_syntax(self, input,
3525 clean_signature, self_parameter, last_positional_only):
3526 computed_clean_signature, \
3527 computed_self_parameter, \
3528 computed_last_positional_only = \
3529 inspect._signature_strip_non_python_syntax(input)
3530 self.assertEqual(computed_clean_signature, clean_signature)
3531 self.assertEqual(computed_self_parameter, self_parameter)
3532 self.assertEqual(computed_last_positional_only, last_positional_only)
3533
3534 def test_signature_strip_non_python_syntax(self):
3535 self._strip_non_python_syntax(
3536 "($module, /, path, mode, *, dir_fd=None, " +
3537 "effective_ids=False,\n follow_symlinks=True)",
3538 "(module, path, mode, *, dir_fd=None, " +
3539 "effective_ids=False, follow_symlinks=True)",
3540 0,
3541 0)
3542
3543 self._strip_non_python_syntax(
3544 "($module, word, salt, /)",
3545 "(module, word, salt)",
3546 0,
3547 2)
3548
3549 self._strip_non_python_syntax(
3550 "(x, y=None, z=None, /)",
3551 "(x, y=None, z=None)",
3552 None,
3553 2)
3554
3555 self._strip_non_python_syntax(
3556 "(x, y=None, z=None)",
3557 "(x, y=None, z=None)",
3558 None,
3559 None)
3560
3561 self._strip_non_python_syntax(
3562 "(x,\n y=None,\n z = None )",
3563 "(x, y=None, z=None)",
3564 None,
3565 None)
3566
3567 self._strip_non_python_syntax(
3568 "",
3569 "",
3570 None,
3571 None)
3572
3573 self._strip_non_python_syntax(
3574 None,
3575 None,
3576 None,
3577 None)
3578
Nick Coghlan9c680b02015-04-13 12:54:54 -04003579class TestSignatureDefinitions(unittest.TestCase):
3580 # This test case provides a home for checking that particular APIs
3581 # have signatures available for introspection
3582
3583 @cpython_only
3584 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3585 "Signature information for builtins requires docstrings")
3586 def test_builtins_have_signatures(self):
3587 # This checks all builtin callables in CPython have signatures
3588 # A few have signatures Signature can't yet handle, so we skip those
3589 # since they will have to wait until PEP 457 adds the required
3590 # introspection support to the inspect module
3591 # Some others also haven't been converted yet for various other
3592 # reasons, so we also skip those for the time being, but design
3593 # the test to fail in order to indicate when it needs to be
3594 # updated.
3595 no_signature = set()
3596 # These need PEP 457 groups
3597 needs_groups = {"range", "slice", "dir", "getattr",
3598 "next", "iter", "vars"}
3599 no_signature |= needs_groups
3600 # These need PEP 457 groups or a signature change to accept None
3601 needs_semantic_update = {"round"}
3602 no_signature |= needs_semantic_update
3603 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003604 needs_varargs = {"breakpoint", "min", "max", "print",
3605 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003606 no_signature |= needs_varargs
3607 # These simply weren't covered in the initial AC conversion
3608 # for builtin callables
3609 not_converted_yet = {"open", "__import__"}
3610 no_signature |= not_converted_yet
3611 # These builtin types are expected to provide introspection info
3612 types_with_signatures = set()
3613 # Check the signatures we expect to be there
3614 ns = vars(builtins)
3615 for name, obj in sorted(ns.items()):
3616 if not callable(obj):
3617 continue
3618 # The builtin types haven't been converted to AC yet
3619 if isinstance(obj, type) and (name not in types_with_signatures):
3620 # Note that this also skips all the exception types
3621 no_signature.add(name)
3622 if (name in no_signature):
3623 # Not yet converted
3624 continue
3625 with self.subTest(builtin=name):
3626 self.assertIsNotNone(inspect.signature(obj))
3627 # Check callables that haven't been converted don't claim a signature
3628 # This ensures this test will start failing as more signatures are
3629 # added, so the affected items can be moved into the scope of the
3630 # regression test above
3631 for name in no_signature:
3632 with self.subTest(builtin=name):
3633 self.assertIsNone(obj.__text_signature__)
3634
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003635
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003636class NTimesUnwrappable:
3637 def __init__(self, n):
3638 self.n = n
3639 self._next = None
3640
3641 @property
3642 def __wrapped__(self):
3643 if self.n <= 0:
3644 raise Exception("Unwrapped too many times")
3645 if self._next is None:
3646 self._next = NTimesUnwrappable(self.n - 1)
3647 return self._next
3648
Nick Coghlane8c45d62013-07-28 20:00:01 +10003649class TestUnwrap(unittest.TestCase):
3650
3651 def test_unwrap_one(self):
3652 def func(a, b):
3653 return a + b
3654 wrapper = functools.lru_cache(maxsize=20)(func)
3655 self.assertIs(inspect.unwrap(wrapper), func)
3656
3657 def test_unwrap_several(self):
3658 def func(a, b):
3659 return a + b
3660 wrapper = func
3661 for __ in range(10):
3662 @functools.wraps(wrapper)
3663 def wrapper():
3664 pass
3665 self.assertIsNot(wrapper.__wrapped__, func)
3666 self.assertIs(inspect.unwrap(wrapper), func)
3667
3668 def test_stop(self):
3669 def func1(a, b):
3670 return a + b
3671 @functools.wraps(func1)
3672 def func2():
3673 pass
3674 @functools.wraps(func2)
3675 def wrapper():
3676 pass
3677 func2.stop_here = 1
3678 unwrapped = inspect.unwrap(wrapper,
3679 stop=(lambda f: hasattr(f, "stop_here")))
3680 self.assertIs(unwrapped, func2)
3681
3682 def test_cycle(self):
3683 def func1(): pass
3684 func1.__wrapped__ = func1
3685 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3686 inspect.unwrap(func1)
3687
3688 def func2(): pass
3689 func2.__wrapped__ = func1
3690 func1.__wrapped__ = func2
3691 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3692 inspect.unwrap(func1)
3693 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3694 inspect.unwrap(func2)
3695
3696 def test_unhashable(self):
3697 def func(): pass
3698 func.__wrapped__ = None
3699 class C:
3700 __hash__ = None
3701 __wrapped__ = func
3702 self.assertIsNone(inspect.unwrap(C()))
3703
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003704 def test_recursion_limit(self):
3705 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3706 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3707 inspect.unwrap(obj)
3708
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003709class TestMain(unittest.TestCase):
3710 def test_only_source(self):
3711 module = importlib.import_module('unittest')
3712 rc, out, err = assert_python_ok('-m', 'inspect',
3713 'unittest')
3714 lines = out.decode().splitlines()
3715 # ignore the final newline
3716 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3717 self.assertEqual(err, b'')
3718
Yury Selivanov42407ab2014-06-23 10:23:50 -07003719 def test_custom_getattr(self):
3720 def foo():
3721 pass
3722 foo.__signature__ = 42
3723 with self.assertRaises(TypeError):
3724 inspect.signature(foo)
3725
Brett Cannon634a8fc2013-10-02 10:25:42 -04003726 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003727 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003728 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003729 rc, out, err = assert_python_ok('-m', 'inspect',
3730 'concurrent.futures:ThreadPoolExecutor')
3731 lines = out.decode().splitlines()
3732 # ignore the final newline
3733 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003734 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003735 self.assertEqual(err, b'')
3736
3737 def test_builtins(self):
3738 module = importlib.import_module('unittest')
3739 _, out, err = assert_python_failure('-m', 'inspect',
3740 'sys')
3741 lines = err.decode().splitlines()
3742 self.assertEqual(lines, ["Can't get info for builtin modules."])
3743
3744 def test_details(self):
3745 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003746 args = support.optim_args_from_interpreter_flags()
3747 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003748 'unittest', '--details')
3749 output = out.decode()
3750 # Just a quick sanity check on the output
3751 self.assertIn(module.__name__, output)
3752 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003753 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003754 self.assertEqual(err, b'')
3755
3756
Yury Selivanovef1e7502014-12-08 16:05:34 -05003757class TestReload(unittest.TestCase):
3758
3759 src_before = textwrap.dedent("""\
3760def foo():
3761 print("Bla")
3762 """)
3763
3764 src_after = textwrap.dedent("""\
3765def foo():
3766 print("Oh no!")
3767 """)
3768
3769 def assertInspectEqual(self, path, source):
3770 inspected_src = inspect.getsource(source)
3771 with open(path) as src:
3772 self.assertEqual(
3773 src.read().splitlines(True),
3774 inspected_src.splitlines(True)
3775 )
3776
3777 def test_getsource_reload(self):
3778 # see issue 1218234
3779 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3780 module = importlib.import_module(name)
3781 self.assertInspectEqual(path, module)
3782 with open(path, 'w') as src:
3783 src.write(self.src_after)
3784 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003785
Nick Coghlane8c45d62013-07-28 20:00:01 +10003786
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003787def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003788 run_unittest(
3789 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3790 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3791 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003792 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003793 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003794 TestBoundArguments, TestSignaturePrivateHelpers,
3795 TestSignatureDefinitions,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003796 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
3797 TestGetCoroutineState
Michael Foord95fc51d2010-11-20 15:07:30 +00003798 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003799
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003800if __name__ == "__main__":
3801 test_main()