blob: 8b701614962b45996c1abf2024edefb93bb8cf90 [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:
Miss Islington (bot)60b82742018-06-11 13:44:16 -0700715 with self.assertWarns(DeprecationWarning):
716 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
717 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500718
Christian Heimes3795b532007-11-08 13:48:53 +0000719 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
720 varkw_e=None, defaults_e=None,
721 kwonlyargs_e=[], kwonlydefaults_e=None,
722 ann_e={}, formatted=None):
723 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
724 inspect.getfullargspec(routine)
725 self.assertEqual(args, args_e)
726 self.assertEqual(varargs, varargs_e)
727 self.assertEqual(varkw, varkw_e)
728 self.assertEqual(defaults, defaults_e)
729 self.assertEqual(kwonlyargs, kwonlyargs_e)
730 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
731 self.assertEqual(ann, ann_e)
732 if formatted is not None:
Miss Islington (bot)60b82742018-06-11 13:44:16 -0700733 with self.assertWarns(DeprecationWarning):
734 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
735 kwonlyargs, kwonlydefaults, ann),
Christian Heimes3795b532007-11-08 13:48:53 +0000736 formatted)
737
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500738 def test_getargspec(self):
739 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
740
741 self.assertArgSpecEquals(mod.spam,
742 ['a', 'b', 'c', 'd', 'e', 'f'],
743 'g', 'h', (3, 4, 5),
744 '(a, b, c, d=3, e=4, f=5, *g, **h)')
745
746 self.assertRaises(ValueError, self.assertArgSpecEquals,
747 mod2.keyworded, [])
748
749 self.assertRaises(ValueError, self.assertArgSpecEquals,
750 mod2.annotated, [])
751 self.assertRaises(ValueError, self.assertArgSpecEquals,
752 mod2.keyword_only_arg, [])
753
754
Christian Heimes3795b532007-11-08 13:48:53 +0000755 def test_getfullargspec(self):
756 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
757 kwonlyargs_e=['arg2'],
758 kwonlydefaults_e={'arg2':1},
759 formatted='(*arg1, arg2=1)')
760
761 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000762 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000763 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000764 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
765 kwonlyargs_e=['arg'],
766 formatted='(*, arg)')
767
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500768 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500769 # Issue 20684: low level introspection API must ignore __wrapped__
770 @functools.wraps(mod.spam)
771 def ham(x, y):
772 pass
773 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500774 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500775 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
776 self.assertFullArgSpecEquals(functools.partial(ham),
777 ['x', 'y'], formatted='(x, y)')
778 # Other variants
779 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500780 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
781 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500782 class C:
783 @functools.wraps(mod.spam)
784 def ham(self, x, y):
785 pass
786 pham = functools.partialmethod(ham)
787 @functools.wraps(mod.spam)
788 def __call__(self, x, y):
789 pass
790 check_method(C())
791 check_method(C.ham)
792 check_method(C().ham)
793 check_method(C.pham)
794 check_method(C().pham)
795
796 class C_new:
797 @functools.wraps(mod.spam)
798 def __new__(self, x, y):
799 pass
800 check_method(C_new)
801
802 class C_init:
803 @functools.wraps(mod.spam)
804 def __init__(self, x, y):
805 pass
806 check_method(C_init)
807
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500808 def test_getfullargspec_signature_attr(self):
809 def test():
810 pass
811 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
812 test.__signature__ = inspect.Signature(parameters=(spam_param,))
813
814 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
815
Yury Selivanov4cb93912014-01-29 11:54:12 -0500816 def test_getfullargspec_signature_annos(self):
817 def test(a:'spam') -> 'ham': pass
818 spec = inspect.getfullargspec(test)
819 self.assertEqual(test.__annotations__, spec.annotations)
820
821 def test(): pass
822 spec = inspect.getfullargspec(test)
823 self.assertEqual(test.__annotations__, spec.annotations)
824
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500825 @unittest.skipIf(MISSING_C_DOCSTRINGS,
826 "Signature information for builtins requires docstrings")
827 def test_getfullargspec_builtin_methods(self):
828 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
829 args_e=['self', 'obj'], formatted='(self, obj)')
830
831 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
832 args_e=['self', 'obj'], formatted='(self, obj)')
833
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500834 self.assertFullArgSpecEquals(
835 os.stat,
836 args_e=['path'],
837 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
838 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
839 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
840
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200841 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500842 @unittest.skipIf(MISSING_C_DOCSTRINGS,
843 "Signature information for builtins requires docstrings")
844 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200845 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500846 builtin = _testcapi.docstring_with_signature_with_defaults
847 spec = inspect.getfullargspec(builtin)
848 self.assertEqual(spec.defaults[0], 'avocado')
849
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200850 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500851 @unittest.skipIf(MISSING_C_DOCSTRINGS,
852 "Signature information for builtins requires docstrings")
853 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200854 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500855 builtin = _testcapi.docstring_no_signature
856 with self.assertRaises(TypeError):
857 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000858
larryhastingsf36ba122018-01-28 11:13:09 -0800859 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
860 for fn in signatures_with_lexicographic_keyword_only_parameters():
861 signature = inspect.getfullargspec(fn)
862 l = list(signature.kwonlyargs)
863 sorted_l = sorted(l)
864 self.assertTrue(l)
865 self.assertEqual(l, sorted_l)
866 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
867 l = list(signature.kwonlyargs)
868 self.assertEqual(l, unsorted_keyword_only_parameters)
869
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500870 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000871 class A(object):
872 def m(self):
873 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500874 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000875
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000876 def test_classify_newstyle(self):
877 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000878
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000879 def s(): pass
880 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000881
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000882 def c(cls): pass
883 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000884
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000885 def getp(self): pass
886 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000887
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000888 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000889
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000890 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000891
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000892 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000893
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100894 dd = _BrokenDataDescriptor()
895 md = _BrokenMethodDescriptor()
896
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000897 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500898
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +0200899 self.assertIn(('__new__', 'static method', object), attrs,
900 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500901 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
902
Benjamin Peterson577473f2010-01-19 00:09:57 +0000903 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
904 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
905 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000906 self.assertIn(('m', 'method', A), attrs,
907 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000908 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
909 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100910 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
911 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000912
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000913 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000914
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000915 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000916
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000917 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000918 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
919 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
920 self.assertIn(('p', 'property', A), attrs, 'missing property')
921 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
922 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
923 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100924 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
925 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000926
927
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000928 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000929
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000930 def m(self): pass
931 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000932
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000933 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000934 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
935 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
936 self.assertIn(('p', 'property', A), attrs, 'missing property')
937 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
938 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
939 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100940 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
941 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000942
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000943 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000944
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000945 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000946
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000947 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000948 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
949 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
950 self.assertIn(('p', 'property', A), attrs, 'missing property')
951 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
952 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
953 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100954 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
955 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
956
957 def test_classify_builtin_types(self):
958 # Simple sanity check that all built-in types can have their
959 # attributes classified.
960 for name in dir(__builtins__):
961 builtin = getattr(__builtins__, name)
962 if isinstance(builtin, type):
963 inspect.classify_class_attrs(builtin)
964
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +0200965 attrs = attrs_wo_objs(bool)
966 self.assertIn(('__new__', 'static method', bool), attrs,
967 'missing __new__')
968 self.assertIn(('from_bytes', 'class method', int), attrs,
969 'missing class method')
970 self.assertIn(('to_bytes', 'method', int), attrs,
971 'missing plain method')
972 self.assertIn(('__add__', 'method', int), attrs,
973 'missing plain method')
974 self.assertIn(('__and__', 'method', bool), attrs,
975 'missing plain method')
976
Ethan Furman63c141c2013-10-18 00:27:39 -0700977 def test_classify_DynamicClassAttribute(self):
978 class Meta(type):
979 def __getattr__(self, name):
980 if name == 'ham':
981 return 'spam'
982 return super().__getattr__(name)
983 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700984 @types.DynamicClassAttribute
985 def ham(self):
986 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700987 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
988 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700989 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700990 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
991
Yury Selivanovbf341fb2015-05-21 15:41:57 -0400992 def test_classify_overrides_bool(self):
993 class NoBool(object):
994 def __eq__(self, other):
995 return NoBool()
996
997 def __bool__(self):
998 raise NotImplementedError(
999 "This object does not specify a boolean value")
1000
1001 class HasNB(object):
1002 dd = NoBool()
1003
1004 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1005 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1006
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001007 def test_classify_metaclass_class_attribute(self):
1008 class Meta(type):
1009 fish = 'slap'
1010 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001011 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001012 class Class(metaclass=Meta):
1013 pass
1014 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1015 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1016
Ethan Furman63c141c2013-10-18 00:27:39 -07001017 def test_classify_VirtualAttribute(self):
1018 class Meta(type):
1019 def __dir__(cls):
1020 return ['__class__', '__module__', '__name__', 'BOOM']
1021 def __getattr__(self, name):
1022 if name =='BOOM':
1023 return 42
1024 return super().__getattr(name)
1025 class Class(metaclass=Meta):
1026 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001027 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001028 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1029
1030 def test_classify_VirtualAttribute_multi_classes(self):
1031 class Meta1(type):
1032 def __dir__(cls):
1033 return ['__class__', '__module__', '__name__', 'one']
1034 def __getattr__(self, name):
1035 if name =='one':
1036 return 1
1037 return super().__getattr__(name)
1038 class Meta2(type):
1039 def __dir__(cls):
1040 return ['__class__', '__module__', '__name__', 'two']
1041 def __getattr__(self, name):
1042 if name =='two':
1043 return 2
1044 return super().__getattr__(name)
1045 class Meta3(Meta1, Meta2):
1046 def __dir__(cls):
1047 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1048 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1049 def __getattr__(self, name):
1050 if name =='three':
1051 return 3
1052 return super().__getattr__(name)
1053 class Class1(metaclass=Meta1):
1054 pass
1055 class Class2(Class1, metaclass=Meta3):
1056 pass
1057
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001058 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1059 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1060 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001061 cca = inspect.classify_class_attrs(Class2)
1062 for sf in (should_find1, should_find2, should_find3):
1063 self.assertIn(sf, cca)
1064
1065 def test_classify_class_attrs_with_buggy_dir(self):
1066 class M(type):
1067 def __dir__(cls):
1068 return ['__class__', '__name__', 'missing']
1069 class C(metaclass=M):
1070 pass
1071 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1072 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001073
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001074 def test_getmembers_descriptors(self):
1075 class A(object):
1076 dd = _BrokenDataDescriptor()
1077 md = _BrokenMethodDescriptor()
1078
1079 def pred_wrapper(pred):
1080 # A quick'n'dirty way to discard standard attributes of new-style
1081 # classes.
1082 class Empty(object):
1083 pass
1084 def wrapped(x):
1085 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1086 return False
1087 return pred(x)
1088 return wrapped
1089
1090 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1091 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1092
1093 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1094 [('md', A.__dict__['md'])])
1095 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1096 [('dd', A.__dict__['dd'])])
1097
1098 class B(A):
1099 pass
1100
1101 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1102 [('md', A.__dict__['md'])])
1103 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1104 [('dd', A.__dict__['dd'])])
1105
Antoine Pitrou0c603812012-01-18 17:40:18 +01001106 def test_getmembers_method(self):
1107 class B:
1108 def f(self):
1109 pass
1110
1111 self.assertIn(('f', B.f), inspect.getmembers(B))
1112 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1113 b = B()
1114 self.assertIn(('f', b.f), inspect.getmembers(b))
1115 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1116
Ethan Furmane03ea372013-09-25 07:14:41 -07001117 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001118 class M(type):
1119 def __getattr__(cls, name):
1120 if name == 'eggs':
1121 return 'scrambled'
1122 return super().__getattr__(name)
1123 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001124 @types.DynamicClassAttribute
1125 def eggs(self):
1126 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001127 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1128 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1129
1130 def test_getmembers_with_buggy_dir(self):
1131 class M(type):
1132 def __dir__(cls):
1133 return ['__class__', '__name__', 'missing']
1134 class C(metaclass=M):
1135 pass
1136 attrs = [a[0] for a in inspect.getmembers(C)]
1137 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001138
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001139
Nick Coghlan2f92e542012-06-23 19:39:55 +10001140_global_ref = object()
1141class TestGetClosureVars(unittest.TestCase):
1142
1143 def test_name_resolution(self):
1144 # Basic test of the 4 different resolution mechanisms
1145 def f(nonlocal_ref):
1146 def g(local_ref):
1147 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1148 return g
1149 _arg = object()
1150 nonlocal_vars = {"nonlocal_ref": _arg}
1151 global_vars = {"_global_ref": _global_ref}
1152 builtin_vars = {"print": print}
1153 unbound_names = {"unbound_ref"}
1154 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1155 builtin_vars, unbound_names)
1156 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1157
1158 def test_generator_closure(self):
1159 def f(nonlocal_ref):
1160 def g(local_ref):
1161 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1162 yield
1163 return g
1164 _arg = object()
1165 nonlocal_vars = {"nonlocal_ref": _arg}
1166 global_vars = {"_global_ref": _global_ref}
1167 builtin_vars = {"print": print}
1168 unbound_names = {"unbound_ref"}
1169 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1170 builtin_vars, unbound_names)
1171 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1172
1173 def test_method_closure(self):
1174 class C:
1175 def f(self, nonlocal_ref):
1176 def g(local_ref):
1177 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1178 return g
1179 _arg = object()
1180 nonlocal_vars = {"nonlocal_ref": _arg}
1181 global_vars = {"_global_ref": _global_ref}
1182 builtin_vars = {"print": print}
1183 unbound_names = {"unbound_ref"}
1184 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1185 builtin_vars, unbound_names)
1186 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1187
1188 def test_nonlocal_vars(self):
1189 # More complex tests of nonlocal resolution
1190 def _nonlocal_vars(f):
1191 return inspect.getclosurevars(f).nonlocals
1192
1193 def make_adder(x):
1194 def add(y):
1195 return x + y
1196 return add
1197
1198 def curry(func, arg1):
1199 return lambda arg2: func(arg1, arg2)
1200
1201 def less_than(a, b):
1202 return a < b
1203
1204 # The infamous Y combinator.
1205 def Y(le):
1206 def g(f):
1207 return le(lambda x: f(f)(x))
1208 Y.g_ref = g
1209 return g(g)
1210
1211 def check_y_combinator(func):
1212 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1213
1214 inc = make_adder(1)
1215 add_two = make_adder(2)
1216 greater_than_five = curry(less_than, 5)
1217
1218 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1219 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1220 self.assertEqual(_nonlocal_vars(greater_than_five),
1221 {'arg1': 5, 'func': less_than})
1222 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1223 {'x': 3})
1224 Y(check_y_combinator)
1225
1226 def test_getclosurevars_empty(self):
1227 def foo(): pass
1228 _empty = inspect.ClosureVars({}, {}, {}, set())
1229 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1230 self.assertEqual(inspect.getclosurevars(foo), _empty)
1231
1232 def test_getclosurevars_error(self):
1233 class T: pass
1234 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1235 self.assertRaises(TypeError, inspect.getclosurevars, list)
1236 self.assertRaises(TypeError, inspect.getclosurevars, {})
1237
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001238 def _private_globals(self):
1239 code = """def f(): print(path)"""
1240 ns = {}
1241 exec(code, ns)
1242 return ns["f"], ns
1243
1244 def test_builtins_fallback(self):
1245 f, ns = self._private_globals()
1246 ns.pop("__builtins__", None)
1247 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1248 self.assertEqual(inspect.getclosurevars(f), expected)
1249
1250 def test_builtins_as_dict(self):
1251 f, ns = self._private_globals()
1252 ns["__builtins__"] = {"path":1}
1253 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1254 self.assertEqual(inspect.getclosurevars(f), expected)
1255
1256 def test_builtins_as_module(self):
1257 f, ns = self._private_globals()
1258 ns["__builtins__"] = os
1259 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1260 self.assertEqual(inspect.getclosurevars(f), expected)
1261
Nick Coghlan2f92e542012-06-23 19:39:55 +10001262
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001263class TestGetcallargsFunctions(unittest.TestCase):
1264
1265 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1266 locs = dict(locs or {}, func=func)
1267 r1 = eval('func(%s)' % call_params_string, None, locs)
1268 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1269 locs)
1270 self.assertEqual(r1, r2)
1271
1272 def assertEqualException(self, func, call_param_string, locs=None):
1273 locs = dict(locs or {}, func=func)
1274 try:
1275 eval('func(%s)' % call_param_string, None, locs)
1276 except Exception as e:
1277 ex1 = e
1278 else:
1279 self.fail('Exception not raised')
1280 try:
1281 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1282 locs)
1283 except Exception as e:
1284 ex2 = e
1285 else:
1286 self.fail('Exception not raised')
1287 self.assertIs(type(ex1), type(ex2))
1288 self.assertEqual(str(ex1), str(ex2))
1289 del ex1, ex2
1290
1291 def makeCallable(self, signature):
1292 """Create a function that returns its locals()"""
1293 code = "lambda %s: locals()"
1294 return eval(code % signature)
1295
1296 def test_plain(self):
1297 f = self.makeCallable('a, b=1')
1298 self.assertEqualCallArgs(f, '2')
1299 self.assertEqualCallArgs(f, '2, 3')
1300 self.assertEqualCallArgs(f, 'a=2')
1301 self.assertEqualCallArgs(f, 'b=3, a=2')
1302 self.assertEqualCallArgs(f, '2, b=3')
1303 # expand *iterable / **mapping
1304 self.assertEqualCallArgs(f, '*(2,)')
1305 self.assertEqualCallArgs(f, '*[2]')
1306 self.assertEqualCallArgs(f, '*(2, 3)')
1307 self.assertEqualCallArgs(f, '*[2, 3]')
1308 self.assertEqualCallArgs(f, '**{"a":2}')
1309 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1310 self.assertEqualCallArgs(f, '2, **{"b":3}')
1311 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1312 # expand UserList / UserDict
1313 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1314 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1315 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1316 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1317 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1318
1319 def test_varargs(self):
1320 f = self.makeCallable('a, b=1, *c')
1321 self.assertEqualCallArgs(f, '2')
1322 self.assertEqualCallArgs(f, '2, 3')
1323 self.assertEqualCallArgs(f, '2, 3, 4')
1324 self.assertEqualCallArgs(f, '*(2,3,4)')
1325 self.assertEqualCallArgs(f, '2, *[3,4]')
1326 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1327
1328 def test_varkw(self):
1329 f = self.makeCallable('a, b=1, **c')
1330 self.assertEqualCallArgs(f, 'a=2')
1331 self.assertEqualCallArgs(f, '2, b=3, c=4')
1332 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1333 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1334 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1335 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1336 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1337 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1338 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1339
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001340 def test_varkw_only(self):
1341 # issue11256:
1342 f = self.makeCallable('**c')
1343 self.assertEqualCallArgs(f, '')
1344 self.assertEqualCallArgs(f, 'a=1')
1345 self.assertEqualCallArgs(f, 'a=1, b=2')
1346 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1347 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1348 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1349
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001350 def test_keyword_only(self):
1351 f = self.makeCallable('a=3, *, c, d=2')
1352 self.assertEqualCallArgs(f, 'c=3')
1353 self.assertEqualCallArgs(f, 'c=3, a=3')
1354 self.assertEqualCallArgs(f, 'a=2, c=4')
1355 self.assertEqualCallArgs(f, '4, c=4')
1356 self.assertEqualException(f, '')
1357 self.assertEqualException(f, '3')
1358 self.assertEqualException(f, 'a=3')
1359 self.assertEqualException(f, 'd=4')
1360
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001361 f = self.makeCallable('*, c, d=2')
1362 self.assertEqualCallArgs(f, 'c=3')
1363 self.assertEqualCallArgs(f, 'c=3, d=4')
1364 self.assertEqualCallArgs(f, 'd=4, c=3')
1365
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001366 def test_multiple_features(self):
1367 f = self.makeCallable('a, b=2, *f, **g')
1368 self.assertEqualCallArgs(f, '2, 3, 7')
1369 self.assertEqualCallArgs(f, '2, 3, x=8')
1370 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1371 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1372 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1373 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1374 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1375 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1376 '(4,[5,6])]), **collections.UserDict('
1377 'y=9, z=10)')
1378
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001379 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1380 self.assertEqualCallArgs(f, '2, 3, x=8')
1381 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1382 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1383 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1384 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1385 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1386 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1387 '(4,[5,6])]), q=0, **collections.UserDict('
1388 'y=9, z=10)')
1389
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001390 def test_errors(self):
1391 f0 = self.makeCallable('')
1392 f1 = self.makeCallable('a, b')
1393 f2 = self.makeCallable('a, b=1')
1394 # f0 takes no arguments
1395 self.assertEqualException(f0, '1')
1396 self.assertEqualException(f0, 'x=1')
1397 self.assertEqualException(f0, '1,x=1')
1398 # f1 takes exactly 2 arguments
1399 self.assertEqualException(f1, '')
1400 self.assertEqualException(f1, '1')
1401 self.assertEqualException(f1, 'a=2')
1402 self.assertEqualException(f1, 'b=3')
1403 # f2 takes at least 1 argument
1404 self.assertEqualException(f2, '')
1405 self.assertEqualException(f2, 'b=3')
1406 for f in f1, f2:
1407 # f1/f2 takes exactly/at most 2 arguments
1408 self.assertEqualException(f, '2, 3, 4')
1409 self.assertEqualException(f, '1, 2, 3, a=1')
1410 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001411 # XXX: success of this one depends on dict order
1412 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001413 # f got an unexpected keyword argument
1414 self.assertEqualException(f, 'c=2')
1415 self.assertEqualException(f, '2, c=3')
1416 self.assertEqualException(f, '2, 3, c=4')
1417 self.assertEqualException(f, '2, c=4, b=3')
1418 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1419 # f got multiple values for keyword argument
1420 self.assertEqualException(f, '1, a=2')
1421 self.assertEqualException(f, '1, **{"a":2}')
1422 self.assertEqualException(f, '1, 2, b=3')
1423 # XXX: Python inconsistency
1424 # - for functions and bound methods: unexpected keyword 'c'
1425 # - for unbound methods: multiple values for keyword 'a'
1426 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001427 # issue11256:
1428 f3 = self.makeCallable('**c')
1429 self.assertEqualException(f3, '1, 2')
1430 self.assertEqualException(f3, '1, 2, a=1, b=2')
1431 f4 = self.makeCallable('*, a, b=0')
1432 self.assertEqualException(f3, '1, 2')
1433 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001434
Yury Selivanov875df202014-03-27 18:23:03 -04001435 # issue #20816: getcallargs() fails to iterate over non-existent
1436 # kwonlydefaults and raises a wrong TypeError
1437 def f5(*, a): pass
1438 with self.assertRaisesRegex(TypeError,
1439 'missing 1 required keyword-only'):
1440 inspect.getcallargs(f5)
1441
1442
Yury Selivanovdccfa132014-03-27 18:42:52 -04001443 # issue20817:
1444 def f6(a, b, c):
1445 pass
1446 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1447 inspect.getcallargs(f6)
1448
Miss Islington (bot)cb055bc2018-05-29 08:43:54 -07001449 # bpo-33197
1450 with self.assertRaisesRegex(ValueError,
1451 'variadic keyword parameters cannot'
1452 ' have default values'):
1453 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1454 default=42)
1455 with self.assertRaisesRegex(ValueError,
1456 "value 5 is not a valid Parameter.kind"):
1457 inspect.Parameter("bar", kind=5, default=42)
1458
1459 with self.assertRaisesRegex(TypeError,
1460 'name must be a str, not a int'):
1461 inspect.Parameter(123, kind=4)
1462
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001463class TestGetcallargsMethods(TestGetcallargsFunctions):
1464
1465 def setUp(self):
1466 class Foo(object):
1467 pass
1468 self.cls = Foo
1469 self.inst = Foo()
1470
1471 def makeCallable(self, signature):
1472 assert 'self' not in signature
1473 mk = super(TestGetcallargsMethods, self).makeCallable
1474 self.cls.method = mk('self, ' + signature)
1475 return self.inst.method
1476
1477class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1478
1479 def makeCallable(self, signature):
1480 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1481 return self.cls.method
1482
1483 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1484 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1485 *self._getAssertEqualParams(func, call_params_string, locs))
1486
1487 def assertEqualException(self, func, call_params_string, locs=None):
1488 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1489 *self._getAssertEqualParams(func, call_params_string, locs))
1490
1491 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1492 assert 'inst' not in call_params_string
1493 locs = dict(locs or {}, inst=self.inst)
1494 return (func, 'inst,' + call_params_string, locs)
1495
Michael Foord95fc51d2010-11-20 15:07:30 +00001496
1497class TestGetattrStatic(unittest.TestCase):
1498
1499 def test_basic(self):
1500 class Thing(object):
1501 x = object()
1502
1503 thing = Thing()
1504 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1505 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1506 with self.assertRaises(AttributeError):
1507 inspect.getattr_static(thing, 'y')
1508
1509 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1510
1511 def test_inherited(self):
1512 class Thing(object):
1513 x = object()
1514 class OtherThing(Thing):
1515 pass
1516
1517 something = OtherThing()
1518 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1519
1520 def test_instance_attr(self):
1521 class Thing(object):
1522 x = 2
1523 def __init__(self, x):
1524 self.x = x
1525 thing = Thing(3)
1526 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1527 del thing.x
1528 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1529
1530 def test_property(self):
1531 class Thing(object):
1532 @property
1533 def x(self):
1534 raise AttributeError("I'm pretending not to exist")
1535 thing = Thing()
1536 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1537
Ezio Melotti75cbd732011-04-28 00:59:29 +03001538 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001539 class descriptor(object):
1540 def __get__(*_):
1541 raise AttributeError("I'm pretending not to exist")
1542 desc = descriptor()
1543 class Thing(object):
1544 x = desc
1545 thing = Thing()
1546 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1547
1548 def test_classAttribute(self):
1549 class Thing(object):
1550 x = object()
1551
1552 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1553
Ethan Furmane03ea372013-09-25 07:14:41 -07001554 def test_classVirtualAttribute(self):
1555 class Thing(object):
1556 @types.DynamicClassAttribute
1557 def x(self):
1558 return self._x
1559 _x = object()
1560
1561 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1562
Michael Foord95fc51d2010-11-20 15:07:30 +00001563 def test_inherited_classattribute(self):
1564 class Thing(object):
1565 x = object()
1566 class OtherThing(Thing):
1567 pass
1568
1569 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1570
1571 def test_slots(self):
1572 class Thing(object):
1573 y = 'bar'
1574 __slots__ = ['x']
1575 def __init__(self):
1576 self.x = 'foo'
1577 thing = Thing()
1578 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1579 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1580
1581 del thing.x
1582 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1583
1584 def test_metaclass(self):
1585 class meta(type):
1586 attr = 'foo'
1587 class Thing(object, metaclass=meta):
1588 pass
1589 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1590
1591 class sub(meta):
1592 pass
1593 class OtherThing(object, metaclass=sub):
1594 x = 3
1595 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1596
1597 class OtherOtherThing(OtherThing):
1598 pass
1599 # this test is odd, but it was added as it exposed a bug
1600 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1601
1602 def test_no_dict_no_slots(self):
1603 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1604 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1605
1606 def test_no_dict_no_slots_instance_member(self):
1607 # returns descriptor
1608 with open(__file__) as handle:
1609 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1610
1611 def test_inherited_slots(self):
1612 # returns descriptor
1613 class Thing(object):
1614 __slots__ = ['x']
1615 def __init__(self):
1616 self.x = 'foo'
1617
1618 class OtherThing(Thing):
1619 pass
1620 # it would be nice if this worked...
1621 # we get the descriptor instead of the instance attribute
1622 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1623
1624 def test_descriptor(self):
1625 class descriptor(object):
1626 def __get__(self, instance, owner):
1627 return 3
1628 class Foo(object):
1629 d = descriptor()
1630
1631 foo = Foo()
1632
1633 # for a non data descriptor we return the instance attribute
1634 foo.__dict__['d'] = 1
1635 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1636
Mike53f7a7c2017-12-14 14:04:53 +03001637 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001638 # descriptor
1639 descriptor.__set__ = lambda s, i, v: None
1640 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1641
1642
1643 def test_metaclass_with_descriptor(self):
1644 class descriptor(object):
1645 def __get__(self, instance, owner):
1646 return 3
1647 class meta(type):
1648 d = descriptor()
1649 class Thing(object, metaclass=meta):
1650 pass
1651 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1652
1653
Michael Foordcc7ebb82010-11-20 16:20:16 +00001654 def test_class_as_property(self):
1655 class Base(object):
1656 foo = 3
1657
1658 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001659 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001660 @property
1661 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001662 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001663 return object
1664
Michael Foord35184ed2010-11-20 16:58:30 +00001665 instance = Something()
1666 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1667 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001668 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1669
Michael Foorde5162652010-11-20 16:40:44 +00001670 def test_mro_as_property(self):
1671 class Meta(type):
1672 @property
1673 def __mro__(self):
1674 return (object,)
1675
1676 class Base(object):
1677 foo = 3
1678
1679 class Something(Base, metaclass=Meta):
1680 pass
1681
1682 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1683 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1684
Michael Foorddcebe0f2011-03-15 19:20:44 -04001685 def test_dict_as_property(self):
1686 test = self
1687 test.called = False
1688
1689 class Foo(dict):
1690 a = 3
1691 @property
1692 def __dict__(self):
1693 test.called = True
1694 return {}
1695
1696 foo = Foo()
1697 foo.a = 4
1698 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1699 self.assertFalse(test.called)
1700
1701 def test_custom_object_dict(self):
1702 test = self
1703 test.called = False
1704
1705 class Custom(dict):
1706 def get(self, key, default=None):
1707 test.called = True
1708 super().get(key, default)
1709
1710 class Foo(object):
1711 a = 3
1712 foo = Foo()
1713 foo.__dict__ = Custom()
1714 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1715 self.assertFalse(test.called)
1716
1717 def test_metaclass_dict_as_property(self):
1718 class Meta(type):
1719 @property
1720 def __dict__(self):
1721 self.executed = True
1722
1723 class Thing(metaclass=Meta):
1724 executed = False
1725
1726 def __init__(self):
1727 self.spam = 42
1728
1729 instance = Thing()
1730 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1731 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001732
Michael Foorda51623b2011-12-18 22:01:40 +00001733 def test_module(self):
1734 sentinel = object()
1735 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1736 sentinel)
1737
Michael Foord3ba95f82011-12-22 01:13:37 +00001738 def test_metaclass_with_metaclass_with_dict_as_property(self):
1739 class MetaMeta(type):
1740 @property
1741 def __dict__(self):
1742 self.executed = True
1743 return dict(spam=42)
1744
1745 class Meta(type, metaclass=MetaMeta):
1746 executed = False
1747
1748 class Thing(metaclass=Meta):
1749 pass
1750
1751 with self.assertRaises(AttributeError):
1752 inspect.getattr_static(Thing, "spam")
1753 self.assertFalse(Thing.executed)
1754
Nick Coghlane0f04652010-11-21 03:44:04 +00001755class TestGetGeneratorState(unittest.TestCase):
1756
1757 def setUp(self):
1758 def number_generator():
1759 for number in range(5):
1760 yield number
1761 self.generator = number_generator()
1762
1763 def _generatorstate(self):
1764 return inspect.getgeneratorstate(self.generator)
1765
1766 def test_created(self):
1767 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1768
1769 def test_suspended(self):
1770 next(self.generator)
1771 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1772
1773 def test_closed_after_exhaustion(self):
1774 for i in self.generator:
1775 pass
1776 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1777
1778 def test_closed_after_immediate_exception(self):
1779 with self.assertRaises(RuntimeError):
1780 self.generator.throw(RuntimeError)
1781 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1782
1783 def test_running(self):
1784 # As mentioned on issue #10220, checking for the RUNNING state only
1785 # makes sense inside the generator itself.
1786 # The following generator checks for this by using the closure's
1787 # reference to self and the generator state checking helper method
1788 def running_check_generator():
1789 for number in range(5):
1790 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1791 yield number
1792 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1793 self.generator = running_check_generator()
1794 # Running up to the first yield
1795 next(self.generator)
1796 # Running after the first yield
1797 next(self.generator)
1798
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001799 def test_easy_debugging(self):
1800 # repr() and str() of a generator state should contain the state name
1801 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1802 for name in names:
1803 state = getattr(inspect, name)
1804 self.assertIn(name, repr(state))
1805 self.assertIn(name, str(state))
1806
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001807 def test_getgeneratorlocals(self):
1808 def each(lst, a=None):
1809 b=(1, 2, 3)
1810 for v in lst:
1811 if v == 3:
1812 c = 12
1813 yield v
1814
1815 numbers = each([1, 2, 3])
1816 self.assertEqual(inspect.getgeneratorlocals(numbers),
1817 {'a': None, 'lst': [1, 2, 3]})
1818 next(numbers)
1819 self.assertEqual(inspect.getgeneratorlocals(numbers),
1820 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1821 'b': (1, 2, 3)})
1822 next(numbers)
1823 self.assertEqual(inspect.getgeneratorlocals(numbers),
1824 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1825 'b': (1, 2, 3)})
1826 next(numbers)
1827 self.assertEqual(inspect.getgeneratorlocals(numbers),
1828 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1829 'b': (1, 2, 3), 'c': 12})
1830 try:
1831 next(numbers)
1832 except StopIteration:
1833 pass
1834 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1835
1836 def test_getgeneratorlocals_empty(self):
1837 def yield_one():
1838 yield 1
1839 one = yield_one()
1840 self.assertEqual(inspect.getgeneratorlocals(one), {})
1841 try:
1842 next(one)
1843 except StopIteration:
1844 pass
1845 self.assertEqual(inspect.getgeneratorlocals(one), {})
1846
1847 def test_getgeneratorlocals_error(self):
1848 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1849 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1850 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1851 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1852
Nick Coghlane0f04652010-11-21 03:44:04 +00001853
Yury Selivanov5376ba92015-06-22 12:19:30 -04001854class TestGetCoroutineState(unittest.TestCase):
1855
1856 def setUp(self):
1857 @types.coroutine
1858 def number_coroutine():
1859 for number in range(5):
1860 yield number
1861 async def coroutine():
1862 await number_coroutine()
1863 self.coroutine = coroutine()
1864
1865 def tearDown(self):
1866 self.coroutine.close()
1867
1868 def _coroutinestate(self):
1869 return inspect.getcoroutinestate(self.coroutine)
1870
1871 def test_created(self):
1872 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1873
1874 def test_suspended(self):
1875 self.coroutine.send(None)
1876 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1877
1878 def test_closed_after_exhaustion(self):
1879 while True:
1880 try:
1881 self.coroutine.send(None)
1882 except StopIteration:
1883 break
1884
1885 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1886
1887 def test_closed_after_immediate_exception(self):
1888 with self.assertRaises(RuntimeError):
1889 self.coroutine.throw(RuntimeError)
1890 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1891
1892 def test_easy_debugging(self):
1893 # repr() and str() of a coroutine state should contain the state name
1894 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1895 for name in names:
1896 state = getattr(inspect, name)
1897 self.assertIn(name, repr(state))
1898 self.assertIn(name, str(state))
1899
1900 def test_getcoroutinelocals(self):
1901 @types.coroutine
1902 def gencoro():
1903 yield
1904
1905 gencoro = gencoro()
1906 async def func(a=None):
1907 b = 'spam'
1908 await gencoro
1909
1910 coro = func()
1911 self.assertEqual(inspect.getcoroutinelocals(coro),
1912 {'a': None, 'gencoro': gencoro})
1913 coro.send(None)
1914 self.assertEqual(inspect.getcoroutinelocals(coro),
1915 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
1916
1917
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001918class MySignature(inspect.Signature):
1919 # Top-level to make it picklable;
1920 # used in test_signature_object_pickle
1921 pass
1922
1923class MyParameter(inspect.Parameter):
1924 # Top-level to make it picklable;
1925 # used in test_signature_object_pickle
1926 pass
1927
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001928
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001929
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001930class TestSignatureObject(unittest.TestCase):
1931 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04001932 def signature(func, **kw):
1933 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001934 return (tuple((param.name,
1935 (... if param.default is param.empty else param.default),
1936 (... if param.annotation is param.empty
1937 else param.annotation),
1938 str(param.kind).lower())
1939 for param in sig.parameters.values()),
1940 (... if sig.return_annotation is sig.empty
1941 else sig.return_annotation))
1942
1943 def test_signature_object(self):
1944 S = inspect.Signature
1945 P = inspect.Parameter
1946
1947 self.assertEqual(str(S()), '()')
1948
Yury Selivanov07a9e452014-01-29 10:58:16 -05001949 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001950 pass
1951 sig = inspect.signature(test)
1952 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001953 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001954 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001955 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001956 args = sig.parameters['args']
1957 ko = sig.parameters['ko']
1958 kwargs = sig.parameters['kwargs']
1959
1960 S((po, pk, args, ko, kwargs))
1961
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001962 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001963 S((pk, po, args, ko, kwargs))
1964
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001965 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001966 S((po, args, pk, ko, kwargs))
1967
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001968 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001969 S((args, po, pk, ko, kwargs))
1970
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001971 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001972 S((po, pk, args, kwargs, ko))
1973
1974 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001975 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001976 S((po, pk, args, kwargs2, ko))
1977
Yury Selivanov07a9e452014-01-29 10:58:16 -05001978 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1979 S((pod, po))
1980
1981 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1982 S((po, pkd, pk))
1983
1984 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1985 S((pkd, pk))
1986
Yury Selivanov374375d2014-03-27 12:41:53 -04001987 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04001988 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04001989
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001990 def test_signature_object_pickle(self):
1991 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
1992 foo_partial = functools.partial(foo, a=1)
1993
1994 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001995
1996 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
1997 with self.subTest(pickle_ver=ver, subclass=False):
1998 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
1999 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002000
2001 # Test that basic sub-classing works
2002 sig = inspect.signature(foo)
2003 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2004 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2005 mysig = MySignature().replace(parameters=myparams.values(),
2006 return_annotation=sig.return_annotation)
2007 self.assertTrue(isinstance(mysig, MySignature))
2008 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2009
2010 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2011 with self.subTest(pickle_ver=ver, subclass=True):
2012 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2013 self.assertEqual(mysig, sig_pickled)
2014 self.assertTrue(isinstance(sig_pickled, MySignature))
2015 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2016 MyParameter))
2017
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002018 def test_signature_immutability(self):
2019 def test(a):
2020 pass
2021 sig = inspect.signature(test)
2022
2023 with self.assertRaises(AttributeError):
2024 sig.foo = 'bar'
2025
2026 with self.assertRaises(TypeError):
2027 sig.parameters['a'] = None
2028
2029 def test_signature_on_noarg(self):
2030 def test():
2031 pass
2032 self.assertEqual(self.signature(test), ((), ...))
2033
2034 def test_signature_on_wargs(self):
2035 def test(a, b:'foo') -> 123:
2036 pass
2037 self.assertEqual(self.signature(test),
2038 ((('a', ..., ..., "positional_or_keyword"),
2039 ('b', ..., 'foo', "positional_or_keyword")),
2040 123))
2041
2042 def test_signature_on_wkwonly(self):
2043 def test(*, a:float, b:str) -> int:
2044 pass
2045 self.assertEqual(self.signature(test),
2046 ((('a', ..., float, "keyword_only"),
2047 ('b', ..., str, "keyword_only")),
2048 int))
2049
2050 def test_signature_on_complex_args(self):
2051 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2052 pass
2053 self.assertEqual(self.signature(test),
2054 ((('a', ..., ..., "positional_or_keyword"),
2055 ('b', 10, 'foo', "positional_or_keyword"),
2056 ('args', ..., 'bar', "var_positional"),
2057 ('spam', ..., 'baz', "keyword_only"),
2058 ('ham', 123, ..., "keyword_only"),
2059 ('kwargs', ..., int, "var_keyword")),
2060 ...))
2061
Dong-hee Na378d7062017-05-18 04:00:51 +09002062 def test_signature_without_self(self):
2063 def test_args_only(*args): # NOQA
2064 pass
2065
2066 def test_args_kwargs_only(*args, **kwargs): # NOQA
2067 pass
2068
2069 class A:
2070 @classmethod
2071 def test_classmethod(*args): # NOQA
2072 pass
2073
2074 @staticmethod
2075 def test_staticmethod(*args): # NOQA
2076 pass
2077
2078 f1 = functools.partialmethod((test_classmethod), 1)
2079 f2 = functools.partialmethod((test_args_only), 1)
2080 f3 = functools.partialmethod((test_staticmethod), 1)
2081 f4 = functools.partialmethod((test_args_kwargs_only),1)
2082
2083 self.assertEqual(self.signature(test_args_only),
2084 ((('args', ..., ..., 'var_positional'),), ...))
2085 self.assertEqual(self.signature(test_args_kwargs_only),
2086 ((('args', ..., ..., 'var_positional'),
2087 ('kwargs', ..., ..., 'var_keyword')), ...))
2088 self.assertEqual(self.signature(A.f1),
2089 ((('args', ..., ..., 'var_positional'),), ...))
2090 self.assertEqual(self.signature(A.f2),
2091 ((('args', ..., ..., 'var_positional'),), ...))
2092 self.assertEqual(self.signature(A.f3),
2093 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002094 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002095 ((('args', ..., ..., 'var_positional'),
2096 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002097 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002098 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2099 "Signature information for builtins requires docstrings")
2100 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002101 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002102
Larry Hastings5c661892014-01-24 06:17:25 -08002103 def test_unbound_method(o):
2104 """Use this to test unbound methods (things that should have a self)"""
2105 signature = inspect.signature(o)
2106 self.assertTrue(isinstance(signature, inspect.Signature))
2107 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2108 return signature
2109
2110 def test_callable(o):
2111 """Use this to test bound methods or normal callables (things that don't expect self)"""
2112 signature = inspect.signature(o)
2113 self.assertTrue(isinstance(signature, inspect.Signature))
2114 if signature.parameters:
2115 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2116 return signature
2117
2118 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002119 def p(name): return signature.parameters[name].default
2120 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002121 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002122 self.assertEqual(p('d'), 3.14)
2123 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002124 self.assertEqual(p('n'), None)
2125 self.assertEqual(p('t'), True)
2126 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002127 self.assertEqual(p('local'), 3)
2128 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002129 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002130
Larry Hastings5c661892014-01-24 06:17:25 -08002131 test_callable(object)
2132
2133 # normal method
2134 # (PyMethodDescr_Type, "method_descriptor")
2135 test_unbound_method(_pickle.Pickler.dump)
2136 d = _pickle.Pickler(io.StringIO())
2137 test_callable(d.dump)
2138
2139 # static method
2140 test_callable(str.maketrans)
2141 test_callable('abc'.maketrans)
2142
2143 # class method
2144 test_callable(dict.fromkeys)
2145 test_callable({}.fromkeys)
2146
2147 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2148 test_unbound_method(type.__call__)
2149 test_unbound_method(int.__add__)
2150 test_callable((3).__add__)
2151
2152 # _PyMethodWrapper_Type
2153 # support for 'method-wrapper'
2154 test_callable(min.__call__)
2155
Larry Hastings2623c8c2014-02-08 22:15:29 -08002156 # This doesn't work now.
2157 # (We don't have a valid signature for "type" in 3.4)
2158 with self.assertRaisesRegex(ValueError, "no signature found"):
2159 class ThisWorksNow:
2160 __call__ = type
2161 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002162
Yury Selivanov056e2652014-03-02 12:25:27 -05002163 # Regression test for issue #20786
2164 test_unbound_method(dict.__delitem__)
2165 test_unbound_method(property.__delete__)
2166
Zachary Ware8ef887c2015-04-13 18:22:35 -05002167 # Regression test for issue #20586
2168 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2169
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002170 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002171 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2172 "Signature information for builtins requires docstrings")
2173 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002174 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002175 func = _testcapi.docstring_with_signature_with_defaults
2176
2177 def decorator(func):
2178 @functools.wraps(func)
2179 def wrapper(*args, **kwargs) -> int:
2180 return func(*args, **kwargs)
2181 return wrapper
2182
2183 decorated_func = decorator(func)
2184
2185 self.assertEqual(inspect.signature(func),
2186 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002187
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002188 def wrapper_like(*args, **kwargs) -> int: pass
2189 self.assertEqual(inspect.signature(decorated_func,
2190 follow_wrapped=False),
2191 inspect.signature(wrapper_like))
2192
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002193 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002194 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002195 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002196 with self.assertRaisesRegex(ValueError,
2197 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002198 inspect.signature(_testcapi.docstring_no_signature)
2199
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002200 with self.assertRaisesRegex(ValueError,
2201 'no signature found for builtin'):
2202 inspect.signature(str)
2203
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002204 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002205 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002206 inspect.signature(42)
2207
Yury Selivanov63da7c72014-01-31 14:48:37 -05002208 def test_signature_from_functionlike_object(self):
2209 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2210 pass
2211
2212 class funclike:
2213 # Has to be callable, and have correct
2214 # __code__, __annotations__, __defaults__, __name__,
2215 # and __kwdefaults__ attributes
2216
2217 def __init__(self, func):
2218 self.__name__ = func.__name__
2219 self.__code__ = func.__code__
2220 self.__annotations__ = func.__annotations__
2221 self.__defaults__ = func.__defaults__
2222 self.__kwdefaults__ = func.__kwdefaults__
2223 self.func = func
2224
2225 def __call__(self, *args, **kwargs):
2226 return self.func(*args, **kwargs)
2227
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002228 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002229
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002230 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002231 self.assertEqual(sig_funclike, sig_func)
2232
2233 sig_funclike = inspect.signature(funclike(func))
2234 self.assertEqual(sig_funclike, sig_func)
2235
2236 # If object is not a duck type of function, then
2237 # signature will try to get a signature for its '__call__'
2238 # method
2239 fl = funclike(func)
2240 del fl.__defaults__
2241 self.assertEqual(self.signature(fl),
2242 ((('args', ..., ..., "var_positional"),
2243 ('kwargs', ..., ..., "var_keyword")),
2244 ...))
2245
Yury Selivanova773de02014-02-21 18:30:53 -05002246 # Test with cython-like builtins:
2247 _orig_isdesc = inspect.ismethoddescriptor
2248 def _isdesc(obj):
2249 if hasattr(obj, '_builtinmock'):
2250 return True
2251 return _orig_isdesc(obj)
2252
2253 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2254 builtin_func = funclike(func)
2255 # Make sure that our mock setup is working
2256 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2257 builtin_func._builtinmock = True
2258 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2259 self.assertEqual(inspect.signature(builtin_func), sig_func)
2260
Yury Selivanov63da7c72014-01-31 14:48:37 -05002261 def test_signature_functionlike_class(self):
2262 # We only want to duck type function-like objects,
2263 # not classes.
2264
2265 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2266 pass
2267
2268 class funclike:
2269 def __init__(self, marker):
2270 pass
2271
2272 __name__ = func.__name__
2273 __code__ = func.__code__
2274 __annotations__ = func.__annotations__
2275 __defaults__ = func.__defaults__
2276 __kwdefaults__ = func.__kwdefaults__
2277
Yury Selivanov63da7c72014-01-31 14:48:37 -05002278 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2279
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002280 def test_signature_on_method(self):
2281 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002282 def __init__(*args):
2283 pass
2284 def m1(self, arg1, arg2=1) -> int:
2285 pass
2286 def m2(*args):
2287 pass
2288 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002289 pass
2290
Yury Selivanov62560fb2014-01-28 12:26:24 -05002291 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002292 ((('arg1', ..., ..., "positional_or_keyword"),
2293 ('arg2', 1, ..., "positional_or_keyword")),
2294 int))
2295
Yury Selivanov62560fb2014-01-28 12:26:24 -05002296 self.assertEqual(self.signature(Test().m2),
2297 ((('args', ..., ..., "var_positional"),),
2298 ...))
2299
2300 self.assertEqual(self.signature(Test),
2301 ((('args', ..., ..., "var_positional"),),
2302 ...))
2303
2304 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2305 self.signature(Test())
2306
Yury Selivanov46c759d2015-05-27 21:56:53 -04002307 def test_signature_wrapped_bound_method(self):
2308 # Issue 24298
2309 class Test:
2310 def m1(self, arg1, arg2=1) -> int:
2311 pass
2312 @functools.wraps(Test().m1)
2313 def m1d(*args, **kwargs):
2314 pass
2315 self.assertEqual(self.signature(m1d),
2316 ((('arg1', ..., ..., "positional_or_keyword"),
2317 ('arg2', 1, ..., "positional_or_keyword")),
2318 int))
2319
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002320 def test_signature_on_classmethod(self):
2321 class Test:
2322 @classmethod
2323 def foo(cls, arg1, *, arg2=1):
2324 pass
2325
2326 meth = Test().foo
2327 self.assertEqual(self.signature(meth),
2328 ((('arg1', ..., ..., "positional_or_keyword"),
2329 ('arg2', 1, ..., "keyword_only")),
2330 ...))
2331
2332 meth = Test.foo
2333 self.assertEqual(self.signature(meth),
2334 ((('arg1', ..., ..., "positional_or_keyword"),
2335 ('arg2', 1, ..., "keyword_only")),
2336 ...))
2337
2338 def test_signature_on_staticmethod(self):
2339 class Test:
2340 @staticmethod
2341 def foo(cls, *, arg):
2342 pass
2343
2344 meth = Test().foo
2345 self.assertEqual(self.signature(meth),
2346 ((('cls', ..., ..., "positional_or_keyword"),
2347 ('arg', ..., ..., "keyword_only")),
2348 ...))
2349
2350 meth = Test.foo
2351 self.assertEqual(self.signature(meth),
2352 ((('cls', ..., ..., "positional_or_keyword"),
2353 ('arg', ..., ..., "keyword_only")),
2354 ...))
2355
2356 def test_signature_on_partial(self):
2357 from functools import partial
2358
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002359 Parameter = inspect.Parameter
2360
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002361 def test():
2362 pass
2363
2364 self.assertEqual(self.signature(partial(test)), ((), ...))
2365
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002366 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002367 inspect.signature(partial(test, 1))
2368
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002369 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002370 inspect.signature(partial(test, a=1))
2371
2372 def test(a, b, *, c, d):
2373 pass
2374
2375 self.assertEqual(self.signature(partial(test)),
2376 ((('a', ..., ..., "positional_or_keyword"),
2377 ('b', ..., ..., "positional_or_keyword"),
2378 ('c', ..., ..., "keyword_only"),
2379 ('d', ..., ..., "keyword_only")),
2380 ...))
2381
2382 self.assertEqual(self.signature(partial(test, 1)),
2383 ((('b', ..., ..., "positional_or_keyword"),
2384 ('c', ..., ..., "keyword_only"),
2385 ('d', ..., ..., "keyword_only")),
2386 ...))
2387
2388 self.assertEqual(self.signature(partial(test, 1, c=2)),
2389 ((('b', ..., ..., "positional_or_keyword"),
2390 ('c', 2, ..., "keyword_only"),
2391 ('d', ..., ..., "keyword_only")),
2392 ...))
2393
2394 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2395 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002396 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002397 ('c', 2, ..., "keyword_only"),
2398 ('d', ..., ..., "keyword_only")),
2399 ...))
2400
2401 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002402 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002403 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002404 ('d', ..., ..., "keyword_only")),
2405 ...))
2406
2407 self.assertEqual(self.signature(partial(test, a=1)),
2408 ((('a', 1, ..., "keyword_only"),
2409 ('b', ..., ..., "keyword_only"),
2410 ('c', ..., ..., "keyword_only"),
2411 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002412 ...))
2413
2414 def test(a, *args, b, **kwargs):
2415 pass
2416
2417 self.assertEqual(self.signature(partial(test, 1)),
2418 ((('args', ..., ..., "var_positional"),
2419 ('b', ..., ..., "keyword_only"),
2420 ('kwargs', ..., ..., "var_keyword")),
2421 ...))
2422
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002423 self.assertEqual(self.signature(partial(test, a=1)),
2424 ((('a', 1, ..., "keyword_only"),
2425 ('b', ..., ..., "keyword_only"),
2426 ('kwargs', ..., ..., "var_keyword")),
2427 ...))
2428
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002429 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2430 ((('args', ..., ..., "var_positional"),
2431 ('b', ..., ..., "keyword_only"),
2432 ('kwargs', ..., ..., "var_keyword")),
2433 ...))
2434
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002435 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2436 ((('args', ..., ..., "var_positional"),
2437 ('b', ..., ..., "keyword_only"),
2438 ('kwargs', ..., ..., "var_keyword")),
2439 ...))
2440
2441 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2442 ((('args', ..., ..., "var_positional"),
2443 ('b', 0, ..., "keyword_only"),
2444 ('kwargs', ..., ..., "var_keyword")),
2445 ...))
2446
2447 self.assertEqual(self.signature(partial(test, b=0)),
2448 ((('a', ..., ..., "positional_or_keyword"),
2449 ('args', ..., ..., "var_positional"),
2450 ('b', 0, ..., "keyword_only"),
2451 ('kwargs', ..., ..., "var_keyword")),
2452 ...))
2453
2454 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2455 ((('a', ..., ..., "positional_or_keyword"),
2456 ('args', ..., ..., "var_positional"),
2457 ('b', 0, ..., "keyword_only"),
2458 ('kwargs', ..., ..., "var_keyword")),
2459 ...))
2460
2461 def test(a, b, c:int) -> 42:
2462 pass
2463
2464 sig = test.__signature__ = inspect.signature(test)
2465
2466 self.assertEqual(self.signature(partial(partial(test, 1))),
2467 ((('b', ..., ..., "positional_or_keyword"),
2468 ('c', ..., int, "positional_or_keyword")),
2469 42))
2470
2471 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2472 ((('c', ..., int, "positional_or_keyword"),),
2473 42))
2474
2475 psig = inspect.signature(partial(partial(test, 1), 2))
2476
2477 def foo(a):
2478 return a
2479 _foo = partial(partial(foo, a=10), a=20)
2480 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002481 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002482 ...))
2483 # check that we don't have any side-effects in signature(),
2484 # and the partial object is still functioning
2485 self.assertEqual(_foo(), 20)
2486
2487 def foo(a, b, c):
2488 return a, b, c
2489 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002490
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002491 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002492 ((('b', 30, ..., "keyword_only"),
2493 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002494 ...))
2495 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002496
2497 def foo(a, b, c, *, d):
2498 return a, b, c, d
2499 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2500 self.assertEqual(self.signature(_foo),
2501 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002502 ('b', 10, ..., "keyword_only"),
2503 ('c', 20, ..., "keyword_only"),
2504 ('d', 30, ..., "keyword_only"),
2505 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002506 ...))
2507 ba = inspect.signature(_foo).bind(a=200, b=11)
2508 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2509
2510 def foo(a=1, b=2, c=3):
2511 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002512 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2513
2514 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002515 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002516
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002517 ba = inspect.signature(_foo).bind(11, 12)
2518 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002519
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002520 ba = inspect.signature(_foo).bind(11, b=12)
2521 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002522
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002523 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002524 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2525
2526 _foo = partial(_foo, b=10, c=20)
2527 ba = inspect.signature(_foo).bind(12)
2528 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2529
2530
2531 def foo(a, b, c, d, **kwargs):
2532 pass
2533 sig = inspect.signature(foo)
2534 params = sig.parameters.copy()
2535 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2536 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2537 foo.__signature__ = inspect.Signature(params.values())
2538 sig = inspect.signature(foo)
2539 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2540
2541 self.assertEqual(self.signature(partial(foo, 1)),
2542 ((('b', ..., ..., 'positional_only'),
2543 ('c', ..., ..., 'positional_or_keyword'),
2544 ('d', ..., ..., 'positional_or_keyword'),
2545 ('kwargs', ..., ..., 'var_keyword')),
2546 ...))
2547
2548 self.assertEqual(self.signature(partial(foo, 1, 2)),
2549 ((('c', ..., ..., 'positional_or_keyword'),
2550 ('d', ..., ..., 'positional_or_keyword'),
2551 ('kwargs', ..., ..., 'var_keyword')),
2552 ...))
2553
2554 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2555 ((('d', ..., ..., 'positional_or_keyword'),
2556 ('kwargs', ..., ..., 'var_keyword')),
2557 ...))
2558
2559 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2560 ((('c', 3, ..., 'keyword_only'),
2561 ('d', ..., ..., 'keyword_only'),
2562 ('kwargs', ..., ..., 'var_keyword')),
2563 ...))
2564
2565 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2566 ((('b', ..., ..., 'positional_only'),
2567 ('c', 3, ..., 'keyword_only'),
2568 ('d', ..., ..., 'keyword_only'),
2569 ('kwargs', ..., ..., 'var_keyword')),
2570 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002571
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002572 def test_signature_on_partialmethod(self):
2573 from functools import partialmethod
2574
2575 class Spam:
2576 def test():
2577 pass
2578 ham = partialmethod(test)
2579
2580 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2581 inspect.signature(Spam.ham)
2582
2583 class Spam:
2584 def test(it, a, *, c) -> 'spam':
2585 pass
2586 ham = partialmethod(test, c=1)
2587
2588 self.assertEqual(self.signature(Spam.ham),
2589 ((('it', ..., ..., 'positional_or_keyword'),
2590 ('a', ..., ..., 'positional_or_keyword'),
2591 ('c', 1, ..., 'keyword_only')),
2592 'spam'))
2593
2594 self.assertEqual(self.signature(Spam().ham),
2595 ((('a', ..., ..., 'positional_or_keyword'),
2596 ('c', 1, ..., 'keyword_only')),
2597 'spam'))
2598
Miss Islington (bot)112f7992018-03-06 10:23:48 -08002599 class Spam:
2600 def test(self: 'anno', x):
2601 pass
2602
2603 g = partialmethod(test, 1)
2604
2605 self.assertEqual(self.signature(Spam.g),
2606 ((('self', ..., 'anno', 'positional_or_keyword'),),
2607 ...))
2608
Yury Selivanov0486f812014-01-29 12:18:59 -05002609 def test_signature_on_fake_partialmethod(self):
2610 def foo(a): pass
2611 foo._partialmethod = 'spam'
2612 self.assertEqual(str(inspect.signature(foo)), '(a)')
2613
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002614 def test_signature_on_decorated(self):
2615 import functools
2616
2617 def decorator(func):
2618 @functools.wraps(func)
2619 def wrapper(*args, **kwargs) -> int:
2620 return func(*args, **kwargs)
2621 return wrapper
2622
2623 class Foo:
2624 @decorator
2625 def bar(self, a, b):
2626 pass
2627
2628 self.assertEqual(self.signature(Foo.bar),
2629 ((('self', ..., ..., "positional_or_keyword"),
2630 ('a', ..., ..., "positional_or_keyword"),
2631 ('b', ..., ..., "positional_or_keyword")),
2632 ...))
2633
2634 self.assertEqual(self.signature(Foo().bar),
2635 ((('a', ..., ..., "positional_or_keyword"),
2636 ('b', ..., ..., "positional_or_keyword")),
2637 ...))
2638
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002639 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2640 ((('args', ..., ..., "var_positional"),
2641 ('kwargs', ..., ..., "var_keyword")),
2642 ...)) # functools.wraps will copy __annotations__
2643 # from "func" to "wrapper", hence no
2644 # return_annotation
2645
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002646 # Test that we handle method wrappers correctly
2647 def decorator(func):
2648 @functools.wraps(func)
2649 def wrapper(*args, **kwargs) -> int:
2650 return func(42, *args, **kwargs)
2651 sig = inspect.signature(func)
2652 new_params = tuple(sig.parameters.values())[1:]
2653 wrapper.__signature__ = sig.replace(parameters=new_params)
2654 return wrapper
2655
2656 class Foo:
2657 @decorator
2658 def __call__(self, a, b):
2659 pass
2660
2661 self.assertEqual(self.signature(Foo.__call__),
2662 ((('a', ..., ..., "positional_or_keyword"),
2663 ('b', ..., ..., "positional_or_keyword")),
2664 ...))
2665
2666 self.assertEqual(self.signature(Foo().__call__),
2667 ((('b', ..., ..., "positional_or_keyword"),),
2668 ...))
2669
Nick Coghlane8c45d62013-07-28 20:00:01 +10002670 # Test we handle __signature__ partway down the wrapper stack
2671 def wrapped_foo_call():
2672 pass
2673 wrapped_foo_call.__wrapped__ = Foo.__call__
2674
2675 self.assertEqual(self.signature(wrapped_foo_call),
2676 ((('a', ..., ..., "positional_or_keyword"),
2677 ('b', ..., ..., "positional_or_keyword")),
2678 ...))
2679
2680
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002681 def test_signature_on_class(self):
2682 class C:
2683 def __init__(self, a):
2684 pass
2685
2686 self.assertEqual(self.signature(C),
2687 ((('a', ..., ..., "positional_or_keyword"),),
2688 ...))
2689
2690 class CM(type):
2691 def __call__(cls, a):
2692 pass
2693 class C(metaclass=CM):
2694 def __init__(self, b):
2695 pass
2696
2697 self.assertEqual(self.signature(C),
2698 ((('a', ..., ..., "positional_or_keyword"),),
2699 ...))
2700
2701 class CM(type):
2702 def __new__(mcls, name, bases, dct, *, foo=1):
2703 return super().__new__(mcls, name, bases, dct)
2704 class C(metaclass=CM):
2705 def __init__(self, b):
2706 pass
2707
2708 self.assertEqual(self.signature(C),
2709 ((('b', ..., ..., "positional_or_keyword"),),
2710 ...))
2711
2712 self.assertEqual(self.signature(CM),
2713 ((('name', ..., ..., "positional_or_keyword"),
2714 ('bases', ..., ..., "positional_or_keyword"),
2715 ('dct', ..., ..., "positional_or_keyword"),
2716 ('foo', 1, ..., "keyword_only")),
2717 ...))
2718
2719 class CMM(type):
2720 def __new__(mcls, name, bases, dct, *, foo=1):
2721 return super().__new__(mcls, name, bases, dct)
2722 def __call__(cls, nm, bs, dt):
2723 return type(nm, bs, dt)
2724 class CM(type, metaclass=CMM):
2725 def __new__(mcls, name, bases, dct, *, bar=2):
2726 return super().__new__(mcls, name, bases, dct)
2727 class C(metaclass=CM):
2728 def __init__(self, b):
2729 pass
2730
2731 self.assertEqual(self.signature(CMM),
2732 ((('name', ..., ..., "positional_or_keyword"),
2733 ('bases', ..., ..., "positional_or_keyword"),
2734 ('dct', ..., ..., "positional_or_keyword"),
2735 ('foo', 1, ..., "keyword_only")),
2736 ...))
2737
2738 self.assertEqual(self.signature(CM),
2739 ((('nm', ..., ..., "positional_or_keyword"),
2740 ('bs', ..., ..., "positional_or_keyword"),
2741 ('dt', ..., ..., "positional_or_keyword")),
2742 ...))
2743
2744 self.assertEqual(self.signature(C),
2745 ((('b', ..., ..., "positional_or_keyword"),),
2746 ...))
2747
2748 class CM(type):
2749 def __init__(cls, name, bases, dct, *, bar=2):
2750 return super().__init__(name, bases, dct)
2751 class C(metaclass=CM):
2752 def __init__(self, b):
2753 pass
2754
2755 self.assertEqual(self.signature(CM),
2756 ((('name', ..., ..., "positional_or_keyword"),
2757 ('bases', ..., ..., "positional_or_keyword"),
2758 ('dct', ..., ..., "positional_or_keyword"),
2759 ('bar', 2, ..., "keyword_only")),
2760 ...))
2761
Yury Selivanov145dff82014-02-01 13:49:29 -05002762 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2763 "Signature information for builtins requires docstrings")
2764 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002765 # Test classes without user-defined __init__ or __new__
2766 class C: pass
2767 self.assertEqual(str(inspect.signature(C)), '()')
2768 class D(C): pass
2769 self.assertEqual(str(inspect.signature(D)), '()')
2770
2771 # Test meta-classes without user-defined __init__ or __new__
2772 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002773 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002774 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2775 self.assertEqual(inspect.signature(C), None)
2776 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2777 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002778
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002779 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2780 "Signature information for builtins requires docstrings")
2781 def test_signature_on_builtin_class(self):
2782 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2783 '(file, protocol=None, fix_imports=True)')
2784
2785 class P(_pickle.Pickler): pass
2786 class EmptyTrait: pass
2787 class P2(EmptyTrait, P): pass
2788 self.assertEqual(str(inspect.signature(P)),
2789 '(file, protocol=None, fix_imports=True)')
2790 self.assertEqual(str(inspect.signature(P2)),
2791 '(file, protocol=None, fix_imports=True)')
2792
2793 class P3(P2):
2794 def __init__(self, spam):
2795 pass
2796 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2797
2798 class MetaP(type):
2799 def __call__(cls, foo, bar):
2800 pass
2801 class P4(P2, metaclass=MetaP):
2802 pass
2803 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2804
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002805 def test_signature_on_callable_objects(self):
2806 class Foo:
2807 def __call__(self, a):
2808 pass
2809
2810 self.assertEqual(self.signature(Foo()),
2811 ((('a', ..., ..., "positional_or_keyword"),),
2812 ...))
2813
2814 class Spam:
2815 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002816 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002817 inspect.signature(Spam())
2818
2819 class Bar(Spam, Foo):
2820 pass
2821
2822 self.assertEqual(self.signature(Bar()),
2823 ((('a', ..., ..., "positional_or_keyword"),),
2824 ...))
2825
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002826 class Wrapped:
2827 pass
2828 Wrapped.__wrapped__ = lambda a: None
2829 self.assertEqual(self.signature(Wrapped),
2830 ((('a', ..., ..., "positional_or_keyword"),),
2831 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002832 # wrapper loop:
2833 Wrapped.__wrapped__ = Wrapped
2834 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2835 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002836
2837 def test_signature_on_lambdas(self):
2838 self.assertEqual(self.signature((lambda a=10: a)),
2839 ((('a', 10, ..., "positional_or_keyword"),),
2840 ...))
2841
2842 def test_signature_equality(self):
2843 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002844 self.assertFalse(inspect.signature(foo) == 42)
2845 self.assertTrue(inspect.signature(foo) != 42)
2846 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2847 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002848
2849 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002850 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2851 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002852 self.assertEqual(
2853 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002854
2855 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002856 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2857 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002858 self.assertNotEqual(
2859 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002860
2861 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002862 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2863 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002864 self.assertNotEqual(
2865 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002866
2867 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002868 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2869 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002870 self.assertNotEqual(
2871 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002872
2873 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002874 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2875 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002876 self.assertNotEqual(
2877 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002878
2879 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002880 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2881 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002882 self.assertNotEqual(
2883 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002884 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002885 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
2886 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002887 self.assertNotEqual(
2888 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002889
2890 def foo(*, a, b, c): pass
2891 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002892 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2893 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002894 self.assertEqual(
2895 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002896
2897 def foo(*, a=1, b, c): pass
2898 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002899 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2900 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002901 self.assertEqual(
2902 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002903
2904 def foo(pos, *, a=1, b, c): pass
2905 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002906 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2907 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002908 self.assertEqual(
2909 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002910
2911 def foo(pos, *, a, b, c): pass
2912 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002913 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2914 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002915 self.assertNotEqual(
2916 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002917
2918 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2919 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002920 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2921 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002922 self.assertEqual(
2923 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002924
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002925 def test_signature_hashable(self):
2926 S = inspect.Signature
2927 P = inspect.Parameter
2928
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002929 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002930 foo_sig = inspect.signature(foo)
2931
2932 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2933
2934 self.assertEqual(hash(foo_sig), hash(manual_sig))
2935 self.assertNotEqual(hash(foo_sig),
2936 hash(manual_sig.replace(return_annotation='spam')))
2937
2938 def bar(a) -> 1: pass
2939 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2940
2941 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002942 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002943 hash(inspect.signature(foo))
2944
2945 def foo(a) -> {}: pass
2946 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2947 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002948
2949 def test_signature_str(self):
2950 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2951 pass
2952 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09002953 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002954
2955 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2956 pass
2957 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09002958 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002959
2960 def foo():
2961 pass
2962 self.assertEqual(str(inspect.signature(foo)), '()')
2963
2964 def test_signature_str_positional_only(self):
2965 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002966 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002967
2968 def test(a_po, *, b, **kwargs):
2969 return a_po, kwargs
2970
2971 sig = inspect.signature(test)
2972 new_params = list(sig.parameters.values())
2973 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2974 test.__signature__ = sig.replace(parameters=new_params)
2975
2976 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002977 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002978
Yury Selivanov2393dca2014-01-27 15:07:58 -05002979 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2980 '(foo, /)')
2981
2982 self.assertEqual(str(S(parameters=[
2983 P('foo', P.POSITIONAL_ONLY),
2984 P('bar', P.VAR_KEYWORD)])),
2985 '(foo, /, **bar)')
2986
2987 self.assertEqual(str(S(parameters=[
2988 P('foo', P.POSITIONAL_ONLY),
2989 P('bar', P.VAR_POSITIONAL)])),
2990 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002991
2992 def test_signature_replace_anno(self):
2993 def test() -> 42:
2994 pass
2995
2996 sig = inspect.signature(test)
2997 sig = sig.replace(return_annotation=None)
2998 self.assertIs(sig.return_annotation, None)
2999 sig = sig.replace(return_annotation=sig.empty)
3000 self.assertIs(sig.return_annotation, sig.empty)
3001 sig = sig.replace(return_annotation=42)
3002 self.assertEqual(sig.return_annotation, 42)
3003 self.assertEqual(sig, inspect.signature(test))
3004
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003005 def test_signature_on_mangled_parameters(self):
3006 class Spam:
3007 def foo(self, __p1:1=2, *, __p2:2=3):
3008 pass
3009 class Ham(Spam):
3010 pass
3011
3012 self.assertEqual(self.signature(Spam.foo),
3013 ((('self', ..., ..., "positional_or_keyword"),
3014 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3015 ('_Spam__p2', 3, 2, "keyword_only")),
3016 ...))
3017
3018 self.assertEqual(self.signature(Spam.foo),
3019 self.signature(Ham.foo))
3020
Yury Selivanovda396452014-03-27 12:09:24 -04003021 def test_signature_from_callable_python_obj(self):
3022 class MySignature(inspect.Signature): pass
3023 def foo(a, *, b:1): pass
3024 foo_sig = MySignature.from_callable(foo)
3025 self.assertTrue(isinstance(foo_sig, MySignature))
3026
3027 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3028 "Signature information for builtins requires docstrings")
3029 def test_signature_from_callable_builtin_obj(self):
3030 class MySignature(inspect.Signature): pass
3031 sig = MySignature.from_callable(_pickle.Pickler)
3032 self.assertTrue(isinstance(sig, MySignature))
3033
larryhastingsf36ba122018-01-28 11:13:09 -08003034 def test_signature_definition_order_preserved_on_kwonly(self):
3035 for fn in signatures_with_lexicographic_keyword_only_parameters():
3036 signature = inspect.signature(fn)
3037 l = list(signature.parameters)
3038 sorted_l = sorted(l)
3039 self.assertTrue(l)
3040 self.assertEqual(l, sorted_l)
3041 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3042 l = list(signature.parameters)
3043 self.assertEqual(l, unsorted_keyword_only_parameters)
3044
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003045
3046class TestParameterObject(unittest.TestCase):
3047 def test_signature_parameter_kinds(self):
3048 P = inspect.Parameter
3049 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3050 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3051
3052 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3053 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3054
3055 def test_signature_parameter_object(self):
3056 p = inspect.Parameter('foo', default=10,
3057 kind=inspect.Parameter.POSITIONAL_ONLY)
3058 self.assertEqual(p.name, 'foo')
3059 self.assertEqual(p.default, 10)
3060 self.assertIs(p.annotation, p.empty)
3061 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3062
Miss Islington (bot)cb055bc2018-05-29 08:43:54 -07003063 with self.assertRaisesRegex(ValueError, "value '123' is "
3064 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003065 inspect.Parameter('foo', default=10, kind='123')
3066
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003067 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003068 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3069
Yury Selivanov2393dca2014-01-27 15:07:58 -05003070 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003071 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3072
Yury Selivanov2393dca2014-01-27 15:07:58 -05003073 with self.assertRaisesRegex(ValueError,
3074 'is not a valid parameter name'):
3075 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3076
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003077 with self.assertRaisesRegex(ValueError,
3078 'is not a valid parameter name'):
3079 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3080
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003081 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003082 inspect.Parameter('a', default=42,
3083 kind=inspect.Parameter.VAR_KEYWORD)
3084
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003085 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003086 inspect.Parameter('a', default=42,
3087 kind=inspect.Parameter.VAR_POSITIONAL)
3088
3089 p = inspect.Parameter('a', default=42,
3090 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003091 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003092 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3093
3094 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003095 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003096
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003097 def test_signature_parameter_hashable(self):
3098 P = inspect.Parameter
3099 foo = P('foo', kind=P.POSITIONAL_ONLY)
3100 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3101 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3102 default=42)))
3103 self.assertNotEqual(hash(foo),
3104 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3105
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003106 def test_signature_parameter_equality(self):
3107 P = inspect.Parameter
3108 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3109
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003110 self.assertTrue(p == p)
3111 self.assertFalse(p != p)
3112 self.assertFalse(p == 42)
3113 self.assertTrue(p != 42)
3114 self.assertTrue(p == EqualsToAll())
3115 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003116
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003117 self.assertTrue(p == P('foo', default=42,
3118 kind=inspect.Parameter.KEYWORD_ONLY))
3119 self.assertFalse(p != P('foo', default=42,
3120 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003121
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003122 def test_signature_parameter_replace(self):
3123 p = inspect.Parameter('foo', default=42,
3124 kind=inspect.Parameter.KEYWORD_ONLY)
3125
3126 self.assertIsNot(p, p.replace())
3127 self.assertEqual(p, p.replace())
3128
3129 p2 = p.replace(annotation=1)
3130 self.assertEqual(p2.annotation, 1)
3131 p2 = p2.replace(annotation=p2.empty)
3132 self.assertEqual(p, p2)
3133
3134 p2 = p2.replace(name='bar')
3135 self.assertEqual(p2.name, 'bar')
3136 self.assertNotEqual(p2, p)
3137
Yury Selivanov2393dca2014-01-27 15:07:58 -05003138 with self.assertRaisesRegex(ValueError,
3139 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003140 p2 = p2.replace(name=p2.empty)
3141
3142 p2 = p2.replace(name='foo', default=None)
3143 self.assertIs(p2.default, None)
3144 self.assertNotEqual(p2, p)
3145
3146 p2 = p2.replace(name='foo', default=p2.empty)
3147 self.assertIs(p2.default, p2.empty)
3148
3149
3150 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3151 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3152 self.assertNotEqual(p2, p)
3153
Miss Islington (bot)cb055bc2018-05-29 08:43:54 -07003154 with self.assertRaisesRegex(ValueError,
3155 "value <class 'inspect._empty'> "
3156 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003157 p2 = p2.replace(kind=p2.empty)
3158
3159 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3160 self.assertEqual(p2, p)
3161
3162 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003163 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3164 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003165
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003166 @cpython_only
3167 def test_signature_parameter_implicit(self):
3168 with self.assertRaisesRegex(ValueError,
Miss Islington (bot)cb055bc2018-05-29 08:43:54 -07003169 'implicit arguments must be passed as '
3170 'positional or keyword arguments, '
3171 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003172 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3173
3174 param = inspect.Parameter(
3175 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3176 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3177 self.assertEqual(param.name, 'implicit0')
3178
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003179 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003180 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003181
3182 with self.assertRaises(AttributeError):
3183 p.foo = 'bar'
3184
3185 with self.assertRaises(AttributeError):
3186 p.kind = 123
3187
3188
3189class TestSignatureBind(unittest.TestCase):
3190 @staticmethod
3191 def call(func, *args, **kwargs):
3192 sig = inspect.signature(func)
3193 ba = sig.bind(*args, **kwargs)
3194 return func(*ba.args, **ba.kwargs)
3195
3196 def test_signature_bind_empty(self):
3197 def test():
3198 return 42
3199
3200 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003201 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003202 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003203 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003204 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003205 with self.assertRaisesRegex(
3206 TypeError, "got an unexpected keyword argument 'spam'"):
3207
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003208 self.call(test, spam=1)
3209
3210 def test_signature_bind_var(self):
3211 def test(*args, **kwargs):
3212 return args, kwargs
3213
3214 self.assertEqual(self.call(test), ((), {}))
3215 self.assertEqual(self.call(test, 1), ((1,), {}))
3216 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3217 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3218 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3219 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3220 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3221 ((1, 2), {'foo': 'bar'}))
3222
3223 def test_signature_bind_just_args(self):
3224 def test(a, b, c):
3225 return a, b, c
3226
3227 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3228
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003229 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003230 self.call(test, 1, 2, 3, 4)
3231
Yury Selivanov86872752015-05-19 00:27:49 -04003232 with self.assertRaisesRegex(TypeError,
3233 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003234 self.call(test, 1)
3235
Yury Selivanov86872752015-05-19 00:27:49 -04003236 with self.assertRaisesRegex(TypeError,
3237 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003238 self.call(test)
3239
3240 def test(a, b, c=10):
3241 return a, b, c
3242 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3243 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3244
3245 def test(a=1, b=2, c=3):
3246 return a, b, c
3247 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3248 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3249 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3250
3251 def test_signature_bind_varargs_order(self):
3252 def test(*args):
3253 return args
3254
3255 self.assertEqual(self.call(test), ())
3256 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3257
3258 def test_signature_bind_args_and_varargs(self):
3259 def test(a, b, c=3, *args):
3260 return a, b, c, args
3261
3262 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3263 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3264 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3265 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3266
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003267 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003268 "multiple values for argument 'c'"):
3269 self.call(test, 1, 2, 3, c=4)
3270
3271 def test_signature_bind_just_kwargs(self):
3272 def test(**kwargs):
3273 return kwargs
3274
3275 self.assertEqual(self.call(test), {})
3276 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3277 {'foo': 'bar', 'spam': 'ham'})
3278
3279 def test_signature_bind_args_and_kwargs(self):
3280 def test(a, b, c=3, **kwargs):
3281 return a, b, c, kwargs
3282
3283 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3284 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3285 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3286 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3287 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3288 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3289 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3290 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3291 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3292 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3293 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3294 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3295 (1, 2, 4, {'foo': 'bar'}))
3296 self.assertEqual(self.call(test, c=5, a=4, b=3),
3297 (4, 3, 5, {}))
3298
3299 def test_signature_bind_kwonly(self):
3300 def test(*, foo):
3301 return foo
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)
3305 self.assertEqual(self.call(test, foo=1), 1)
3306
3307 def test(a, *, foo=1, bar):
3308 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003309 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003310 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003311 self.call(test, 1)
3312
3313 def test(foo, *, bar):
3314 return foo, bar
3315 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3316 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3317
Yury Selivanov86872752015-05-19 00:27:49 -04003318 with self.assertRaisesRegex(
3319 TypeError, "got an unexpected keyword argument 'spam'"):
3320
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003321 self.call(test, bar=2, foo=1, spam=10)
3322
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003323 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003324 'too many positional arguments'):
3325 self.call(test, 1, 2)
3326
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003327 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003328 'too many positional arguments'):
3329 self.call(test, 1, 2, bar=2)
3330
Yury Selivanov86872752015-05-19 00:27:49 -04003331 with self.assertRaisesRegex(
3332 TypeError, "got an unexpected keyword argument 'spam'"):
3333
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003334 self.call(test, 1, bar=2, spam='ham')
3335
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003336 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003337 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003338 self.call(test, 1)
3339
3340 def test(foo, *, bar, **bin):
3341 return foo, bar, bin
3342 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3343 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3344 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3345 (1, 2, {'spam': 'ham'}))
3346 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3347 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003348 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003349 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003350 self.call(test, spam='ham', bar=2)
3351 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3352 (1, 2, {'bin': 1, 'spam': 10}))
3353
3354 def test_signature_bind_arguments(self):
3355 def test(a, *args, b, z=100, **kwargs):
3356 pass
3357 sig = inspect.signature(test)
3358 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3359 # we won't have 'z' argument in the bound arguments object, as we didn't
3360 # pass it to the 'bind'
3361 self.assertEqual(tuple(ba.arguments.items()),
3362 (('a', 10), ('args', (20,)), ('b', 30),
3363 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3364 self.assertEqual(ba.kwargs,
3365 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3366 self.assertEqual(ba.args, (10, 20))
3367
3368 def test_signature_bind_positional_only(self):
3369 P = inspect.Parameter
3370
3371 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3372 return a_po, b_po, c_po, foo, bar, kwargs
3373
3374 sig = inspect.signature(test)
3375 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3376 for name in ('a_po', 'b_po', 'c_po'):
3377 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3378 new_sig = sig.replace(parameters=new_params.values())
3379 test.__signature__ = new_sig
3380
3381 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3382 (1, 2, 4, 5, 6, {}))
3383
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003384 self.assertEqual(self.call(test, 1, 2),
3385 (1, 2, 3, 42, 50, {}))
3386
3387 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3388 (1, 2, 3, 4, 5, {}))
3389
3390 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3391 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3392
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003393 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003394 self.call(test, 1, 2, c_po=4)
3395
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003396 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003397 self.call(test, a_po=1, b_po=2)
3398
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003399 def test_signature_bind_with_self_arg(self):
3400 # Issue #17071: one of the parameters is named "self
3401 def test(a, self, b):
3402 pass
3403 sig = inspect.signature(test)
3404 ba = sig.bind(1, 2, 3)
3405 self.assertEqual(ba.args, (1, 2, 3))
3406 ba = sig.bind(1, self=2, b=3)
3407 self.assertEqual(ba.args, (1, 2, 3))
3408
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003409 def test_signature_bind_vararg_name(self):
3410 def test(a, *args):
3411 return a, args
3412 sig = inspect.signature(test)
3413
Yury Selivanov86872752015-05-19 00:27:49 -04003414 with self.assertRaisesRegex(
3415 TypeError, "got an unexpected keyword argument 'args'"):
3416
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003417 sig.bind(a=0, args=1)
3418
3419 def test(*args, **kwargs):
3420 return args, kwargs
3421 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3422
3423 sig = inspect.signature(test)
3424 ba = sig.bind(args=1)
3425 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3426
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003427 @cpython_only
3428 def test_signature_bind_implicit_arg(self):
3429 # Issue #19611: getcallargs should work with set comprehensions
3430 def make_set():
3431 return {z * z for z in range(5)}
3432 setcomp_code = make_set.__code__.co_consts[1]
3433 setcomp_func = types.FunctionType(setcomp_code, {})
3434
3435 iterator = iter(range(5))
3436 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3437
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003438
3439class TestBoundArguments(unittest.TestCase):
3440 def test_signature_bound_arguments_unhashable(self):
3441 def foo(a): pass
3442 ba = inspect.signature(foo).bind(1)
3443
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003444 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003445 hash(ba)
3446
3447 def test_signature_bound_arguments_equality(self):
3448 def foo(a): pass
3449 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003450 self.assertTrue(ba == ba)
3451 self.assertFalse(ba != ba)
3452 self.assertTrue(ba == EqualsToAll())
3453 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003454
3455 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003456 self.assertTrue(ba == ba2)
3457 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003458
3459 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003460 self.assertFalse(ba == ba3)
3461 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003462 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003463 self.assertTrue(ba == ba3)
3464 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003465
3466 def bar(b): pass
3467 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003468 self.assertFalse(ba == ba4)
3469 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003470
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003471 def foo(*, a, b): pass
3472 sig = inspect.signature(foo)
3473 ba1 = sig.bind(a=1, b=2)
3474 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003475 self.assertTrue(ba1 == ba2)
3476 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003477
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003478 def test_signature_bound_arguments_pickle(self):
3479 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3480 sig = inspect.signature(foo)
3481 ba = sig.bind(20, 30, z={})
3482
3483 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3484 with self.subTest(pickle_ver=ver):
3485 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3486 self.assertEqual(ba, ba_pickled)
3487
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003488 def test_signature_bound_arguments_repr(self):
3489 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3490 sig = inspect.signature(foo)
3491 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003492 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003493
Yury Selivanovb907a512015-05-16 13:45:09 -04003494 def test_signature_bound_arguments_apply_defaults(self):
3495 def foo(a, b=1, *args, c:1={}, **kw): pass
3496 sig = inspect.signature(foo)
3497
3498 ba = sig.bind(20)
3499 ba.apply_defaults()
3500 self.assertEqual(
3501 list(ba.arguments.items()),
3502 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3503
3504 # Make sure that we preserve the order:
3505 # i.e. 'c' should be *before* 'kw'.
3506 ba = sig.bind(10, 20, 30, d=1)
3507 ba.apply_defaults()
3508 self.assertEqual(
3509 list(ba.arguments.items()),
3510 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3511
3512 # Make sure that BoundArguments produced by bind_partial()
3513 # are supported.
3514 def foo(a, b): pass
3515 sig = inspect.signature(foo)
3516 ba = sig.bind_partial(20)
3517 ba.apply_defaults()
3518 self.assertEqual(
3519 list(ba.arguments.items()),
3520 [('a', 20)])
3521
3522 # Test no args
3523 def foo(): pass
3524 sig = inspect.signature(foo)
3525 ba = sig.bind()
3526 ba.apply_defaults()
3527 self.assertEqual(list(ba.arguments.items()), [])
3528
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003529 # Make sure a no-args binding still acquires proper defaults.
3530 def foo(a='spam'): pass
3531 sig = inspect.signature(foo)
3532 ba = sig.bind()
3533 ba.apply_defaults()
3534 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3535
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003536
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003537class TestSignaturePrivateHelpers(unittest.TestCase):
3538 def test_signature_get_bound_param(self):
3539 getter = inspect._signature_get_bound_param
3540
3541 self.assertEqual(getter('($self)'), 'self')
3542 self.assertEqual(getter('($self, obj)'), 'self')
3543 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3544
Larry Hastings2623c8c2014-02-08 22:15:29 -08003545 def _strip_non_python_syntax(self, input,
3546 clean_signature, self_parameter, last_positional_only):
3547 computed_clean_signature, \
3548 computed_self_parameter, \
3549 computed_last_positional_only = \
3550 inspect._signature_strip_non_python_syntax(input)
3551 self.assertEqual(computed_clean_signature, clean_signature)
3552 self.assertEqual(computed_self_parameter, self_parameter)
3553 self.assertEqual(computed_last_positional_only, last_positional_only)
3554
3555 def test_signature_strip_non_python_syntax(self):
3556 self._strip_non_python_syntax(
3557 "($module, /, path, mode, *, dir_fd=None, " +
3558 "effective_ids=False,\n follow_symlinks=True)",
3559 "(module, path, mode, *, dir_fd=None, " +
3560 "effective_ids=False, follow_symlinks=True)",
3561 0,
3562 0)
3563
3564 self._strip_non_python_syntax(
3565 "($module, word, salt, /)",
3566 "(module, word, salt)",
3567 0,
3568 2)
3569
3570 self._strip_non_python_syntax(
3571 "(x, y=None, z=None, /)",
3572 "(x, y=None, z=None)",
3573 None,
3574 2)
3575
3576 self._strip_non_python_syntax(
3577 "(x, y=None, z=None)",
3578 "(x, y=None, z=None)",
3579 None,
3580 None)
3581
3582 self._strip_non_python_syntax(
3583 "(x,\n y=None,\n z = None )",
3584 "(x, y=None, z=None)",
3585 None,
3586 None)
3587
3588 self._strip_non_python_syntax(
3589 "",
3590 "",
3591 None,
3592 None)
3593
3594 self._strip_non_python_syntax(
3595 None,
3596 None,
3597 None,
3598 None)
3599
Nick Coghlan9c680b02015-04-13 12:54:54 -04003600class TestSignatureDefinitions(unittest.TestCase):
3601 # This test case provides a home for checking that particular APIs
3602 # have signatures available for introspection
3603
3604 @cpython_only
3605 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3606 "Signature information for builtins requires docstrings")
3607 def test_builtins_have_signatures(self):
3608 # This checks all builtin callables in CPython have signatures
3609 # A few have signatures Signature can't yet handle, so we skip those
3610 # since they will have to wait until PEP 457 adds the required
3611 # introspection support to the inspect module
3612 # Some others also haven't been converted yet for various other
3613 # reasons, so we also skip those for the time being, but design
3614 # the test to fail in order to indicate when it needs to be
3615 # updated.
3616 no_signature = set()
3617 # These need PEP 457 groups
3618 needs_groups = {"range", "slice", "dir", "getattr",
3619 "next", "iter", "vars"}
3620 no_signature |= needs_groups
3621 # These need PEP 457 groups or a signature change to accept None
3622 needs_semantic_update = {"round"}
3623 no_signature |= needs_semantic_update
3624 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003625 needs_varargs = {"breakpoint", "min", "max", "print",
3626 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003627 no_signature |= needs_varargs
3628 # These simply weren't covered in the initial AC conversion
3629 # for builtin callables
3630 not_converted_yet = {"open", "__import__"}
3631 no_signature |= not_converted_yet
3632 # These builtin types are expected to provide introspection info
3633 types_with_signatures = set()
3634 # Check the signatures we expect to be there
3635 ns = vars(builtins)
3636 for name, obj in sorted(ns.items()):
3637 if not callable(obj):
3638 continue
3639 # The builtin types haven't been converted to AC yet
3640 if isinstance(obj, type) and (name not in types_with_signatures):
3641 # Note that this also skips all the exception types
3642 no_signature.add(name)
3643 if (name in no_signature):
3644 # Not yet converted
3645 continue
3646 with self.subTest(builtin=name):
3647 self.assertIsNotNone(inspect.signature(obj))
3648 # Check callables that haven't been converted don't claim a signature
3649 # This ensures this test will start failing as more signatures are
3650 # added, so the affected items can be moved into the scope of the
3651 # regression test above
3652 for name in no_signature:
3653 with self.subTest(builtin=name):
3654 self.assertIsNone(obj.__text_signature__)
3655
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003656
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003657class NTimesUnwrappable:
3658 def __init__(self, n):
3659 self.n = n
3660 self._next = None
3661
3662 @property
3663 def __wrapped__(self):
3664 if self.n <= 0:
3665 raise Exception("Unwrapped too many times")
3666 if self._next is None:
3667 self._next = NTimesUnwrappable(self.n - 1)
3668 return self._next
3669
Nick Coghlane8c45d62013-07-28 20:00:01 +10003670class TestUnwrap(unittest.TestCase):
3671
3672 def test_unwrap_one(self):
3673 def func(a, b):
3674 return a + b
3675 wrapper = functools.lru_cache(maxsize=20)(func)
3676 self.assertIs(inspect.unwrap(wrapper), func)
3677
3678 def test_unwrap_several(self):
3679 def func(a, b):
3680 return a + b
3681 wrapper = func
3682 for __ in range(10):
3683 @functools.wraps(wrapper)
3684 def wrapper():
3685 pass
3686 self.assertIsNot(wrapper.__wrapped__, func)
3687 self.assertIs(inspect.unwrap(wrapper), func)
3688
3689 def test_stop(self):
3690 def func1(a, b):
3691 return a + b
3692 @functools.wraps(func1)
3693 def func2():
3694 pass
3695 @functools.wraps(func2)
3696 def wrapper():
3697 pass
3698 func2.stop_here = 1
3699 unwrapped = inspect.unwrap(wrapper,
3700 stop=(lambda f: hasattr(f, "stop_here")))
3701 self.assertIs(unwrapped, func2)
3702
3703 def test_cycle(self):
3704 def func1(): pass
3705 func1.__wrapped__ = func1
3706 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3707 inspect.unwrap(func1)
3708
3709 def func2(): pass
3710 func2.__wrapped__ = func1
3711 func1.__wrapped__ = func2
3712 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3713 inspect.unwrap(func1)
3714 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3715 inspect.unwrap(func2)
3716
3717 def test_unhashable(self):
3718 def func(): pass
3719 func.__wrapped__ = None
3720 class C:
3721 __hash__ = None
3722 __wrapped__ = func
3723 self.assertIsNone(inspect.unwrap(C()))
3724
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003725 def test_recursion_limit(self):
3726 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3727 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3728 inspect.unwrap(obj)
3729
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003730class TestMain(unittest.TestCase):
3731 def test_only_source(self):
3732 module = importlib.import_module('unittest')
3733 rc, out, err = assert_python_ok('-m', 'inspect',
3734 'unittest')
3735 lines = out.decode().splitlines()
3736 # ignore the final newline
3737 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3738 self.assertEqual(err, b'')
3739
Yury Selivanov42407ab2014-06-23 10:23:50 -07003740 def test_custom_getattr(self):
3741 def foo():
3742 pass
3743 foo.__signature__ = 42
3744 with self.assertRaises(TypeError):
3745 inspect.signature(foo)
3746
Brett Cannon634a8fc2013-10-02 10:25:42 -04003747 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003748 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003749 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003750 rc, out, err = assert_python_ok('-m', 'inspect',
3751 'concurrent.futures:ThreadPoolExecutor')
3752 lines = out.decode().splitlines()
3753 # ignore the final newline
3754 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003755 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003756 self.assertEqual(err, b'')
3757
3758 def test_builtins(self):
3759 module = importlib.import_module('unittest')
3760 _, out, err = assert_python_failure('-m', 'inspect',
3761 'sys')
3762 lines = err.decode().splitlines()
3763 self.assertEqual(lines, ["Can't get info for builtin modules."])
3764
3765 def test_details(self):
3766 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003767 args = support.optim_args_from_interpreter_flags()
3768 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003769 'unittest', '--details')
3770 output = out.decode()
3771 # Just a quick sanity check on the output
3772 self.assertIn(module.__name__, output)
3773 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003774 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003775 self.assertEqual(err, b'')
3776
3777
Yury Selivanovef1e7502014-12-08 16:05:34 -05003778class TestReload(unittest.TestCase):
3779
3780 src_before = textwrap.dedent("""\
3781def foo():
3782 print("Bla")
3783 """)
3784
3785 src_after = textwrap.dedent("""\
3786def foo():
3787 print("Oh no!")
3788 """)
3789
3790 def assertInspectEqual(self, path, source):
3791 inspected_src = inspect.getsource(source)
3792 with open(path) as src:
3793 self.assertEqual(
3794 src.read().splitlines(True),
3795 inspected_src.splitlines(True)
3796 )
3797
3798 def test_getsource_reload(self):
3799 # see issue 1218234
3800 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3801 module = importlib.import_module(name)
3802 self.assertInspectEqual(path, module)
3803 with open(path, 'w') as src:
3804 src.write(self.src_after)
3805 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003806
Nick Coghlane8c45d62013-07-28 20:00:01 +10003807
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003808def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003809 run_unittest(
3810 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3811 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3812 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003813 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003814 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003815 TestBoundArguments, TestSignaturePrivateHelpers,
3816 TestSignatureDefinitions,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003817 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
3818 TestGetCoroutineState
Michael Foord95fc51d2010-11-20 15:07:30 +00003819 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003820
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003821if __name__ == "__main__":
3822 test_main()