blob: cda8d5cf73ef11230bd7726a6941b36122089d78 [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:
Matthias Bussonnier46c5cd02018-06-11 22:08:16 +0200715 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:
Matthias Bussonnier46c5cd02018-06-11 22:08:16 +0200733 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
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001139class TestIsDataDescriptor(unittest.TestCase):
1140
1141 def test_custom_descriptors(self):
1142 class NonDataDescriptor:
1143 def __get__(self, value, type=None): pass
1144 class DataDescriptor0:
1145 def __set__(self, name, value): pass
1146 class DataDescriptor1:
1147 def __delete__(self, name): pass
1148 class DataDescriptor2:
1149 __set__ = None
1150 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1151 'class with only __get__ not a data descriptor')
1152 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1153 'class with __set__ is a data descriptor')
1154 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1155 'class with __delete__ is a data descriptor')
1156 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1157 'class with __set__ = None is a data descriptor')
1158
1159 def test_slot(self):
1160 class Slotted:
1161 __slots__ = 'foo',
1162 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1163 'a slot is a data descriptor')
1164
1165 def test_property(self):
1166 class Propertied:
1167 @property
1168 def a_property(self):
1169 pass
1170 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1171 'a property is a data descriptor')
1172
1173 def test_functions(self):
1174 class Test(object):
1175 def instance_method(self): pass
1176 @classmethod
1177 def class_method(cls): pass
1178 @staticmethod
1179 def static_method(): pass
1180 def function():
1181 pass
1182 a_lambda = lambda: None
1183 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1184 'a instance method is not a data descriptor')
1185 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1186 'a class method is not a data descriptor')
1187 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1188 'a static method is not a data descriptor')
1189 self.assertFalse(inspect.isdatadescriptor(function),
1190 'a function is not a data descriptor')
1191 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1192 'a lambda is not a data descriptor')
1193
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001194
Nick Coghlan2f92e542012-06-23 19:39:55 +10001195_global_ref = object()
1196class TestGetClosureVars(unittest.TestCase):
1197
1198 def test_name_resolution(self):
1199 # Basic test of the 4 different resolution mechanisms
1200 def f(nonlocal_ref):
1201 def g(local_ref):
1202 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1203 return g
1204 _arg = object()
1205 nonlocal_vars = {"nonlocal_ref": _arg}
1206 global_vars = {"_global_ref": _global_ref}
1207 builtin_vars = {"print": print}
1208 unbound_names = {"unbound_ref"}
1209 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1210 builtin_vars, unbound_names)
1211 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1212
1213 def test_generator_closure(self):
1214 def f(nonlocal_ref):
1215 def g(local_ref):
1216 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1217 yield
1218 return g
1219 _arg = object()
1220 nonlocal_vars = {"nonlocal_ref": _arg}
1221 global_vars = {"_global_ref": _global_ref}
1222 builtin_vars = {"print": print}
1223 unbound_names = {"unbound_ref"}
1224 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1225 builtin_vars, unbound_names)
1226 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1227
1228 def test_method_closure(self):
1229 class C:
1230 def f(self, nonlocal_ref):
1231 def g(local_ref):
1232 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1233 return g
1234 _arg = object()
1235 nonlocal_vars = {"nonlocal_ref": _arg}
1236 global_vars = {"_global_ref": _global_ref}
1237 builtin_vars = {"print": print}
1238 unbound_names = {"unbound_ref"}
1239 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1240 builtin_vars, unbound_names)
1241 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1242
1243 def test_nonlocal_vars(self):
1244 # More complex tests of nonlocal resolution
1245 def _nonlocal_vars(f):
1246 return inspect.getclosurevars(f).nonlocals
1247
1248 def make_adder(x):
1249 def add(y):
1250 return x + y
1251 return add
1252
1253 def curry(func, arg1):
1254 return lambda arg2: func(arg1, arg2)
1255
1256 def less_than(a, b):
1257 return a < b
1258
1259 # The infamous Y combinator.
1260 def Y(le):
1261 def g(f):
1262 return le(lambda x: f(f)(x))
1263 Y.g_ref = g
1264 return g(g)
1265
1266 def check_y_combinator(func):
1267 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1268
1269 inc = make_adder(1)
1270 add_two = make_adder(2)
1271 greater_than_five = curry(less_than, 5)
1272
1273 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1274 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1275 self.assertEqual(_nonlocal_vars(greater_than_five),
1276 {'arg1': 5, 'func': less_than})
1277 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1278 {'x': 3})
1279 Y(check_y_combinator)
1280
1281 def test_getclosurevars_empty(self):
1282 def foo(): pass
1283 _empty = inspect.ClosureVars({}, {}, {}, set())
1284 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1285 self.assertEqual(inspect.getclosurevars(foo), _empty)
1286
1287 def test_getclosurevars_error(self):
1288 class T: pass
1289 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1290 self.assertRaises(TypeError, inspect.getclosurevars, list)
1291 self.assertRaises(TypeError, inspect.getclosurevars, {})
1292
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001293 def _private_globals(self):
1294 code = """def f(): print(path)"""
1295 ns = {}
1296 exec(code, ns)
1297 return ns["f"], ns
1298
1299 def test_builtins_fallback(self):
1300 f, ns = self._private_globals()
1301 ns.pop("__builtins__", None)
1302 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1303 self.assertEqual(inspect.getclosurevars(f), expected)
1304
1305 def test_builtins_as_dict(self):
1306 f, ns = self._private_globals()
1307 ns["__builtins__"] = {"path":1}
1308 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1309 self.assertEqual(inspect.getclosurevars(f), expected)
1310
1311 def test_builtins_as_module(self):
1312 f, ns = self._private_globals()
1313 ns["__builtins__"] = os
1314 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1315 self.assertEqual(inspect.getclosurevars(f), expected)
1316
Nick Coghlan2f92e542012-06-23 19:39:55 +10001317
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001318class TestGetcallargsFunctions(unittest.TestCase):
1319
1320 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1321 locs = dict(locs or {}, func=func)
1322 r1 = eval('func(%s)' % call_params_string, None, locs)
1323 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1324 locs)
1325 self.assertEqual(r1, r2)
1326
1327 def assertEqualException(self, func, call_param_string, locs=None):
1328 locs = dict(locs or {}, func=func)
1329 try:
1330 eval('func(%s)' % call_param_string, None, locs)
1331 except Exception as e:
1332 ex1 = e
1333 else:
1334 self.fail('Exception not raised')
1335 try:
1336 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1337 locs)
1338 except Exception as e:
1339 ex2 = e
1340 else:
1341 self.fail('Exception not raised')
1342 self.assertIs(type(ex1), type(ex2))
1343 self.assertEqual(str(ex1), str(ex2))
1344 del ex1, ex2
1345
1346 def makeCallable(self, signature):
1347 """Create a function that returns its locals()"""
1348 code = "lambda %s: locals()"
1349 return eval(code % signature)
1350
1351 def test_plain(self):
1352 f = self.makeCallable('a, b=1')
1353 self.assertEqualCallArgs(f, '2')
1354 self.assertEqualCallArgs(f, '2, 3')
1355 self.assertEqualCallArgs(f, 'a=2')
1356 self.assertEqualCallArgs(f, 'b=3, a=2')
1357 self.assertEqualCallArgs(f, '2, b=3')
1358 # expand *iterable / **mapping
1359 self.assertEqualCallArgs(f, '*(2,)')
1360 self.assertEqualCallArgs(f, '*[2]')
1361 self.assertEqualCallArgs(f, '*(2, 3)')
1362 self.assertEqualCallArgs(f, '*[2, 3]')
1363 self.assertEqualCallArgs(f, '**{"a":2}')
1364 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1365 self.assertEqualCallArgs(f, '2, **{"b":3}')
1366 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1367 # expand UserList / UserDict
1368 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1369 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1370 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1371 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1372 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1373
1374 def test_varargs(self):
1375 f = self.makeCallable('a, b=1, *c')
1376 self.assertEqualCallArgs(f, '2')
1377 self.assertEqualCallArgs(f, '2, 3')
1378 self.assertEqualCallArgs(f, '2, 3, 4')
1379 self.assertEqualCallArgs(f, '*(2,3,4)')
1380 self.assertEqualCallArgs(f, '2, *[3,4]')
1381 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1382
1383 def test_varkw(self):
1384 f = self.makeCallable('a, b=1, **c')
1385 self.assertEqualCallArgs(f, 'a=2')
1386 self.assertEqualCallArgs(f, '2, b=3, c=4')
1387 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1388 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1389 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1390 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1391 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1392 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1393 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1394
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001395 def test_varkw_only(self):
1396 # issue11256:
1397 f = self.makeCallable('**c')
1398 self.assertEqualCallArgs(f, '')
1399 self.assertEqualCallArgs(f, 'a=1')
1400 self.assertEqualCallArgs(f, 'a=1, b=2')
1401 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1402 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1403 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1404
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001405 def test_keyword_only(self):
1406 f = self.makeCallable('a=3, *, c, d=2')
1407 self.assertEqualCallArgs(f, 'c=3')
1408 self.assertEqualCallArgs(f, 'c=3, a=3')
1409 self.assertEqualCallArgs(f, 'a=2, c=4')
1410 self.assertEqualCallArgs(f, '4, c=4')
1411 self.assertEqualException(f, '')
1412 self.assertEqualException(f, '3')
1413 self.assertEqualException(f, 'a=3')
1414 self.assertEqualException(f, 'd=4')
1415
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001416 f = self.makeCallable('*, c, d=2')
1417 self.assertEqualCallArgs(f, 'c=3')
1418 self.assertEqualCallArgs(f, 'c=3, d=4')
1419 self.assertEqualCallArgs(f, 'd=4, c=3')
1420
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001421 def test_multiple_features(self):
1422 f = self.makeCallable('a, b=2, *f, **g')
1423 self.assertEqualCallArgs(f, '2, 3, 7')
1424 self.assertEqualCallArgs(f, '2, 3, x=8')
1425 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1426 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1427 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1428 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1429 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1430 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1431 '(4,[5,6])]), **collections.UserDict('
1432 'y=9, z=10)')
1433
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001434 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1435 self.assertEqualCallArgs(f, '2, 3, x=8')
1436 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1437 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1438 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1439 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1440 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1441 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1442 '(4,[5,6])]), q=0, **collections.UserDict('
1443 'y=9, z=10)')
1444
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001445 def test_errors(self):
1446 f0 = self.makeCallable('')
1447 f1 = self.makeCallable('a, b')
1448 f2 = self.makeCallable('a, b=1')
1449 # f0 takes no arguments
1450 self.assertEqualException(f0, '1')
1451 self.assertEqualException(f0, 'x=1')
1452 self.assertEqualException(f0, '1,x=1')
1453 # f1 takes exactly 2 arguments
1454 self.assertEqualException(f1, '')
1455 self.assertEqualException(f1, '1')
1456 self.assertEqualException(f1, 'a=2')
1457 self.assertEqualException(f1, 'b=3')
1458 # f2 takes at least 1 argument
1459 self.assertEqualException(f2, '')
1460 self.assertEqualException(f2, 'b=3')
1461 for f in f1, f2:
1462 # f1/f2 takes exactly/at most 2 arguments
1463 self.assertEqualException(f, '2, 3, 4')
1464 self.assertEqualException(f, '1, 2, 3, a=1')
1465 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001466 # XXX: success of this one depends on dict order
1467 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001468 # f got an unexpected keyword argument
1469 self.assertEqualException(f, 'c=2')
1470 self.assertEqualException(f, '2, c=3')
1471 self.assertEqualException(f, '2, 3, c=4')
1472 self.assertEqualException(f, '2, c=4, b=3')
1473 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1474 # f got multiple values for keyword argument
1475 self.assertEqualException(f, '1, a=2')
1476 self.assertEqualException(f, '1, **{"a":2}')
1477 self.assertEqualException(f, '1, 2, b=3')
1478 # XXX: Python inconsistency
1479 # - for functions and bound methods: unexpected keyword 'c'
1480 # - for unbound methods: multiple values for keyword 'a'
1481 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001482 # issue11256:
1483 f3 = self.makeCallable('**c')
1484 self.assertEqualException(f3, '1, 2')
1485 self.assertEqualException(f3, '1, 2, a=1, b=2')
1486 f4 = self.makeCallable('*, a, b=0')
1487 self.assertEqualException(f3, '1, 2')
1488 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001489
Yury Selivanov875df202014-03-27 18:23:03 -04001490 # issue #20816: getcallargs() fails to iterate over non-existent
1491 # kwonlydefaults and raises a wrong TypeError
1492 def f5(*, a): pass
1493 with self.assertRaisesRegex(TypeError,
1494 'missing 1 required keyword-only'):
1495 inspect.getcallargs(f5)
1496
1497
Yury Selivanovdccfa132014-03-27 18:42:52 -04001498 # issue20817:
1499 def f6(a, b, c):
1500 pass
1501 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1502 inspect.getcallargs(f6)
1503
Dong-hee Naa9cab432018-05-30 00:04:08 +09001504 # bpo-33197
1505 with self.assertRaisesRegex(ValueError,
1506 'variadic keyword parameters cannot'
1507 ' have default values'):
1508 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1509 default=42)
1510 with self.assertRaisesRegex(ValueError,
1511 "value 5 is not a valid Parameter.kind"):
1512 inspect.Parameter("bar", kind=5, default=42)
1513
1514 with self.assertRaisesRegex(TypeError,
1515 'name must be a str, not a int'):
1516 inspect.Parameter(123, kind=4)
1517
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001518class TestGetcallargsMethods(TestGetcallargsFunctions):
1519
1520 def setUp(self):
1521 class Foo(object):
1522 pass
1523 self.cls = Foo
1524 self.inst = Foo()
1525
1526 def makeCallable(self, signature):
1527 assert 'self' not in signature
1528 mk = super(TestGetcallargsMethods, self).makeCallable
1529 self.cls.method = mk('self, ' + signature)
1530 return self.inst.method
1531
1532class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1533
1534 def makeCallable(self, signature):
1535 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1536 return self.cls.method
1537
1538 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1539 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1540 *self._getAssertEqualParams(func, call_params_string, locs))
1541
1542 def assertEqualException(self, func, call_params_string, locs=None):
1543 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1544 *self._getAssertEqualParams(func, call_params_string, locs))
1545
1546 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1547 assert 'inst' not in call_params_string
1548 locs = dict(locs or {}, inst=self.inst)
1549 return (func, 'inst,' + call_params_string, locs)
1550
Michael Foord95fc51d2010-11-20 15:07:30 +00001551
1552class TestGetattrStatic(unittest.TestCase):
1553
1554 def test_basic(self):
1555 class Thing(object):
1556 x = object()
1557
1558 thing = Thing()
1559 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1560 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1561 with self.assertRaises(AttributeError):
1562 inspect.getattr_static(thing, 'y')
1563
1564 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1565
1566 def test_inherited(self):
1567 class Thing(object):
1568 x = object()
1569 class OtherThing(Thing):
1570 pass
1571
1572 something = OtherThing()
1573 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1574
1575 def test_instance_attr(self):
1576 class Thing(object):
1577 x = 2
1578 def __init__(self, x):
1579 self.x = x
1580 thing = Thing(3)
1581 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1582 del thing.x
1583 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1584
1585 def test_property(self):
1586 class Thing(object):
1587 @property
1588 def x(self):
1589 raise AttributeError("I'm pretending not to exist")
1590 thing = Thing()
1591 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1592
Ezio Melotti75cbd732011-04-28 00:59:29 +03001593 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001594 class descriptor(object):
1595 def __get__(*_):
1596 raise AttributeError("I'm pretending not to exist")
1597 desc = descriptor()
1598 class Thing(object):
1599 x = desc
1600 thing = Thing()
1601 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1602
1603 def test_classAttribute(self):
1604 class Thing(object):
1605 x = object()
1606
1607 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1608
Ethan Furmane03ea372013-09-25 07:14:41 -07001609 def test_classVirtualAttribute(self):
1610 class Thing(object):
1611 @types.DynamicClassAttribute
1612 def x(self):
1613 return self._x
1614 _x = object()
1615
1616 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1617
Michael Foord95fc51d2010-11-20 15:07:30 +00001618 def test_inherited_classattribute(self):
1619 class Thing(object):
1620 x = object()
1621 class OtherThing(Thing):
1622 pass
1623
1624 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1625
1626 def test_slots(self):
1627 class Thing(object):
1628 y = 'bar'
1629 __slots__ = ['x']
1630 def __init__(self):
1631 self.x = 'foo'
1632 thing = Thing()
1633 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1634 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1635
1636 del thing.x
1637 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1638
1639 def test_metaclass(self):
1640 class meta(type):
1641 attr = 'foo'
1642 class Thing(object, metaclass=meta):
1643 pass
1644 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1645
1646 class sub(meta):
1647 pass
1648 class OtherThing(object, metaclass=sub):
1649 x = 3
1650 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1651
1652 class OtherOtherThing(OtherThing):
1653 pass
1654 # this test is odd, but it was added as it exposed a bug
1655 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1656
1657 def test_no_dict_no_slots(self):
1658 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1659 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1660
1661 def test_no_dict_no_slots_instance_member(self):
1662 # returns descriptor
1663 with open(__file__) as handle:
1664 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1665
1666 def test_inherited_slots(self):
1667 # returns descriptor
1668 class Thing(object):
1669 __slots__ = ['x']
1670 def __init__(self):
1671 self.x = 'foo'
1672
1673 class OtherThing(Thing):
1674 pass
1675 # it would be nice if this worked...
1676 # we get the descriptor instead of the instance attribute
1677 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1678
1679 def test_descriptor(self):
1680 class descriptor(object):
1681 def __get__(self, instance, owner):
1682 return 3
1683 class Foo(object):
1684 d = descriptor()
1685
1686 foo = Foo()
1687
1688 # for a non data descriptor we return the instance attribute
1689 foo.__dict__['d'] = 1
1690 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1691
Mike53f7a7c2017-12-14 14:04:53 +03001692 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001693 # descriptor
1694 descriptor.__set__ = lambda s, i, v: None
1695 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1696
1697
1698 def test_metaclass_with_descriptor(self):
1699 class descriptor(object):
1700 def __get__(self, instance, owner):
1701 return 3
1702 class meta(type):
1703 d = descriptor()
1704 class Thing(object, metaclass=meta):
1705 pass
1706 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1707
1708
Michael Foordcc7ebb82010-11-20 16:20:16 +00001709 def test_class_as_property(self):
1710 class Base(object):
1711 foo = 3
1712
1713 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001714 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001715 @property
1716 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001717 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001718 return object
1719
Michael Foord35184ed2010-11-20 16:58:30 +00001720 instance = Something()
1721 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1722 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001723 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1724
Michael Foorde5162652010-11-20 16:40:44 +00001725 def test_mro_as_property(self):
1726 class Meta(type):
1727 @property
1728 def __mro__(self):
1729 return (object,)
1730
1731 class Base(object):
1732 foo = 3
1733
1734 class Something(Base, metaclass=Meta):
1735 pass
1736
1737 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1738 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1739
Michael Foorddcebe0f2011-03-15 19:20:44 -04001740 def test_dict_as_property(self):
1741 test = self
1742 test.called = False
1743
1744 class Foo(dict):
1745 a = 3
1746 @property
1747 def __dict__(self):
1748 test.called = True
1749 return {}
1750
1751 foo = Foo()
1752 foo.a = 4
1753 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1754 self.assertFalse(test.called)
1755
1756 def test_custom_object_dict(self):
1757 test = self
1758 test.called = False
1759
1760 class Custom(dict):
1761 def get(self, key, default=None):
1762 test.called = True
1763 super().get(key, default)
1764
1765 class Foo(object):
1766 a = 3
1767 foo = Foo()
1768 foo.__dict__ = Custom()
1769 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1770 self.assertFalse(test.called)
1771
1772 def test_metaclass_dict_as_property(self):
1773 class Meta(type):
1774 @property
1775 def __dict__(self):
1776 self.executed = True
1777
1778 class Thing(metaclass=Meta):
1779 executed = False
1780
1781 def __init__(self):
1782 self.spam = 42
1783
1784 instance = Thing()
1785 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1786 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001787
Michael Foorda51623b2011-12-18 22:01:40 +00001788 def test_module(self):
1789 sentinel = object()
1790 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1791 sentinel)
1792
Michael Foord3ba95f82011-12-22 01:13:37 +00001793 def test_metaclass_with_metaclass_with_dict_as_property(self):
1794 class MetaMeta(type):
1795 @property
1796 def __dict__(self):
1797 self.executed = True
1798 return dict(spam=42)
1799
1800 class Meta(type, metaclass=MetaMeta):
1801 executed = False
1802
1803 class Thing(metaclass=Meta):
1804 pass
1805
1806 with self.assertRaises(AttributeError):
1807 inspect.getattr_static(Thing, "spam")
1808 self.assertFalse(Thing.executed)
1809
Nick Coghlane0f04652010-11-21 03:44:04 +00001810class TestGetGeneratorState(unittest.TestCase):
1811
1812 def setUp(self):
1813 def number_generator():
1814 for number in range(5):
1815 yield number
1816 self.generator = number_generator()
1817
1818 def _generatorstate(self):
1819 return inspect.getgeneratorstate(self.generator)
1820
1821 def test_created(self):
1822 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1823
1824 def test_suspended(self):
1825 next(self.generator)
1826 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1827
1828 def test_closed_after_exhaustion(self):
1829 for i in self.generator:
1830 pass
1831 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1832
1833 def test_closed_after_immediate_exception(self):
1834 with self.assertRaises(RuntimeError):
1835 self.generator.throw(RuntimeError)
1836 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1837
1838 def test_running(self):
1839 # As mentioned on issue #10220, checking for the RUNNING state only
1840 # makes sense inside the generator itself.
1841 # The following generator checks for this by using the closure's
1842 # reference to self and the generator state checking helper method
1843 def running_check_generator():
1844 for number in range(5):
1845 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1846 yield number
1847 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1848 self.generator = running_check_generator()
1849 # Running up to the first yield
1850 next(self.generator)
1851 # Running after the first yield
1852 next(self.generator)
1853
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001854 def test_easy_debugging(self):
1855 # repr() and str() of a generator state should contain the state name
1856 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1857 for name in names:
1858 state = getattr(inspect, name)
1859 self.assertIn(name, repr(state))
1860 self.assertIn(name, str(state))
1861
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001862 def test_getgeneratorlocals(self):
1863 def each(lst, a=None):
1864 b=(1, 2, 3)
1865 for v in lst:
1866 if v == 3:
1867 c = 12
1868 yield v
1869
1870 numbers = each([1, 2, 3])
1871 self.assertEqual(inspect.getgeneratorlocals(numbers),
1872 {'a': None, 'lst': [1, 2, 3]})
1873 next(numbers)
1874 self.assertEqual(inspect.getgeneratorlocals(numbers),
1875 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1876 'b': (1, 2, 3)})
1877 next(numbers)
1878 self.assertEqual(inspect.getgeneratorlocals(numbers),
1879 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1880 'b': (1, 2, 3)})
1881 next(numbers)
1882 self.assertEqual(inspect.getgeneratorlocals(numbers),
1883 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1884 'b': (1, 2, 3), 'c': 12})
1885 try:
1886 next(numbers)
1887 except StopIteration:
1888 pass
1889 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1890
1891 def test_getgeneratorlocals_empty(self):
1892 def yield_one():
1893 yield 1
1894 one = yield_one()
1895 self.assertEqual(inspect.getgeneratorlocals(one), {})
1896 try:
1897 next(one)
1898 except StopIteration:
1899 pass
1900 self.assertEqual(inspect.getgeneratorlocals(one), {})
1901
1902 def test_getgeneratorlocals_error(self):
1903 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1904 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1905 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1906 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1907
Nick Coghlane0f04652010-11-21 03:44:04 +00001908
Yury Selivanov5376ba92015-06-22 12:19:30 -04001909class TestGetCoroutineState(unittest.TestCase):
1910
1911 def setUp(self):
1912 @types.coroutine
1913 def number_coroutine():
1914 for number in range(5):
1915 yield number
1916 async def coroutine():
1917 await number_coroutine()
1918 self.coroutine = coroutine()
1919
1920 def tearDown(self):
1921 self.coroutine.close()
1922
1923 def _coroutinestate(self):
1924 return inspect.getcoroutinestate(self.coroutine)
1925
1926 def test_created(self):
1927 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1928
1929 def test_suspended(self):
1930 self.coroutine.send(None)
1931 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1932
1933 def test_closed_after_exhaustion(self):
1934 while True:
1935 try:
1936 self.coroutine.send(None)
1937 except StopIteration:
1938 break
1939
1940 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1941
1942 def test_closed_after_immediate_exception(self):
1943 with self.assertRaises(RuntimeError):
1944 self.coroutine.throw(RuntimeError)
1945 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1946
1947 def test_easy_debugging(self):
1948 # repr() and str() of a coroutine state should contain the state name
1949 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1950 for name in names:
1951 state = getattr(inspect, name)
1952 self.assertIn(name, repr(state))
1953 self.assertIn(name, str(state))
1954
1955 def test_getcoroutinelocals(self):
1956 @types.coroutine
1957 def gencoro():
1958 yield
1959
1960 gencoro = gencoro()
1961 async def func(a=None):
1962 b = 'spam'
1963 await gencoro
1964
1965 coro = func()
1966 self.assertEqual(inspect.getcoroutinelocals(coro),
1967 {'a': None, 'gencoro': gencoro})
1968 coro.send(None)
1969 self.assertEqual(inspect.getcoroutinelocals(coro),
1970 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
1971
1972
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001973class MySignature(inspect.Signature):
1974 # Top-level to make it picklable;
1975 # used in test_signature_object_pickle
1976 pass
1977
1978class MyParameter(inspect.Parameter):
1979 # Top-level to make it picklable;
1980 # used in test_signature_object_pickle
1981 pass
1982
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001983
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001984
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001985class TestSignatureObject(unittest.TestCase):
1986 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04001987 def signature(func, **kw):
1988 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001989 return (tuple((param.name,
1990 (... if param.default is param.empty else param.default),
1991 (... if param.annotation is param.empty
1992 else param.annotation),
1993 str(param.kind).lower())
1994 for param in sig.parameters.values()),
1995 (... if sig.return_annotation is sig.empty
1996 else sig.return_annotation))
1997
1998 def test_signature_object(self):
1999 S = inspect.Signature
2000 P = inspect.Parameter
2001
2002 self.assertEqual(str(S()), '()')
2003
Yury Selivanov07a9e452014-01-29 10:58:16 -05002004 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002005 pass
2006 sig = inspect.signature(test)
2007 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002008 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002009 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002010 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002011 args = sig.parameters['args']
2012 ko = sig.parameters['ko']
2013 kwargs = sig.parameters['kwargs']
2014
2015 S((po, pk, args, ko, kwargs))
2016
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002017 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002018 S((pk, po, args, ko, kwargs))
2019
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002020 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002021 S((po, args, pk, ko, kwargs))
2022
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002023 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002024 S((args, po, pk, ko, kwargs))
2025
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002026 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002027 S((po, pk, args, kwargs, ko))
2028
2029 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002030 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002031 S((po, pk, args, kwargs2, ko))
2032
Yury Selivanov07a9e452014-01-29 10:58:16 -05002033 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2034 S((pod, po))
2035
2036 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2037 S((po, pkd, pk))
2038
2039 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2040 S((pkd, pk))
2041
Yury Selivanov374375d2014-03-27 12:41:53 -04002042 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002043 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002044
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002045 def test_signature_object_pickle(self):
2046 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2047 foo_partial = functools.partial(foo, a=1)
2048
2049 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002050
2051 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2052 with self.subTest(pickle_ver=ver, subclass=False):
2053 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2054 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002055
2056 # Test that basic sub-classing works
2057 sig = inspect.signature(foo)
2058 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2059 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2060 mysig = MySignature().replace(parameters=myparams.values(),
2061 return_annotation=sig.return_annotation)
2062 self.assertTrue(isinstance(mysig, MySignature))
2063 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2064
2065 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2066 with self.subTest(pickle_ver=ver, subclass=True):
2067 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2068 self.assertEqual(mysig, sig_pickled)
2069 self.assertTrue(isinstance(sig_pickled, MySignature))
2070 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2071 MyParameter))
2072
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002073 def test_signature_immutability(self):
2074 def test(a):
2075 pass
2076 sig = inspect.signature(test)
2077
2078 with self.assertRaises(AttributeError):
2079 sig.foo = 'bar'
2080
2081 with self.assertRaises(TypeError):
2082 sig.parameters['a'] = None
2083
2084 def test_signature_on_noarg(self):
2085 def test():
2086 pass
2087 self.assertEqual(self.signature(test), ((), ...))
2088
2089 def test_signature_on_wargs(self):
2090 def test(a, b:'foo') -> 123:
2091 pass
2092 self.assertEqual(self.signature(test),
2093 ((('a', ..., ..., "positional_or_keyword"),
2094 ('b', ..., 'foo', "positional_or_keyword")),
2095 123))
2096
2097 def test_signature_on_wkwonly(self):
2098 def test(*, a:float, b:str) -> int:
2099 pass
2100 self.assertEqual(self.signature(test),
2101 ((('a', ..., float, "keyword_only"),
2102 ('b', ..., str, "keyword_only")),
2103 int))
2104
2105 def test_signature_on_complex_args(self):
2106 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2107 pass
2108 self.assertEqual(self.signature(test),
2109 ((('a', ..., ..., "positional_or_keyword"),
2110 ('b', 10, 'foo', "positional_or_keyword"),
2111 ('args', ..., 'bar', "var_positional"),
2112 ('spam', ..., 'baz', "keyword_only"),
2113 ('ham', 123, ..., "keyword_only"),
2114 ('kwargs', ..., int, "var_keyword")),
2115 ...))
2116
Dong-hee Na378d7062017-05-18 04:00:51 +09002117 def test_signature_without_self(self):
2118 def test_args_only(*args): # NOQA
2119 pass
2120
2121 def test_args_kwargs_only(*args, **kwargs): # NOQA
2122 pass
2123
2124 class A:
2125 @classmethod
2126 def test_classmethod(*args): # NOQA
2127 pass
2128
2129 @staticmethod
2130 def test_staticmethod(*args): # NOQA
2131 pass
2132
2133 f1 = functools.partialmethod((test_classmethod), 1)
2134 f2 = functools.partialmethod((test_args_only), 1)
2135 f3 = functools.partialmethod((test_staticmethod), 1)
2136 f4 = functools.partialmethod((test_args_kwargs_only),1)
2137
2138 self.assertEqual(self.signature(test_args_only),
2139 ((('args', ..., ..., 'var_positional'),), ...))
2140 self.assertEqual(self.signature(test_args_kwargs_only),
2141 ((('args', ..., ..., 'var_positional'),
2142 ('kwargs', ..., ..., 'var_keyword')), ...))
2143 self.assertEqual(self.signature(A.f1),
2144 ((('args', ..., ..., 'var_positional'),), ...))
2145 self.assertEqual(self.signature(A.f2),
2146 ((('args', ..., ..., 'var_positional'),), ...))
2147 self.assertEqual(self.signature(A.f3),
2148 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002149 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002150 ((('args', ..., ..., 'var_positional'),
2151 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002152 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002153 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2154 "Signature information for builtins requires docstrings")
2155 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002156 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002157
Larry Hastings5c661892014-01-24 06:17:25 -08002158 def test_unbound_method(o):
2159 """Use this to test unbound methods (things that should have a self)"""
2160 signature = inspect.signature(o)
2161 self.assertTrue(isinstance(signature, inspect.Signature))
2162 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2163 return signature
2164
2165 def test_callable(o):
2166 """Use this to test bound methods or normal callables (things that don't expect self)"""
2167 signature = inspect.signature(o)
2168 self.assertTrue(isinstance(signature, inspect.Signature))
2169 if signature.parameters:
2170 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2171 return signature
2172
2173 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002174 def p(name): return signature.parameters[name].default
2175 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002176 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002177 self.assertEqual(p('d'), 3.14)
2178 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002179 self.assertEqual(p('n'), None)
2180 self.assertEqual(p('t'), True)
2181 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002182 self.assertEqual(p('local'), 3)
2183 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002184 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002185
Larry Hastings5c661892014-01-24 06:17:25 -08002186 test_callable(object)
2187
2188 # normal method
2189 # (PyMethodDescr_Type, "method_descriptor")
2190 test_unbound_method(_pickle.Pickler.dump)
2191 d = _pickle.Pickler(io.StringIO())
2192 test_callable(d.dump)
2193
2194 # static method
2195 test_callable(str.maketrans)
2196 test_callable('abc'.maketrans)
2197
2198 # class method
2199 test_callable(dict.fromkeys)
2200 test_callable({}.fromkeys)
2201
2202 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2203 test_unbound_method(type.__call__)
2204 test_unbound_method(int.__add__)
2205 test_callable((3).__add__)
2206
2207 # _PyMethodWrapper_Type
2208 # support for 'method-wrapper'
2209 test_callable(min.__call__)
2210
Larry Hastings2623c8c2014-02-08 22:15:29 -08002211 # This doesn't work now.
2212 # (We don't have a valid signature for "type" in 3.4)
2213 with self.assertRaisesRegex(ValueError, "no signature found"):
2214 class ThisWorksNow:
2215 __call__ = type
2216 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002217
Yury Selivanov056e2652014-03-02 12:25:27 -05002218 # Regression test for issue #20786
2219 test_unbound_method(dict.__delitem__)
2220 test_unbound_method(property.__delete__)
2221
Zachary Ware8ef887c2015-04-13 18:22:35 -05002222 # Regression test for issue #20586
2223 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2224
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002225 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002226 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2227 "Signature information for builtins requires docstrings")
2228 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002229 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002230 func = _testcapi.docstring_with_signature_with_defaults
2231
2232 def decorator(func):
2233 @functools.wraps(func)
2234 def wrapper(*args, **kwargs) -> int:
2235 return func(*args, **kwargs)
2236 return wrapper
2237
2238 decorated_func = decorator(func)
2239
2240 self.assertEqual(inspect.signature(func),
2241 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002242
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002243 def wrapper_like(*args, **kwargs) -> int: pass
2244 self.assertEqual(inspect.signature(decorated_func,
2245 follow_wrapped=False),
2246 inspect.signature(wrapper_like))
2247
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002248 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002249 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002250 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002251 with self.assertRaisesRegex(ValueError,
2252 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002253 inspect.signature(_testcapi.docstring_no_signature)
2254
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002255 with self.assertRaisesRegex(ValueError,
2256 'no signature found for builtin'):
2257 inspect.signature(str)
2258
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002259 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002260 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002261 inspect.signature(42)
2262
Yury Selivanov63da7c72014-01-31 14:48:37 -05002263 def test_signature_from_functionlike_object(self):
2264 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2265 pass
2266
2267 class funclike:
2268 # Has to be callable, and have correct
2269 # __code__, __annotations__, __defaults__, __name__,
2270 # and __kwdefaults__ attributes
2271
2272 def __init__(self, func):
2273 self.__name__ = func.__name__
2274 self.__code__ = func.__code__
2275 self.__annotations__ = func.__annotations__
2276 self.__defaults__ = func.__defaults__
2277 self.__kwdefaults__ = func.__kwdefaults__
2278 self.func = func
2279
2280 def __call__(self, *args, **kwargs):
2281 return self.func(*args, **kwargs)
2282
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002283 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002284
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002285 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002286 self.assertEqual(sig_funclike, sig_func)
2287
2288 sig_funclike = inspect.signature(funclike(func))
2289 self.assertEqual(sig_funclike, sig_func)
2290
2291 # If object is not a duck type of function, then
2292 # signature will try to get a signature for its '__call__'
2293 # method
2294 fl = funclike(func)
2295 del fl.__defaults__
2296 self.assertEqual(self.signature(fl),
2297 ((('args', ..., ..., "var_positional"),
2298 ('kwargs', ..., ..., "var_keyword")),
2299 ...))
2300
Yury Selivanova773de02014-02-21 18:30:53 -05002301 # Test with cython-like builtins:
2302 _orig_isdesc = inspect.ismethoddescriptor
2303 def _isdesc(obj):
2304 if hasattr(obj, '_builtinmock'):
2305 return True
2306 return _orig_isdesc(obj)
2307
2308 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2309 builtin_func = funclike(func)
2310 # Make sure that our mock setup is working
2311 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2312 builtin_func._builtinmock = True
2313 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2314 self.assertEqual(inspect.signature(builtin_func), sig_func)
2315
Yury Selivanov63da7c72014-01-31 14:48:37 -05002316 def test_signature_functionlike_class(self):
2317 # We only want to duck type function-like objects,
2318 # not classes.
2319
2320 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2321 pass
2322
2323 class funclike:
2324 def __init__(self, marker):
2325 pass
2326
2327 __name__ = func.__name__
2328 __code__ = func.__code__
2329 __annotations__ = func.__annotations__
2330 __defaults__ = func.__defaults__
2331 __kwdefaults__ = func.__kwdefaults__
2332
Yury Selivanov63da7c72014-01-31 14:48:37 -05002333 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2334
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002335 def test_signature_on_method(self):
2336 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002337 def __init__(*args):
2338 pass
2339 def m1(self, arg1, arg2=1) -> int:
2340 pass
2341 def m2(*args):
2342 pass
2343 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002344 pass
2345
Yury Selivanov62560fb2014-01-28 12:26:24 -05002346 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002347 ((('arg1', ..., ..., "positional_or_keyword"),
2348 ('arg2', 1, ..., "positional_or_keyword")),
2349 int))
2350
Yury Selivanov62560fb2014-01-28 12:26:24 -05002351 self.assertEqual(self.signature(Test().m2),
2352 ((('args', ..., ..., "var_positional"),),
2353 ...))
2354
2355 self.assertEqual(self.signature(Test),
2356 ((('args', ..., ..., "var_positional"),),
2357 ...))
2358
2359 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2360 self.signature(Test())
2361
Yury Selivanov46c759d2015-05-27 21:56:53 -04002362 def test_signature_wrapped_bound_method(self):
2363 # Issue 24298
2364 class Test:
2365 def m1(self, arg1, arg2=1) -> int:
2366 pass
2367 @functools.wraps(Test().m1)
2368 def m1d(*args, **kwargs):
2369 pass
2370 self.assertEqual(self.signature(m1d),
2371 ((('arg1', ..., ..., "positional_or_keyword"),
2372 ('arg2', 1, ..., "positional_or_keyword")),
2373 int))
2374
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002375 def test_signature_on_classmethod(self):
2376 class Test:
2377 @classmethod
2378 def foo(cls, arg1, *, arg2=1):
2379 pass
2380
2381 meth = Test().foo
2382 self.assertEqual(self.signature(meth),
2383 ((('arg1', ..., ..., "positional_or_keyword"),
2384 ('arg2', 1, ..., "keyword_only")),
2385 ...))
2386
2387 meth = Test.foo
2388 self.assertEqual(self.signature(meth),
2389 ((('arg1', ..., ..., "positional_or_keyword"),
2390 ('arg2', 1, ..., "keyword_only")),
2391 ...))
2392
2393 def test_signature_on_staticmethod(self):
2394 class Test:
2395 @staticmethod
2396 def foo(cls, *, arg):
2397 pass
2398
2399 meth = Test().foo
2400 self.assertEqual(self.signature(meth),
2401 ((('cls', ..., ..., "positional_or_keyword"),
2402 ('arg', ..., ..., "keyword_only")),
2403 ...))
2404
2405 meth = Test.foo
2406 self.assertEqual(self.signature(meth),
2407 ((('cls', ..., ..., "positional_or_keyword"),
2408 ('arg', ..., ..., "keyword_only")),
2409 ...))
2410
2411 def test_signature_on_partial(self):
2412 from functools import partial
2413
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002414 Parameter = inspect.Parameter
2415
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002416 def test():
2417 pass
2418
2419 self.assertEqual(self.signature(partial(test)), ((), ...))
2420
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002421 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002422 inspect.signature(partial(test, 1))
2423
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002424 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002425 inspect.signature(partial(test, a=1))
2426
2427 def test(a, b, *, c, d):
2428 pass
2429
2430 self.assertEqual(self.signature(partial(test)),
2431 ((('a', ..., ..., "positional_or_keyword"),
2432 ('b', ..., ..., "positional_or_keyword"),
2433 ('c', ..., ..., "keyword_only"),
2434 ('d', ..., ..., "keyword_only")),
2435 ...))
2436
2437 self.assertEqual(self.signature(partial(test, 1)),
2438 ((('b', ..., ..., "positional_or_keyword"),
2439 ('c', ..., ..., "keyword_only"),
2440 ('d', ..., ..., "keyword_only")),
2441 ...))
2442
2443 self.assertEqual(self.signature(partial(test, 1, c=2)),
2444 ((('b', ..., ..., "positional_or_keyword"),
2445 ('c', 2, ..., "keyword_only"),
2446 ('d', ..., ..., "keyword_only")),
2447 ...))
2448
2449 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2450 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002451 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002452 ('c', 2, ..., "keyword_only"),
2453 ('d', ..., ..., "keyword_only")),
2454 ...))
2455
2456 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002457 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002458 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002459 ('d', ..., ..., "keyword_only")),
2460 ...))
2461
2462 self.assertEqual(self.signature(partial(test, a=1)),
2463 ((('a', 1, ..., "keyword_only"),
2464 ('b', ..., ..., "keyword_only"),
2465 ('c', ..., ..., "keyword_only"),
2466 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002467 ...))
2468
2469 def test(a, *args, b, **kwargs):
2470 pass
2471
2472 self.assertEqual(self.signature(partial(test, 1)),
2473 ((('args', ..., ..., "var_positional"),
2474 ('b', ..., ..., "keyword_only"),
2475 ('kwargs', ..., ..., "var_keyword")),
2476 ...))
2477
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002478 self.assertEqual(self.signature(partial(test, a=1)),
2479 ((('a', 1, ..., "keyword_only"),
2480 ('b', ..., ..., "keyword_only"),
2481 ('kwargs', ..., ..., "var_keyword")),
2482 ...))
2483
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002484 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2485 ((('args', ..., ..., "var_positional"),
2486 ('b', ..., ..., "keyword_only"),
2487 ('kwargs', ..., ..., "var_keyword")),
2488 ...))
2489
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002490 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2491 ((('args', ..., ..., "var_positional"),
2492 ('b', ..., ..., "keyword_only"),
2493 ('kwargs', ..., ..., "var_keyword")),
2494 ...))
2495
2496 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2497 ((('args', ..., ..., "var_positional"),
2498 ('b', 0, ..., "keyword_only"),
2499 ('kwargs', ..., ..., "var_keyword")),
2500 ...))
2501
2502 self.assertEqual(self.signature(partial(test, b=0)),
2503 ((('a', ..., ..., "positional_or_keyword"),
2504 ('args', ..., ..., "var_positional"),
2505 ('b', 0, ..., "keyword_only"),
2506 ('kwargs', ..., ..., "var_keyword")),
2507 ...))
2508
2509 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2510 ((('a', ..., ..., "positional_or_keyword"),
2511 ('args', ..., ..., "var_positional"),
2512 ('b', 0, ..., "keyword_only"),
2513 ('kwargs', ..., ..., "var_keyword")),
2514 ...))
2515
2516 def test(a, b, c:int) -> 42:
2517 pass
2518
2519 sig = test.__signature__ = inspect.signature(test)
2520
2521 self.assertEqual(self.signature(partial(partial(test, 1))),
2522 ((('b', ..., ..., "positional_or_keyword"),
2523 ('c', ..., int, "positional_or_keyword")),
2524 42))
2525
2526 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2527 ((('c', ..., int, "positional_or_keyword"),),
2528 42))
2529
2530 psig = inspect.signature(partial(partial(test, 1), 2))
2531
2532 def foo(a):
2533 return a
2534 _foo = partial(partial(foo, a=10), a=20)
2535 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002536 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002537 ...))
2538 # check that we don't have any side-effects in signature(),
2539 # and the partial object is still functioning
2540 self.assertEqual(_foo(), 20)
2541
2542 def foo(a, b, c):
2543 return a, b, c
2544 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002545
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002546 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002547 ((('b', 30, ..., "keyword_only"),
2548 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002549 ...))
2550 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002551
2552 def foo(a, b, c, *, d):
2553 return a, b, c, d
2554 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2555 self.assertEqual(self.signature(_foo),
2556 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002557 ('b', 10, ..., "keyword_only"),
2558 ('c', 20, ..., "keyword_only"),
2559 ('d', 30, ..., "keyword_only"),
2560 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002561 ...))
2562 ba = inspect.signature(_foo).bind(a=200, b=11)
2563 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2564
2565 def foo(a=1, b=2, c=3):
2566 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002567 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2568
2569 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002570 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002571
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002572 ba = inspect.signature(_foo).bind(11, 12)
2573 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002574
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002575 ba = inspect.signature(_foo).bind(11, b=12)
2576 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002577
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002578 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002579 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2580
2581 _foo = partial(_foo, b=10, c=20)
2582 ba = inspect.signature(_foo).bind(12)
2583 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2584
2585
2586 def foo(a, b, c, d, **kwargs):
2587 pass
2588 sig = inspect.signature(foo)
2589 params = sig.parameters.copy()
2590 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2591 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2592 foo.__signature__ = inspect.Signature(params.values())
2593 sig = inspect.signature(foo)
2594 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2595
2596 self.assertEqual(self.signature(partial(foo, 1)),
2597 ((('b', ..., ..., 'positional_only'),
2598 ('c', ..., ..., 'positional_or_keyword'),
2599 ('d', ..., ..., 'positional_or_keyword'),
2600 ('kwargs', ..., ..., 'var_keyword')),
2601 ...))
2602
2603 self.assertEqual(self.signature(partial(foo, 1, 2)),
2604 ((('c', ..., ..., 'positional_or_keyword'),
2605 ('d', ..., ..., 'positional_or_keyword'),
2606 ('kwargs', ..., ..., 'var_keyword')),
2607 ...))
2608
2609 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2610 ((('d', ..., ..., 'positional_or_keyword'),
2611 ('kwargs', ..., ..., 'var_keyword')),
2612 ...))
2613
2614 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2615 ((('c', 3, ..., 'keyword_only'),
2616 ('d', ..., ..., 'keyword_only'),
2617 ('kwargs', ..., ..., 'var_keyword')),
2618 ...))
2619
2620 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2621 ((('b', ..., ..., 'positional_only'),
2622 ('c', 3, ..., 'keyword_only'),
2623 ('d', ..., ..., 'keyword_only'),
2624 ('kwargs', ..., ..., 'var_keyword')),
2625 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002626
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002627 def test_signature_on_partialmethod(self):
2628 from functools import partialmethod
2629
2630 class Spam:
2631 def test():
2632 pass
2633 ham = partialmethod(test)
2634
2635 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2636 inspect.signature(Spam.ham)
2637
2638 class Spam:
2639 def test(it, a, *, c) -> 'spam':
2640 pass
2641 ham = partialmethod(test, c=1)
2642
2643 self.assertEqual(self.signature(Spam.ham),
2644 ((('it', ..., ..., 'positional_or_keyword'),
2645 ('a', ..., ..., 'positional_or_keyword'),
2646 ('c', 1, ..., 'keyword_only')),
2647 'spam'))
2648
2649 self.assertEqual(self.signature(Spam().ham),
2650 ((('a', ..., ..., 'positional_or_keyword'),
2651 ('c', 1, ..., 'keyword_only')),
2652 'spam'))
2653
Yury Selivanov8a387212018-03-06 12:59:45 -05002654 class Spam:
2655 def test(self: 'anno', x):
2656 pass
2657
2658 g = partialmethod(test, 1)
2659
2660 self.assertEqual(self.signature(Spam.g),
2661 ((('self', ..., 'anno', 'positional_or_keyword'),),
2662 ...))
2663
Yury Selivanov0486f812014-01-29 12:18:59 -05002664 def test_signature_on_fake_partialmethod(self):
2665 def foo(a): pass
2666 foo._partialmethod = 'spam'
2667 self.assertEqual(str(inspect.signature(foo)), '(a)')
2668
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002669 def test_signature_on_decorated(self):
2670 import functools
2671
2672 def decorator(func):
2673 @functools.wraps(func)
2674 def wrapper(*args, **kwargs) -> int:
2675 return func(*args, **kwargs)
2676 return wrapper
2677
2678 class Foo:
2679 @decorator
2680 def bar(self, a, b):
2681 pass
2682
2683 self.assertEqual(self.signature(Foo.bar),
2684 ((('self', ..., ..., "positional_or_keyword"),
2685 ('a', ..., ..., "positional_or_keyword"),
2686 ('b', ..., ..., "positional_or_keyword")),
2687 ...))
2688
2689 self.assertEqual(self.signature(Foo().bar),
2690 ((('a', ..., ..., "positional_or_keyword"),
2691 ('b', ..., ..., "positional_or_keyword")),
2692 ...))
2693
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002694 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2695 ((('args', ..., ..., "var_positional"),
2696 ('kwargs', ..., ..., "var_keyword")),
2697 ...)) # functools.wraps will copy __annotations__
2698 # from "func" to "wrapper", hence no
2699 # return_annotation
2700
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002701 # Test that we handle method wrappers correctly
2702 def decorator(func):
2703 @functools.wraps(func)
2704 def wrapper(*args, **kwargs) -> int:
2705 return func(42, *args, **kwargs)
2706 sig = inspect.signature(func)
2707 new_params = tuple(sig.parameters.values())[1:]
2708 wrapper.__signature__ = sig.replace(parameters=new_params)
2709 return wrapper
2710
2711 class Foo:
2712 @decorator
2713 def __call__(self, a, b):
2714 pass
2715
2716 self.assertEqual(self.signature(Foo.__call__),
2717 ((('a', ..., ..., "positional_or_keyword"),
2718 ('b', ..., ..., "positional_or_keyword")),
2719 ...))
2720
2721 self.assertEqual(self.signature(Foo().__call__),
2722 ((('b', ..., ..., "positional_or_keyword"),),
2723 ...))
2724
Nick Coghlane8c45d62013-07-28 20:00:01 +10002725 # Test we handle __signature__ partway down the wrapper stack
2726 def wrapped_foo_call():
2727 pass
2728 wrapped_foo_call.__wrapped__ = Foo.__call__
2729
2730 self.assertEqual(self.signature(wrapped_foo_call),
2731 ((('a', ..., ..., "positional_or_keyword"),
2732 ('b', ..., ..., "positional_or_keyword")),
2733 ...))
2734
2735
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002736 def test_signature_on_class(self):
2737 class C:
2738 def __init__(self, a):
2739 pass
2740
2741 self.assertEqual(self.signature(C),
2742 ((('a', ..., ..., "positional_or_keyword"),),
2743 ...))
2744
2745 class CM(type):
2746 def __call__(cls, a):
2747 pass
2748 class C(metaclass=CM):
2749 def __init__(self, b):
2750 pass
2751
2752 self.assertEqual(self.signature(C),
2753 ((('a', ..., ..., "positional_or_keyword"),),
2754 ...))
2755
2756 class CM(type):
2757 def __new__(mcls, name, bases, dct, *, foo=1):
2758 return super().__new__(mcls, name, bases, dct)
2759 class C(metaclass=CM):
2760 def __init__(self, b):
2761 pass
2762
2763 self.assertEqual(self.signature(C),
2764 ((('b', ..., ..., "positional_or_keyword"),),
2765 ...))
2766
2767 self.assertEqual(self.signature(CM),
2768 ((('name', ..., ..., "positional_or_keyword"),
2769 ('bases', ..., ..., "positional_or_keyword"),
2770 ('dct', ..., ..., "positional_or_keyword"),
2771 ('foo', 1, ..., "keyword_only")),
2772 ...))
2773
2774 class CMM(type):
2775 def __new__(mcls, name, bases, dct, *, foo=1):
2776 return super().__new__(mcls, name, bases, dct)
2777 def __call__(cls, nm, bs, dt):
2778 return type(nm, bs, dt)
2779 class CM(type, metaclass=CMM):
2780 def __new__(mcls, name, bases, dct, *, bar=2):
2781 return super().__new__(mcls, name, bases, dct)
2782 class C(metaclass=CM):
2783 def __init__(self, b):
2784 pass
2785
2786 self.assertEqual(self.signature(CMM),
2787 ((('name', ..., ..., "positional_or_keyword"),
2788 ('bases', ..., ..., "positional_or_keyword"),
2789 ('dct', ..., ..., "positional_or_keyword"),
2790 ('foo', 1, ..., "keyword_only")),
2791 ...))
2792
2793 self.assertEqual(self.signature(CM),
2794 ((('nm', ..., ..., "positional_or_keyword"),
2795 ('bs', ..., ..., "positional_or_keyword"),
2796 ('dt', ..., ..., "positional_or_keyword")),
2797 ...))
2798
2799 self.assertEqual(self.signature(C),
2800 ((('b', ..., ..., "positional_or_keyword"),),
2801 ...))
2802
2803 class CM(type):
2804 def __init__(cls, name, bases, dct, *, bar=2):
2805 return super().__init__(name, bases, dct)
2806 class C(metaclass=CM):
2807 def __init__(self, b):
2808 pass
2809
2810 self.assertEqual(self.signature(CM),
2811 ((('name', ..., ..., "positional_or_keyword"),
2812 ('bases', ..., ..., "positional_or_keyword"),
2813 ('dct', ..., ..., "positional_or_keyword"),
2814 ('bar', 2, ..., "keyword_only")),
2815 ...))
2816
Yury Selivanov145dff82014-02-01 13:49:29 -05002817 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2818 "Signature information for builtins requires docstrings")
2819 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002820 # Test classes without user-defined __init__ or __new__
2821 class C: pass
2822 self.assertEqual(str(inspect.signature(C)), '()')
2823 class D(C): pass
2824 self.assertEqual(str(inspect.signature(D)), '()')
2825
2826 # Test meta-classes without user-defined __init__ or __new__
2827 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002828 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002829 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2830 self.assertEqual(inspect.signature(C), None)
2831 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2832 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002833
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002834 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2835 "Signature information for builtins requires docstrings")
2836 def test_signature_on_builtin_class(self):
2837 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2838 '(file, protocol=None, fix_imports=True)')
2839
2840 class P(_pickle.Pickler): pass
2841 class EmptyTrait: pass
2842 class P2(EmptyTrait, P): pass
2843 self.assertEqual(str(inspect.signature(P)),
2844 '(file, protocol=None, fix_imports=True)')
2845 self.assertEqual(str(inspect.signature(P2)),
2846 '(file, protocol=None, fix_imports=True)')
2847
2848 class P3(P2):
2849 def __init__(self, spam):
2850 pass
2851 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2852
2853 class MetaP(type):
2854 def __call__(cls, foo, bar):
2855 pass
2856 class P4(P2, metaclass=MetaP):
2857 pass
2858 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2859
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002860 def test_signature_on_callable_objects(self):
2861 class Foo:
2862 def __call__(self, a):
2863 pass
2864
2865 self.assertEqual(self.signature(Foo()),
2866 ((('a', ..., ..., "positional_or_keyword"),),
2867 ...))
2868
2869 class Spam:
2870 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002871 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002872 inspect.signature(Spam())
2873
2874 class Bar(Spam, Foo):
2875 pass
2876
2877 self.assertEqual(self.signature(Bar()),
2878 ((('a', ..., ..., "positional_or_keyword"),),
2879 ...))
2880
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002881 class Wrapped:
2882 pass
2883 Wrapped.__wrapped__ = lambda a: None
2884 self.assertEqual(self.signature(Wrapped),
2885 ((('a', ..., ..., "positional_or_keyword"),),
2886 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002887 # wrapper loop:
2888 Wrapped.__wrapped__ = Wrapped
2889 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2890 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002891
2892 def test_signature_on_lambdas(self):
2893 self.assertEqual(self.signature((lambda a=10: a)),
2894 ((('a', 10, ..., "positional_or_keyword"),),
2895 ...))
2896
2897 def test_signature_equality(self):
2898 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002899 self.assertFalse(inspect.signature(foo) == 42)
2900 self.assertTrue(inspect.signature(foo) != 42)
2901 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2902 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002903
2904 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002905 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2906 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002907 self.assertEqual(
2908 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002909
2910 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002911 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2912 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002913 self.assertNotEqual(
2914 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002915
2916 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002917 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2918 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002919 self.assertNotEqual(
2920 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002921
2922 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002923 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2924 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002925 self.assertNotEqual(
2926 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002927
2928 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002929 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2930 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002931 self.assertNotEqual(
2932 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002933
2934 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002935 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2936 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002937 self.assertNotEqual(
2938 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002939 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002940 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
2941 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002942 self.assertNotEqual(
2943 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002944
2945 def foo(*, a, b, c): pass
2946 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002947 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2948 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002949 self.assertEqual(
2950 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002951
2952 def foo(*, a=1, b, c): pass
2953 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002954 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2955 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002956 self.assertEqual(
2957 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002958
2959 def foo(pos, *, a=1, b, c): pass
2960 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002961 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2962 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002963 self.assertEqual(
2964 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002965
2966 def foo(pos, *, a, b, c): pass
2967 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002968 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2969 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002970 self.assertNotEqual(
2971 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002972
2973 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2974 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002975 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2976 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002977 self.assertEqual(
2978 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002979
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002980 def test_signature_hashable(self):
2981 S = inspect.Signature
2982 P = inspect.Parameter
2983
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002984 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002985 foo_sig = inspect.signature(foo)
2986
2987 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2988
2989 self.assertEqual(hash(foo_sig), hash(manual_sig))
2990 self.assertNotEqual(hash(foo_sig),
2991 hash(manual_sig.replace(return_annotation='spam')))
2992
2993 def bar(a) -> 1: pass
2994 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2995
2996 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002997 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002998 hash(inspect.signature(foo))
2999
3000 def foo(a) -> {}: pass
3001 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3002 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003003
3004 def test_signature_str(self):
3005 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3006 pass
3007 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003008 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003009
3010 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3011 pass
3012 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003013 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003014
3015 def foo():
3016 pass
3017 self.assertEqual(str(inspect.signature(foo)), '()')
3018
3019 def test_signature_str_positional_only(self):
3020 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003021 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003022
3023 def test(a_po, *, b, **kwargs):
3024 return a_po, kwargs
3025
3026 sig = inspect.signature(test)
3027 new_params = list(sig.parameters.values())
3028 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3029 test.__signature__ = sig.replace(parameters=new_params)
3030
3031 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003032 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003033
Yury Selivanov2393dca2014-01-27 15:07:58 -05003034 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3035 '(foo, /)')
3036
3037 self.assertEqual(str(S(parameters=[
3038 P('foo', P.POSITIONAL_ONLY),
3039 P('bar', P.VAR_KEYWORD)])),
3040 '(foo, /, **bar)')
3041
3042 self.assertEqual(str(S(parameters=[
3043 P('foo', P.POSITIONAL_ONLY),
3044 P('bar', P.VAR_POSITIONAL)])),
3045 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003046
3047 def test_signature_replace_anno(self):
3048 def test() -> 42:
3049 pass
3050
3051 sig = inspect.signature(test)
3052 sig = sig.replace(return_annotation=None)
3053 self.assertIs(sig.return_annotation, None)
3054 sig = sig.replace(return_annotation=sig.empty)
3055 self.assertIs(sig.return_annotation, sig.empty)
3056 sig = sig.replace(return_annotation=42)
3057 self.assertEqual(sig.return_annotation, 42)
3058 self.assertEqual(sig, inspect.signature(test))
3059
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003060 def test_signature_on_mangled_parameters(self):
3061 class Spam:
3062 def foo(self, __p1:1=2, *, __p2:2=3):
3063 pass
3064 class Ham(Spam):
3065 pass
3066
3067 self.assertEqual(self.signature(Spam.foo),
3068 ((('self', ..., ..., "positional_or_keyword"),
3069 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3070 ('_Spam__p2', 3, 2, "keyword_only")),
3071 ...))
3072
3073 self.assertEqual(self.signature(Spam.foo),
3074 self.signature(Ham.foo))
3075
Yury Selivanovda396452014-03-27 12:09:24 -04003076 def test_signature_from_callable_python_obj(self):
3077 class MySignature(inspect.Signature): pass
3078 def foo(a, *, b:1): pass
3079 foo_sig = MySignature.from_callable(foo)
3080 self.assertTrue(isinstance(foo_sig, MySignature))
3081
3082 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3083 "Signature information for builtins requires docstrings")
3084 def test_signature_from_callable_builtin_obj(self):
3085 class MySignature(inspect.Signature): pass
3086 sig = MySignature.from_callable(_pickle.Pickler)
3087 self.assertTrue(isinstance(sig, MySignature))
3088
larryhastingsf36ba122018-01-28 11:13:09 -08003089 def test_signature_definition_order_preserved_on_kwonly(self):
3090 for fn in signatures_with_lexicographic_keyword_only_parameters():
3091 signature = inspect.signature(fn)
3092 l = list(signature.parameters)
3093 sorted_l = sorted(l)
3094 self.assertTrue(l)
3095 self.assertEqual(l, sorted_l)
3096 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3097 l = list(signature.parameters)
3098 self.assertEqual(l, unsorted_keyword_only_parameters)
3099
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003100
3101class TestParameterObject(unittest.TestCase):
3102 def test_signature_parameter_kinds(self):
3103 P = inspect.Parameter
3104 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3105 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3106
3107 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3108 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3109
3110 def test_signature_parameter_object(self):
3111 p = inspect.Parameter('foo', default=10,
3112 kind=inspect.Parameter.POSITIONAL_ONLY)
3113 self.assertEqual(p.name, 'foo')
3114 self.assertEqual(p.default, 10)
3115 self.assertIs(p.annotation, p.empty)
3116 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3117
Dong-hee Naa9cab432018-05-30 00:04:08 +09003118 with self.assertRaisesRegex(ValueError, "value '123' is "
3119 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003120 inspect.Parameter('foo', default=10, kind='123')
3121
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003122 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003123 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3124
Yury Selivanov2393dca2014-01-27 15:07:58 -05003125 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003126 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3127
Yury Selivanov2393dca2014-01-27 15:07:58 -05003128 with self.assertRaisesRegex(ValueError,
3129 'is not a valid parameter name'):
3130 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3131
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003132 with self.assertRaisesRegex(ValueError,
3133 'is not a valid parameter name'):
3134 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3135
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003136 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003137 inspect.Parameter('a', default=42,
3138 kind=inspect.Parameter.VAR_KEYWORD)
3139
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003140 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003141 inspect.Parameter('a', default=42,
3142 kind=inspect.Parameter.VAR_POSITIONAL)
3143
3144 p = inspect.Parameter('a', default=42,
3145 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003146 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003147 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3148
3149 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003150 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003151
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003152 def test_signature_parameter_hashable(self):
3153 P = inspect.Parameter
3154 foo = P('foo', kind=P.POSITIONAL_ONLY)
3155 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3156 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3157 default=42)))
3158 self.assertNotEqual(hash(foo),
3159 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3160
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003161 def test_signature_parameter_equality(self):
3162 P = inspect.Parameter
3163 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3164
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003165 self.assertTrue(p == p)
3166 self.assertFalse(p != p)
3167 self.assertFalse(p == 42)
3168 self.assertTrue(p != 42)
3169 self.assertTrue(p == EqualsToAll())
3170 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003171
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003172 self.assertTrue(p == P('foo', default=42,
3173 kind=inspect.Parameter.KEYWORD_ONLY))
3174 self.assertFalse(p != P('foo', default=42,
3175 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003176
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003177 def test_signature_parameter_replace(self):
3178 p = inspect.Parameter('foo', default=42,
3179 kind=inspect.Parameter.KEYWORD_ONLY)
3180
3181 self.assertIsNot(p, p.replace())
3182 self.assertEqual(p, p.replace())
3183
3184 p2 = p.replace(annotation=1)
3185 self.assertEqual(p2.annotation, 1)
3186 p2 = p2.replace(annotation=p2.empty)
3187 self.assertEqual(p, p2)
3188
3189 p2 = p2.replace(name='bar')
3190 self.assertEqual(p2.name, 'bar')
3191 self.assertNotEqual(p2, p)
3192
Yury Selivanov2393dca2014-01-27 15:07:58 -05003193 with self.assertRaisesRegex(ValueError,
3194 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003195 p2 = p2.replace(name=p2.empty)
3196
3197 p2 = p2.replace(name='foo', default=None)
3198 self.assertIs(p2.default, None)
3199 self.assertNotEqual(p2, p)
3200
3201 p2 = p2.replace(name='foo', default=p2.empty)
3202 self.assertIs(p2.default, p2.empty)
3203
3204
3205 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3206 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3207 self.assertNotEqual(p2, p)
3208
Dong-hee Naa9cab432018-05-30 00:04:08 +09003209 with self.assertRaisesRegex(ValueError,
3210 "value <class 'inspect._empty'> "
3211 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003212 p2 = p2.replace(kind=p2.empty)
3213
3214 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3215 self.assertEqual(p2, p)
3216
3217 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003218 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3219 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003220
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003221 @cpython_only
3222 def test_signature_parameter_implicit(self):
3223 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003224 'implicit arguments must be passed as '
3225 'positional or keyword arguments, '
3226 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003227 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3228
3229 param = inspect.Parameter(
3230 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3231 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3232 self.assertEqual(param.name, 'implicit0')
3233
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003234 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003235 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003236
3237 with self.assertRaises(AttributeError):
3238 p.foo = 'bar'
3239
3240 with self.assertRaises(AttributeError):
3241 p.kind = 123
3242
3243
3244class TestSignatureBind(unittest.TestCase):
3245 @staticmethod
3246 def call(func, *args, **kwargs):
3247 sig = inspect.signature(func)
3248 ba = sig.bind(*args, **kwargs)
3249 return func(*ba.args, **ba.kwargs)
3250
3251 def test_signature_bind_empty(self):
3252 def test():
3253 return 42
3254
3255 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003256 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003257 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003258 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003259 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003260 with self.assertRaisesRegex(
3261 TypeError, "got an unexpected keyword argument 'spam'"):
3262
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003263 self.call(test, spam=1)
3264
3265 def test_signature_bind_var(self):
3266 def test(*args, **kwargs):
3267 return args, kwargs
3268
3269 self.assertEqual(self.call(test), ((), {}))
3270 self.assertEqual(self.call(test, 1), ((1,), {}))
3271 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3272 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3273 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3274 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3275 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3276 ((1, 2), {'foo': 'bar'}))
3277
3278 def test_signature_bind_just_args(self):
3279 def test(a, b, c):
3280 return a, b, c
3281
3282 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3283
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003284 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003285 self.call(test, 1, 2, 3, 4)
3286
Yury Selivanov86872752015-05-19 00:27:49 -04003287 with self.assertRaisesRegex(TypeError,
3288 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003289 self.call(test, 1)
3290
Yury Selivanov86872752015-05-19 00:27:49 -04003291 with self.assertRaisesRegex(TypeError,
3292 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003293 self.call(test)
3294
3295 def test(a, b, c=10):
3296 return a, b, c
3297 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3298 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3299
3300 def test(a=1, b=2, c=3):
3301 return a, b, c
3302 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3303 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3304 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3305
3306 def test_signature_bind_varargs_order(self):
3307 def test(*args):
3308 return args
3309
3310 self.assertEqual(self.call(test), ())
3311 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3312
3313 def test_signature_bind_args_and_varargs(self):
3314 def test(a, b, c=3, *args):
3315 return a, b, c, args
3316
3317 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3318 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3319 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3320 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3321
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003322 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003323 "multiple values for argument 'c'"):
3324 self.call(test, 1, 2, 3, c=4)
3325
3326 def test_signature_bind_just_kwargs(self):
3327 def test(**kwargs):
3328 return kwargs
3329
3330 self.assertEqual(self.call(test), {})
3331 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3332 {'foo': 'bar', 'spam': 'ham'})
3333
3334 def test_signature_bind_args_and_kwargs(self):
3335 def test(a, b, c=3, **kwargs):
3336 return a, b, c, kwargs
3337
3338 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3339 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3340 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3341 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3342 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3343 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3344 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3345 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3346 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3347 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3348 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3349 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3350 (1, 2, 4, {'foo': 'bar'}))
3351 self.assertEqual(self.call(test, c=5, a=4, b=3),
3352 (4, 3, 5, {}))
3353
3354 def test_signature_bind_kwonly(self):
3355 def test(*, foo):
3356 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003357 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003358 'too many positional arguments'):
3359 self.call(test, 1)
3360 self.assertEqual(self.call(test, foo=1), 1)
3361
3362 def test(a, *, foo=1, bar):
3363 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003364 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003365 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003366 self.call(test, 1)
3367
3368 def test(foo, *, bar):
3369 return foo, bar
3370 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3371 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3372
Yury Selivanov86872752015-05-19 00:27:49 -04003373 with self.assertRaisesRegex(
3374 TypeError, "got an unexpected keyword argument 'spam'"):
3375
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003376 self.call(test, bar=2, foo=1, spam=10)
3377
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003378 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003379 'too many positional arguments'):
3380 self.call(test, 1, 2)
3381
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003382 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003383 'too many positional arguments'):
3384 self.call(test, 1, 2, bar=2)
3385
Yury Selivanov86872752015-05-19 00:27:49 -04003386 with self.assertRaisesRegex(
3387 TypeError, "got an unexpected keyword argument 'spam'"):
3388
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003389 self.call(test, 1, bar=2, spam='ham')
3390
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003391 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003392 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003393 self.call(test, 1)
3394
3395 def test(foo, *, bar, **bin):
3396 return foo, bar, bin
3397 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3398 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3399 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3400 (1, 2, {'spam': 'ham'}))
3401 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3402 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003403 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003404 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003405 self.call(test, spam='ham', bar=2)
3406 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3407 (1, 2, {'bin': 1, 'spam': 10}))
3408
3409 def test_signature_bind_arguments(self):
3410 def test(a, *args, b, z=100, **kwargs):
3411 pass
3412 sig = inspect.signature(test)
3413 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3414 # we won't have 'z' argument in the bound arguments object, as we didn't
3415 # pass it to the 'bind'
3416 self.assertEqual(tuple(ba.arguments.items()),
3417 (('a', 10), ('args', (20,)), ('b', 30),
3418 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3419 self.assertEqual(ba.kwargs,
3420 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3421 self.assertEqual(ba.args, (10, 20))
3422
3423 def test_signature_bind_positional_only(self):
3424 P = inspect.Parameter
3425
3426 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3427 return a_po, b_po, c_po, foo, bar, kwargs
3428
3429 sig = inspect.signature(test)
3430 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3431 for name in ('a_po', 'b_po', 'c_po'):
3432 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3433 new_sig = sig.replace(parameters=new_params.values())
3434 test.__signature__ = new_sig
3435
3436 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3437 (1, 2, 4, 5, 6, {}))
3438
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003439 self.assertEqual(self.call(test, 1, 2),
3440 (1, 2, 3, 42, 50, {}))
3441
3442 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3443 (1, 2, 3, 4, 5, {}))
3444
3445 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3446 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3447
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003448 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003449 self.call(test, 1, 2, c_po=4)
3450
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003451 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003452 self.call(test, a_po=1, b_po=2)
3453
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003454 def test_signature_bind_with_self_arg(self):
3455 # Issue #17071: one of the parameters is named "self
3456 def test(a, self, b):
3457 pass
3458 sig = inspect.signature(test)
3459 ba = sig.bind(1, 2, 3)
3460 self.assertEqual(ba.args, (1, 2, 3))
3461 ba = sig.bind(1, self=2, b=3)
3462 self.assertEqual(ba.args, (1, 2, 3))
3463
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003464 def test_signature_bind_vararg_name(self):
3465 def test(a, *args):
3466 return a, args
3467 sig = inspect.signature(test)
3468
Yury Selivanov86872752015-05-19 00:27:49 -04003469 with self.assertRaisesRegex(
3470 TypeError, "got an unexpected keyword argument 'args'"):
3471
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003472 sig.bind(a=0, args=1)
3473
3474 def test(*args, **kwargs):
3475 return args, kwargs
3476 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3477
3478 sig = inspect.signature(test)
3479 ba = sig.bind(args=1)
3480 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3481
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003482 @cpython_only
3483 def test_signature_bind_implicit_arg(self):
3484 # Issue #19611: getcallargs should work with set comprehensions
3485 def make_set():
3486 return {z * z for z in range(5)}
3487 setcomp_code = make_set.__code__.co_consts[1]
3488 setcomp_func = types.FunctionType(setcomp_code, {})
3489
3490 iterator = iter(range(5))
3491 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3492
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003493
3494class TestBoundArguments(unittest.TestCase):
3495 def test_signature_bound_arguments_unhashable(self):
3496 def foo(a): pass
3497 ba = inspect.signature(foo).bind(1)
3498
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003499 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003500 hash(ba)
3501
3502 def test_signature_bound_arguments_equality(self):
3503 def foo(a): pass
3504 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003505 self.assertTrue(ba == ba)
3506 self.assertFalse(ba != ba)
3507 self.assertTrue(ba == EqualsToAll())
3508 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003509
3510 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003511 self.assertTrue(ba == ba2)
3512 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003513
3514 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003515 self.assertFalse(ba == ba3)
3516 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003517 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003518 self.assertTrue(ba == ba3)
3519 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003520
3521 def bar(b): pass
3522 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003523 self.assertFalse(ba == ba4)
3524 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003525
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003526 def foo(*, a, b): pass
3527 sig = inspect.signature(foo)
3528 ba1 = sig.bind(a=1, b=2)
3529 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003530 self.assertTrue(ba1 == ba2)
3531 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003532
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003533 def test_signature_bound_arguments_pickle(self):
3534 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3535 sig = inspect.signature(foo)
3536 ba = sig.bind(20, 30, z={})
3537
3538 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3539 with self.subTest(pickle_ver=ver):
3540 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3541 self.assertEqual(ba, ba_pickled)
3542
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003543 def test_signature_bound_arguments_repr(self):
3544 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3545 sig = inspect.signature(foo)
3546 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003547 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003548
Yury Selivanovb907a512015-05-16 13:45:09 -04003549 def test_signature_bound_arguments_apply_defaults(self):
3550 def foo(a, b=1, *args, c:1={}, **kw): pass
3551 sig = inspect.signature(foo)
3552
3553 ba = sig.bind(20)
3554 ba.apply_defaults()
3555 self.assertEqual(
3556 list(ba.arguments.items()),
3557 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3558
3559 # Make sure that we preserve the order:
3560 # i.e. 'c' should be *before* 'kw'.
3561 ba = sig.bind(10, 20, 30, d=1)
3562 ba.apply_defaults()
3563 self.assertEqual(
3564 list(ba.arguments.items()),
3565 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3566
3567 # Make sure that BoundArguments produced by bind_partial()
3568 # are supported.
3569 def foo(a, b): pass
3570 sig = inspect.signature(foo)
3571 ba = sig.bind_partial(20)
3572 ba.apply_defaults()
3573 self.assertEqual(
3574 list(ba.arguments.items()),
3575 [('a', 20)])
3576
3577 # Test no args
3578 def foo(): pass
3579 sig = inspect.signature(foo)
3580 ba = sig.bind()
3581 ba.apply_defaults()
3582 self.assertEqual(list(ba.arguments.items()), [])
3583
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003584 # Make sure a no-args binding still acquires proper defaults.
3585 def foo(a='spam'): pass
3586 sig = inspect.signature(foo)
3587 ba = sig.bind()
3588 ba.apply_defaults()
3589 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3590
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003591
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003592class TestSignaturePrivateHelpers(unittest.TestCase):
3593 def test_signature_get_bound_param(self):
3594 getter = inspect._signature_get_bound_param
3595
3596 self.assertEqual(getter('($self)'), 'self')
3597 self.assertEqual(getter('($self, obj)'), 'self')
3598 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3599
Larry Hastings2623c8c2014-02-08 22:15:29 -08003600 def _strip_non_python_syntax(self, input,
3601 clean_signature, self_parameter, last_positional_only):
3602 computed_clean_signature, \
3603 computed_self_parameter, \
3604 computed_last_positional_only = \
3605 inspect._signature_strip_non_python_syntax(input)
3606 self.assertEqual(computed_clean_signature, clean_signature)
3607 self.assertEqual(computed_self_parameter, self_parameter)
3608 self.assertEqual(computed_last_positional_only, last_positional_only)
3609
3610 def test_signature_strip_non_python_syntax(self):
3611 self._strip_non_python_syntax(
3612 "($module, /, path, mode, *, dir_fd=None, " +
3613 "effective_ids=False,\n follow_symlinks=True)",
3614 "(module, path, mode, *, dir_fd=None, " +
3615 "effective_ids=False, follow_symlinks=True)",
3616 0,
3617 0)
3618
3619 self._strip_non_python_syntax(
3620 "($module, word, salt, /)",
3621 "(module, word, salt)",
3622 0,
3623 2)
3624
3625 self._strip_non_python_syntax(
3626 "(x, y=None, z=None, /)",
3627 "(x, y=None, z=None)",
3628 None,
3629 2)
3630
3631 self._strip_non_python_syntax(
3632 "(x, y=None, z=None)",
3633 "(x, y=None, z=None)",
3634 None,
3635 None)
3636
3637 self._strip_non_python_syntax(
3638 "(x,\n y=None,\n z = None )",
3639 "(x, y=None, z=None)",
3640 None,
3641 None)
3642
3643 self._strip_non_python_syntax(
3644 "",
3645 "",
3646 None,
3647 None)
3648
3649 self._strip_non_python_syntax(
3650 None,
3651 None,
3652 None,
3653 None)
3654
Nick Coghlan9c680b02015-04-13 12:54:54 -04003655class TestSignatureDefinitions(unittest.TestCase):
3656 # This test case provides a home for checking that particular APIs
3657 # have signatures available for introspection
3658
3659 @cpython_only
3660 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3661 "Signature information for builtins requires docstrings")
3662 def test_builtins_have_signatures(self):
3663 # This checks all builtin callables in CPython have signatures
3664 # A few have signatures Signature can't yet handle, so we skip those
3665 # since they will have to wait until PEP 457 adds the required
3666 # introspection support to the inspect module
3667 # Some others also haven't been converted yet for various other
3668 # reasons, so we also skip those for the time being, but design
3669 # the test to fail in order to indicate when it needs to be
3670 # updated.
3671 no_signature = set()
3672 # These need PEP 457 groups
3673 needs_groups = {"range", "slice", "dir", "getattr",
3674 "next", "iter", "vars"}
3675 no_signature |= needs_groups
3676 # These need PEP 457 groups or a signature change to accept None
3677 needs_semantic_update = {"round"}
3678 no_signature |= needs_semantic_update
3679 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003680 needs_varargs = {"breakpoint", "min", "max", "print",
3681 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003682 no_signature |= needs_varargs
3683 # These simply weren't covered in the initial AC conversion
3684 # for builtin callables
3685 not_converted_yet = {"open", "__import__"}
3686 no_signature |= not_converted_yet
3687 # These builtin types are expected to provide introspection info
3688 types_with_signatures = set()
3689 # Check the signatures we expect to be there
3690 ns = vars(builtins)
3691 for name, obj in sorted(ns.items()):
3692 if not callable(obj):
3693 continue
3694 # The builtin types haven't been converted to AC yet
3695 if isinstance(obj, type) and (name not in types_with_signatures):
3696 # Note that this also skips all the exception types
3697 no_signature.add(name)
3698 if (name in no_signature):
3699 # Not yet converted
3700 continue
3701 with self.subTest(builtin=name):
3702 self.assertIsNotNone(inspect.signature(obj))
3703 # Check callables that haven't been converted don't claim a signature
3704 # This ensures this test will start failing as more signatures are
3705 # added, so the affected items can be moved into the scope of the
3706 # regression test above
3707 for name in no_signature:
3708 with self.subTest(builtin=name):
3709 self.assertIsNone(obj.__text_signature__)
3710
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003711
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003712class NTimesUnwrappable:
3713 def __init__(self, n):
3714 self.n = n
3715 self._next = None
3716
3717 @property
3718 def __wrapped__(self):
3719 if self.n <= 0:
3720 raise Exception("Unwrapped too many times")
3721 if self._next is None:
3722 self._next = NTimesUnwrappable(self.n - 1)
3723 return self._next
3724
Nick Coghlane8c45d62013-07-28 20:00:01 +10003725class TestUnwrap(unittest.TestCase):
3726
3727 def test_unwrap_one(self):
3728 def func(a, b):
3729 return a + b
3730 wrapper = functools.lru_cache(maxsize=20)(func)
3731 self.assertIs(inspect.unwrap(wrapper), func)
3732
3733 def test_unwrap_several(self):
3734 def func(a, b):
3735 return a + b
3736 wrapper = func
3737 for __ in range(10):
3738 @functools.wraps(wrapper)
3739 def wrapper():
3740 pass
3741 self.assertIsNot(wrapper.__wrapped__, func)
3742 self.assertIs(inspect.unwrap(wrapper), func)
3743
3744 def test_stop(self):
3745 def func1(a, b):
3746 return a + b
3747 @functools.wraps(func1)
3748 def func2():
3749 pass
3750 @functools.wraps(func2)
3751 def wrapper():
3752 pass
3753 func2.stop_here = 1
3754 unwrapped = inspect.unwrap(wrapper,
3755 stop=(lambda f: hasattr(f, "stop_here")))
3756 self.assertIs(unwrapped, func2)
3757
3758 def test_cycle(self):
3759 def func1(): pass
3760 func1.__wrapped__ = func1
3761 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3762 inspect.unwrap(func1)
3763
3764 def func2(): pass
3765 func2.__wrapped__ = func1
3766 func1.__wrapped__ = func2
3767 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3768 inspect.unwrap(func1)
3769 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3770 inspect.unwrap(func2)
3771
3772 def test_unhashable(self):
3773 def func(): pass
3774 func.__wrapped__ = None
3775 class C:
3776 __hash__ = None
3777 __wrapped__ = func
3778 self.assertIsNone(inspect.unwrap(C()))
3779
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003780 def test_recursion_limit(self):
3781 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3782 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3783 inspect.unwrap(obj)
3784
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003785class TestMain(unittest.TestCase):
3786 def test_only_source(self):
3787 module = importlib.import_module('unittest')
3788 rc, out, err = assert_python_ok('-m', 'inspect',
3789 'unittest')
3790 lines = out.decode().splitlines()
3791 # ignore the final newline
3792 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3793 self.assertEqual(err, b'')
3794
Yury Selivanov42407ab2014-06-23 10:23:50 -07003795 def test_custom_getattr(self):
3796 def foo():
3797 pass
3798 foo.__signature__ = 42
3799 with self.assertRaises(TypeError):
3800 inspect.signature(foo)
3801
Brett Cannon634a8fc2013-10-02 10:25:42 -04003802 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003803 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003804 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003805 rc, out, err = assert_python_ok('-m', 'inspect',
3806 'concurrent.futures:ThreadPoolExecutor')
3807 lines = out.decode().splitlines()
3808 # ignore the final newline
3809 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003810 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003811 self.assertEqual(err, b'')
3812
3813 def test_builtins(self):
3814 module = importlib.import_module('unittest')
3815 _, out, err = assert_python_failure('-m', 'inspect',
3816 'sys')
3817 lines = err.decode().splitlines()
3818 self.assertEqual(lines, ["Can't get info for builtin modules."])
3819
3820 def test_details(self):
3821 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003822 args = support.optim_args_from_interpreter_flags()
3823 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003824 'unittest', '--details')
3825 output = out.decode()
3826 # Just a quick sanity check on the output
3827 self.assertIn(module.__name__, output)
3828 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003829 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003830 self.assertEqual(err, b'')
3831
3832
Yury Selivanovef1e7502014-12-08 16:05:34 -05003833class TestReload(unittest.TestCase):
3834
3835 src_before = textwrap.dedent("""\
3836def foo():
3837 print("Bla")
3838 """)
3839
3840 src_after = textwrap.dedent("""\
3841def foo():
3842 print("Oh no!")
3843 """)
3844
3845 def assertInspectEqual(self, path, source):
3846 inspected_src = inspect.getsource(source)
3847 with open(path) as src:
3848 self.assertEqual(
3849 src.read().splitlines(True),
3850 inspected_src.splitlines(True)
3851 )
3852
3853 def test_getsource_reload(self):
3854 # see issue 1218234
3855 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3856 module = importlib.import_module(name)
3857 self.assertInspectEqual(path, module)
3858 with open(path, 'w') as src:
3859 src.write(self.src_after)
3860 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003861
Nick Coghlane8c45d62013-07-28 20:00:01 +10003862
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003863def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003864 run_unittest(
3865 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3866 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3867 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003868 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003869 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003870 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04003871 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003872 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
3873 TestGetCoroutineState
Michael Foord95fc51d2010-11-20 15:07:30 +00003874 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003875
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003876if __name__ == "__main__":
3877 test_main()