blob: e523dd40636ce00735f44ee56653ea0c06f49246 [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")
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700347 return "\n".join(lines[top-1:bottom]) + ("\n" if bottom else "")
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
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700530class TestGettingSourceOfToplevelFrames(GetSourceBase):
531 fodderModule = mod
532
533 def test_range_toplevel_frame(self):
534 self.maxDiff = None
535 self.assertSourceEqual(mod.currentframe, 1, None)
536
537 def test_range_traceback_toplevel_frame(self):
538 self.assertSourceEqual(mod.tb, 1, None)
539
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000540class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000541 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000542
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000543 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000544 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000545
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000546 def test_replacing_decorator(self):
547 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000548
Yury Selivanov081bbf62014-09-26 17:34:54 -0400549 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200550 self.assertSourceEqual(mod2.real, 130, 132)
551
552 def test_decorator_with_lambda(self):
553 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400554
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000555class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000556 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000557 def test_oneline_lambda(self):
558 # Test inspect.getsource with a one-line lambda function.
559 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000560
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000561 def test_threeline_lambda(self):
562 # Test inspect.getsource with a three-line lambda function,
563 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000564 self.assertSourceEqual(mod2.tll, 28, 30)
565
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000566 def test_twoline_indented_lambda(self):
567 # Test inspect.getsource with a two-line lambda function,
568 # where the second line _is_ indented.
569 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000570
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000571 def test_onelinefunc(self):
572 # Test inspect.getsource with a regular one-line function.
573 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000574
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000575 def test_manyargs(self):
576 # Test inspect.getsource with a regular function where
577 # the arguments are on two lines and _not_ indented and
578 # the body on the second line with the last arguments.
579 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000580
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000581 def test_twolinefunc(self):
582 # Test inspect.getsource with a regular function where
583 # the body is on two lines, following the argument list and
584 # continued on the next line by a \\.
585 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000586
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000587 def test_lambda_in_list(self):
588 # Test inspect.getsource with a one-line lambda function
589 # defined in a list, indented.
590 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000591
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000592 def test_anonymous(self):
593 # Test inspect.getsource with a lambda function defined
594 # as argument to another function.
595 self.assertSourceEqual(mod2.anonymous, 55, 55)
596
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000597class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000598 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000599
600 def test_with_comment(self):
601 self.assertSourceEqual(mod2.with_comment, 58, 59)
602
603 def test_multiline_sig(self):
604 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
605
Armin Rigodd5c0232005-09-25 11:45:45 +0000606 def test_nested_class(self):
607 self.assertSourceEqual(mod2.func69().func71, 71, 72)
608
609 def test_one_liner_followed_by_non_name(self):
610 self.assertSourceEqual(mod2.func77, 77, 77)
611
612 def test_one_liner_dedent_non_name(self):
613 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
614
615 def test_with_comment_instead_of_docstring(self):
616 self.assertSourceEqual(mod2.func88, 88, 90)
617
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000618 def test_method_in_dynamic_class(self):
619 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
620
R David Murray32562d72014-10-03 11:15:38 -0400621 # This should not skip for CPython, but might on a repackaged python where
622 # unicodedata is not an external module, or on pypy.
623 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
624 unicodedata.__file__.endswith('.py'),
625 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000626 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200627 self.assertRaises(OSError, inspect.getsource, unicodedata)
628 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000629
R. David Murraya1b37402010-06-17 02:04:29 +0000630 def test_findsource_code_in_linecache(self):
631 lines = ["x=1"]
632 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200633 self.assertRaises(OSError, inspect.findsource, co)
634 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000635 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200636 try:
637 self.assertEqual(inspect.findsource(co), (lines,0))
638 self.assertEqual(inspect.getsource(co), lines[0])
639 finally:
640 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000641
Ezio Melotti1b145922013-03-30 05:17:24 +0200642 def test_findsource_without_filename(self):
643 for fname in ['', '<string>']:
644 co = compile('x=1', fname, "exec")
645 self.assertRaises(IOError, inspect.findsource, co)
646 self.assertRaises(IOError, inspect.getsource, co)
647
Antoine Pitroua8723a02015-04-15 00:41:29 +0200648 def test_getsource_on_method(self):
649 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
650
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300651 def test_nested_func(self):
652 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
653
654
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000655class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400656 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000657 self.tempdir = TESTFN + '_dir'
658 os.mkdir(self.tempdir)
659 with open(os.path.join(self.tempdir,
660 'inspect_fodder3%spy' % os.extsep), 'w') as f:
661 f.write("class X:\n pass # No EOL")
662 with DirsOnSysPath(self.tempdir):
663 import inspect_fodder3 as mod3
664 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400665 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000666
667 def tearDown(self):
668 shutil.rmtree(self.tempdir)
669
670 def test_class(self):
671 self.assertSourceEqual(self.fodderModule.X, 1, 2)
672
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100673
674class _BrokenDataDescriptor(object):
675 """
676 A broken data descriptor. See bug #1785.
677 """
678 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700679 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100680
681 def __set__(*args):
682 raise RuntimeError
683
684 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700685 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100686
687
688class _BrokenMethodDescriptor(object):
689 """
690 A broken method descriptor. See bug #1785.
691 """
692 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700693 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100694
695 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700696 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100697
698
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000699# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000700def attrs_wo_objs(cls):
701 return [t[:3] for t in inspect.classify_class_attrs(cls)]
702
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100703
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000704class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000705 def test_newstyle_mro(self):
706 # The same w/ new-class MRO.
707 class A(object): pass
708 class B(A): pass
709 class C(A): pass
710 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000711
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000712 expected = (D, B, C, A, object)
713 got = inspect.getmro(D)
714 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000715
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500716 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
717 varkw_e=None, defaults_e=None, formatted=None):
718 with self.assertWarns(DeprecationWarning):
719 args, varargs, varkw, defaults = inspect.getargspec(routine)
720 self.assertEqual(args, args_e)
721 self.assertEqual(varargs, varargs_e)
722 self.assertEqual(varkw, varkw_e)
723 self.assertEqual(defaults, defaults_e)
724 if formatted is not None:
Matthias Bussonnier46c5cd02018-06-11 22:08:16 +0200725 with self.assertWarns(DeprecationWarning):
726 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
727 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500728
Christian Heimes3795b532007-11-08 13:48:53 +0000729 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
730 varkw_e=None, defaults_e=None,
731 kwonlyargs_e=[], kwonlydefaults_e=None,
732 ann_e={}, formatted=None):
733 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
734 inspect.getfullargspec(routine)
735 self.assertEqual(args, args_e)
736 self.assertEqual(varargs, varargs_e)
737 self.assertEqual(varkw, varkw_e)
738 self.assertEqual(defaults, defaults_e)
739 self.assertEqual(kwonlyargs, kwonlyargs_e)
740 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
741 self.assertEqual(ann, ann_e)
742 if formatted is not None:
Matthias Bussonnier46c5cd02018-06-11 22:08:16 +0200743 with self.assertWarns(DeprecationWarning):
744 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
745 kwonlyargs, kwonlydefaults, ann),
Christian Heimes3795b532007-11-08 13:48:53 +0000746 formatted)
747
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500748 def test_getargspec(self):
749 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
750
751 self.assertArgSpecEquals(mod.spam,
752 ['a', 'b', 'c', 'd', 'e', 'f'],
753 'g', 'h', (3, 4, 5),
754 '(a, b, c, d=3, e=4, f=5, *g, **h)')
755
756 self.assertRaises(ValueError, self.assertArgSpecEquals,
757 mod2.keyworded, [])
758
759 self.assertRaises(ValueError, self.assertArgSpecEquals,
760 mod2.annotated, [])
761 self.assertRaises(ValueError, self.assertArgSpecEquals,
762 mod2.keyword_only_arg, [])
763
764
Christian Heimes3795b532007-11-08 13:48:53 +0000765 def test_getfullargspec(self):
766 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
767 kwonlyargs_e=['arg2'],
768 kwonlydefaults_e={'arg2':1},
769 formatted='(*arg1, arg2=1)')
770
771 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000772 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000773 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000774 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
775 kwonlyargs_e=['arg'],
776 formatted='(*, arg)')
777
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500778 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500779 # Issue 20684: low level introspection API must ignore __wrapped__
780 @functools.wraps(mod.spam)
781 def ham(x, y):
782 pass
783 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500784 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500785 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
786 self.assertFullArgSpecEquals(functools.partial(ham),
787 ['x', 'y'], formatted='(x, y)')
788 # Other variants
789 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500790 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
791 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500792 class C:
793 @functools.wraps(mod.spam)
794 def ham(self, x, y):
795 pass
796 pham = functools.partialmethod(ham)
797 @functools.wraps(mod.spam)
798 def __call__(self, x, y):
799 pass
800 check_method(C())
801 check_method(C.ham)
802 check_method(C().ham)
803 check_method(C.pham)
804 check_method(C().pham)
805
806 class C_new:
807 @functools.wraps(mod.spam)
808 def __new__(self, x, y):
809 pass
810 check_method(C_new)
811
812 class C_init:
813 @functools.wraps(mod.spam)
814 def __init__(self, x, y):
815 pass
816 check_method(C_init)
817
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500818 def test_getfullargspec_signature_attr(self):
819 def test():
820 pass
821 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
822 test.__signature__ = inspect.Signature(parameters=(spam_param,))
823
824 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
825
Yury Selivanov4cb93912014-01-29 11:54:12 -0500826 def test_getfullargspec_signature_annos(self):
827 def test(a:'spam') -> 'ham': pass
828 spec = inspect.getfullargspec(test)
829 self.assertEqual(test.__annotations__, spec.annotations)
830
831 def test(): pass
832 spec = inspect.getfullargspec(test)
833 self.assertEqual(test.__annotations__, spec.annotations)
834
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500835 @unittest.skipIf(MISSING_C_DOCSTRINGS,
836 "Signature information for builtins requires docstrings")
837 def test_getfullargspec_builtin_methods(self):
838 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
839 args_e=['self', 'obj'], formatted='(self, obj)')
840
841 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
842 args_e=['self', 'obj'], formatted='(self, obj)')
843
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500844 self.assertFullArgSpecEquals(
845 os.stat,
846 args_e=['path'],
847 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
848 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
849 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
850
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200851 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500852 @unittest.skipIf(MISSING_C_DOCSTRINGS,
853 "Signature information for builtins requires docstrings")
854 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200855 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500856 builtin = _testcapi.docstring_with_signature_with_defaults
857 spec = inspect.getfullargspec(builtin)
858 self.assertEqual(spec.defaults[0], 'avocado')
859
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200860 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500861 @unittest.skipIf(MISSING_C_DOCSTRINGS,
862 "Signature information for builtins requires docstrings")
863 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200864 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500865 builtin = _testcapi.docstring_no_signature
866 with self.assertRaises(TypeError):
867 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000868
larryhastingsf36ba122018-01-28 11:13:09 -0800869 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
870 for fn in signatures_with_lexicographic_keyword_only_parameters():
871 signature = inspect.getfullargspec(fn)
872 l = list(signature.kwonlyargs)
873 sorted_l = sorted(l)
874 self.assertTrue(l)
875 self.assertEqual(l, sorted_l)
876 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
877 l = list(signature.kwonlyargs)
878 self.assertEqual(l, unsorted_keyword_only_parameters)
879
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500880 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000881 class A(object):
882 def m(self):
883 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500884 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000885
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000886 def test_classify_newstyle(self):
887 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000888
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000889 def s(): pass
890 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000891
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000892 def c(cls): pass
893 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000894
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000895 def getp(self): pass
896 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000897
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000898 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000899
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000900 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000901
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000902 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000903
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100904 dd = _BrokenDataDescriptor()
905 md = _BrokenMethodDescriptor()
906
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000907 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500908
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +0200909 self.assertIn(('__new__', 'static method', object), attrs,
910 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500911 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
912
Benjamin Peterson577473f2010-01-19 00:09:57 +0000913 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
914 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
915 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000916 self.assertIn(('m', 'method', A), attrs,
917 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000918 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
919 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100920 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
921 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000922
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000923 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000924
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000925 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000926
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000927 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000928 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
929 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
930 self.assertIn(('p', 'property', A), attrs, 'missing property')
931 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
932 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
933 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100934 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
935 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000936
937
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000938 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000939
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000940 def m(self): pass
941 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000942
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000943 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000944 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
945 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
946 self.assertIn(('p', 'property', A), attrs, 'missing property')
947 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
948 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
949 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100950 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
951 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000952
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000953 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000954
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000955 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000956
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000957 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000958 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
959 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
960 self.assertIn(('p', 'property', A), attrs, 'missing property')
961 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
962 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
963 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100964 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
965 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
966
967 def test_classify_builtin_types(self):
968 # Simple sanity check that all built-in types can have their
969 # attributes classified.
970 for name in dir(__builtins__):
971 builtin = getattr(__builtins__, name)
972 if isinstance(builtin, type):
973 inspect.classify_class_attrs(builtin)
974
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +0200975 attrs = attrs_wo_objs(bool)
976 self.assertIn(('__new__', 'static method', bool), attrs,
977 'missing __new__')
978 self.assertIn(('from_bytes', 'class method', int), attrs,
979 'missing class method')
980 self.assertIn(('to_bytes', 'method', int), attrs,
981 'missing plain method')
982 self.assertIn(('__add__', 'method', int), attrs,
983 'missing plain method')
984 self.assertIn(('__and__', 'method', bool), attrs,
985 'missing plain method')
986
Ethan Furman63c141c2013-10-18 00:27:39 -0700987 def test_classify_DynamicClassAttribute(self):
988 class Meta(type):
989 def __getattr__(self, name):
990 if name == 'ham':
991 return 'spam'
992 return super().__getattr__(name)
993 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700994 @types.DynamicClassAttribute
995 def ham(self):
996 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700997 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
998 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700999 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001000 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1001
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001002 def test_classify_overrides_bool(self):
1003 class NoBool(object):
1004 def __eq__(self, other):
1005 return NoBool()
1006
1007 def __bool__(self):
1008 raise NotImplementedError(
1009 "This object does not specify a boolean value")
1010
1011 class HasNB(object):
1012 dd = NoBool()
1013
1014 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1015 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1016
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001017 def test_classify_metaclass_class_attribute(self):
1018 class Meta(type):
1019 fish = 'slap'
1020 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001021 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001022 class Class(metaclass=Meta):
1023 pass
1024 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1025 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1026
Ethan Furman63c141c2013-10-18 00:27:39 -07001027 def test_classify_VirtualAttribute(self):
1028 class Meta(type):
1029 def __dir__(cls):
1030 return ['__class__', '__module__', '__name__', 'BOOM']
1031 def __getattr__(self, name):
1032 if name =='BOOM':
1033 return 42
1034 return super().__getattr(name)
1035 class Class(metaclass=Meta):
1036 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001037 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001038 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1039
1040 def test_classify_VirtualAttribute_multi_classes(self):
1041 class Meta1(type):
1042 def __dir__(cls):
1043 return ['__class__', '__module__', '__name__', 'one']
1044 def __getattr__(self, name):
1045 if name =='one':
1046 return 1
1047 return super().__getattr__(name)
1048 class Meta2(type):
1049 def __dir__(cls):
1050 return ['__class__', '__module__', '__name__', 'two']
1051 def __getattr__(self, name):
1052 if name =='two':
1053 return 2
1054 return super().__getattr__(name)
1055 class Meta3(Meta1, Meta2):
1056 def __dir__(cls):
1057 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1058 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1059 def __getattr__(self, name):
1060 if name =='three':
1061 return 3
1062 return super().__getattr__(name)
1063 class Class1(metaclass=Meta1):
1064 pass
1065 class Class2(Class1, metaclass=Meta3):
1066 pass
1067
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001068 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1069 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1070 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001071 cca = inspect.classify_class_attrs(Class2)
1072 for sf in (should_find1, should_find2, should_find3):
1073 self.assertIn(sf, cca)
1074
1075 def test_classify_class_attrs_with_buggy_dir(self):
1076 class M(type):
1077 def __dir__(cls):
1078 return ['__class__', '__name__', 'missing']
1079 class C(metaclass=M):
1080 pass
1081 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1082 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001083
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001084 def test_getmembers_descriptors(self):
1085 class A(object):
1086 dd = _BrokenDataDescriptor()
1087 md = _BrokenMethodDescriptor()
1088
1089 def pred_wrapper(pred):
1090 # A quick'n'dirty way to discard standard attributes of new-style
1091 # classes.
1092 class Empty(object):
1093 pass
1094 def wrapped(x):
1095 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1096 return False
1097 return pred(x)
1098 return wrapped
1099
1100 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1101 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1102
1103 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1104 [('md', A.__dict__['md'])])
1105 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1106 [('dd', A.__dict__['dd'])])
1107
1108 class B(A):
1109 pass
1110
1111 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1112 [('md', A.__dict__['md'])])
1113 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1114 [('dd', A.__dict__['dd'])])
1115
Antoine Pitrou0c603812012-01-18 17:40:18 +01001116 def test_getmembers_method(self):
1117 class B:
1118 def f(self):
1119 pass
1120
1121 self.assertIn(('f', B.f), inspect.getmembers(B))
1122 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1123 b = B()
1124 self.assertIn(('f', b.f), inspect.getmembers(b))
1125 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1126
Ethan Furmane03ea372013-09-25 07:14:41 -07001127 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001128 class M(type):
1129 def __getattr__(cls, name):
1130 if name == 'eggs':
1131 return 'scrambled'
1132 return super().__getattr__(name)
1133 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001134 @types.DynamicClassAttribute
1135 def eggs(self):
1136 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001137 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1138 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1139
1140 def test_getmembers_with_buggy_dir(self):
1141 class M(type):
1142 def __dir__(cls):
1143 return ['__class__', '__name__', 'missing']
1144 class C(metaclass=M):
1145 pass
1146 attrs = [a[0] for a in inspect.getmembers(C)]
1147 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001148
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001149class TestIsDataDescriptor(unittest.TestCase):
1150
1151 def test_custom_descriptors(self):
1152 class NonDataDescriptor:
1153 def __get__(self, value, type=None): pass
1154 class DataDescriptor0:
1155 def __set__(self, name, value): pass
1156 class DataDescriptor1:
1157 def __delete__(self, name): pass
1158 class DataDescriptor2:
1159 __set__ = None
1160 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1161 'class with only __get__ not a data descriptor')
1162 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1163 'class with __set__ is a data descriptor')
1164 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1165 'class with __delete__ is a data descriptor')
1166 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1167 'class with __set__ = None is a data descriptor')
1168
1169 def test_slot(self):
1170 class Slotted:
1171 __slots__ = 'foo',
1172 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1173 'a slot is a data descriptor')
1174
1175 def test_property(self):
1176 class Propertied:
1177 @property
1178 def a_property(self):
1179 pass
1180 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1181 'a property is a data descriptor')
1182
1183 def test_functions(self):
1184 class Test(object):
1185 def instance_method(self): pass
1186 @classmethod
1187 def class_method(cls): pass
1188 @staticmethod
1189 def static_method(): pass
1190 def function():
1191 pass
1192 a_lambda = lambda: None
1193 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1194 'a instance method is not a data descriptor')
1195 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1196 'a class method is not a data descriptor')
1197 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1198 'a static method is not a data descriptor')
1199 self.assertFalse(inspect.isdatadescriptor(function),
1200 'a function is not a data descriptor')
1201 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1202 'a lambda is not a data descriptor')
1203
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001204
Nick Coghlan2f92e542012-06-23 19:39:55 +10001205_global_ref = object()
1206class TestGetClosureVars(unittest.TestCase):
1207
1208 def test_name_resolution(self):
1209 # Basic test of the 4 different resolution mechanisms
1210 def f(nonlocal_ref):
1211 def g(local_ref):
1212 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1213 return g
1214 _arg = object()
1215 nonlocal_vars = {"nonlocal_ref": _arg}
1216 global_vars = {"_global_ref": _global_ref}
1217 builtin_vars = {"print": print}
1218 unbound_names = {"unbound_ref"}
1219 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1220 builtin_vars, unbound_names)
1221 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1222
1223 def test_generator_closure(self):
1224 def f(nonlocal_ref):
1225 def g(local_ref):
1226 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1227 yield
1228 return g
1229 _arg = object()
1230 nonlocal_vars = {"nonlocal_ref": _arg}
1231 global_vars = {"_global_ref": _global_ref}
1232 builtin_vars = {"print": print}
1233 unbound_names = {"unbound_ref"}
1234 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1235 builtin_vars, unbound_names)
1236 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1237
1238 def test_method_closure(self):
1239 class C:
1240 def f(self, nonlocal_ref):
1241 def g(local_ref):
1242 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1243 return g
1244 _arg = object()
1245 nonlocal_vars = {"nonlocal_ref": _arg}
1246 global_vars = {"_global_ref": _global_ref}
1247 builtin_vars = {"print": print}
1248 unbound_names = {"unbound_ref"}
1249 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1250 builtin_vars, unbound_names)
1251 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1252
1253 def test_nonlocal_vars(self):
1254 # More complex tests of nonlocal resolution
1255 def _nonlocal_vars(f):
1256 return inspect.getclosurevars(f).nonlocals
1257
1258 def make_adder(x):
1259 def add(y):
1260 return x + y
1261 return add
1262
1263 def curry(func, arg1):
1264 return lambda arg2: func(arg1, arg2)
1265
1266 def less_than(a, b):
1267 return a < b
1268
1269 # The infamous Y combinator.
1270 def Y(le):
1271 def g(f):
1272 return le(lambda x: f(f)(x))
1273 Y.g_ref = g
1274 return g(g)
1275
1276 def check_y_combinator(func):
1277 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1278
1279 inc = make_adder(1)
1280 add_two = make_adder(2)
1281 greater_than_five = curry(less_than, 5)
1282
1283 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1284 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1285 self.assertEqual(_nonlocal_vars(greater_than_five),
1286 {'arg1': 5, 'func': less_than})
1287 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1288 {'x': 3})
1289 Y(check_y_combinator)
1290
1291 def test_getclosurevars_empty(self):
1292 def foo(): pass
1293 _empty = inspect.ClosureVars({}, {}, {}, set())
1294 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1295 self.assertEqual(inspect.getclosurevars(foo), _empty)
1296
1297 def test_getclosurevars_error(self):
1298 class T: pass
1299 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1300 self.assertRaises(TypeError, inspect.getclosurevars, list)
1301 self.assertRaises(TypeError, inspect.getclosurevars, {})
1302
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001303 def _private_globals(self):
1304 code = """def f(): print(path)"""
1305 ns = {}
1306 exec(code, ns)
1307 return ns["f"], ns
1308
1309 def test_builtins_fallback(self):
1310 f, ns = self._private_globals()
1311 ns.pop("__builtins__", None)
1312 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1313 self.assertEqual(inspect.getclosurevars(f), expected)
1314
1315 def test_builtins_as_dict(self):
1316 f, ns = self._private_globals()
1317 ns["__builtins__"] = {"path":1}
1318 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1319 self.assertEqual(inspect.getclosurevars(f), expected)
1320
1321 def test_builtins_as_module(self):
1322 f, ns = self._private_globals()
1323 ns["__builtins__"] = os
1324 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1325 self.assertEqual(inspect.getclosurevars(f), expected)
1326
Nick Coghlan2f92e542012-06-23 19:39:55 +10001327
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001328class TestGetcallargsFunctions(unittest.TestCase):
1329
1330 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1331 locs = dict(locs or {}, func=func)
1332 r1 = eval('func(%s)' % call_params_string, None, locs)
1333 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1334 locs)
1335 self.assertEqual(r1, r2)
1336
1337 def assertEqualException(self, func, call_param_string, locs=None):
1338 locs = dict(locs or {}, func=func)
1339 try:
1340 eval('func(%s)' % call_param_string, None, locs)
1341 except Exception as e:
1342 ex1 = e
1343 else:
1344 self.fail('Exception not raised')
1345 try:
1346 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1347 locs)
1348 except Exception as e:
1349 ex2 = e
1350 else:
1351 self.fail('Exception not raised')
1352 self.assertIs(type(ex1), type(ex2))
1353 self.assertEqual(str(ex1), str(ex2))
1354 del ex1, ex2
1355
1356 def makeCallable(self, signature):
1357 """Create a function that returns its locals()"""
1358 code = "lambda %s: locals()"
1359 return eval(code % signature)
1360
1361 def test_plain(self):
1362 f = self.makeCallable('a, b=1')
1363 self.assertEqualCallArgs(f, '2')
1364 self.assertEqualCallArgs(f, '2, 3')
1365 self.assertEqualCallArgs(f, 'a=2')
1366 self.assertEqualCallArgs(f, 'b=3, a=2')
1367 self.assertEqualCallArgs(f, '2, b=3')
1368 # expand *iterable / **mapping
1369 self.assertEqualCallArgs(f, '*(2,)')
1370 self.assertEqualCallArgs(f, '*[2]')
1371 self.assertEqualCallArgs(f, '*(2, 3)')
1372 self.assertEqualCallArgs(f, '*[2, 3]')
1373 self.assertEqualCallArgs(f, '**{"a":2}')
1374 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1375 self.assertEqualCallArgs(f, '2, **{"b":3}')
1376 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1377 # expand UserList / UserDict
1378 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1379 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1380 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1381 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1382 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1383
1384 def test_varargs(self):
1385 f = self.makeCallable('a, b=1, *c')
1386 self.assertEqualCallArgs(f, '2')
1387 self.assertEqualCallArgs(f, '2, 3')
1388 self.assertEqualCallArgs(f, '2, 3, 4')
1389 self.assertEqualCallArgs(f, '*(2,3,4)')
1390 self.assertEqualCallArgs(f, '2, *[3,4]')
1391 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1392
1393 def test_varkw(self):
1394 f = self.makeCallable('a, b=1, **c')
1395 self.assertEqualCallArgs(f, 'a=2')
1396 self.assertEqualCallArgs(f, '2, b=3, c=4')
1397 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1398 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1399 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1400 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1401 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1402 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1403 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1404
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001405 def test_varkw_only(self):
1406 # issue11256:
1407 f = self.makeCallable('**c')
1408 self.assertEqualCallArgs(f, '')
1409 self.assertEqualCallArgs(f, 'a=1')
1410 self.assertEqualCallArgs(f, 'a=1, b=2')
1411 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1412 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1413 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1414
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001415 def test_keyword_only(self):
1416 f = self.makeCallable('a=3, *, c, d=2')
1417 self.assertEqualCallArgs(f, 'c=3')
1418 self.assertEqualCallArgs(f, 'c=3, a=3')
1419 self.assertEqualCallArgs(f, 'a=2, c=4')
1420 self.assertEqualCallArgs(f, '4, c=4')
1421 self.assertEqualException(f, '')
1422 self.assertEqualException(f, '3')
1423 self.assertEqualException(f, 'a=3')
1424 self.assertEqualException(f, 'd=4')
1425
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001426 f = self.makeCallable('*, c, d=2')
1427 self.assertEqualCallArgs(f, 'c=3')
1428 self.assertEqualCallArgs(f, 'c=3, d=4')
1429 self.assertEqualCallArgs(f, 'd=4, c=3')
1430
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001431 def test_multiple_features(self):
1432 f = self.makeCallable('a, b=2, *f, **g')
1433 self.assertEqualCallArgs(f, '2, 3, 7')
1434 self.assertEqualCallArgs(f, '2, 3, x=8')
1435 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1436 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1437 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1438 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1439 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1440 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1441 '(4,[5,6])]), **collections.UserDict('
1442 'y=9, z=10)')
1443
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001444 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1445 self.assertEqualCallArgs(f, '2, 3, x=8')
1446 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1447 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1448 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1449 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1450 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1451 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1452 '(4,[5,6])]), q=0, **collections.UserDict('
1453 'y=9, z=10)')
1454
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001455 def test_errors(self):
1456 f0 = self.makeCallable('')
1457 f1 = self.makeCallable('a, b')
1458 f2 = self.makeCallable('a, b=1')
1459 # f0 takes no arguments
1460 self.assertEqualException(f0, '1')
1461 self.assertEqualException(f0, 'x=1')
1462 self.assertEqualException(f0, '1,x=1')
1463 # f1 takes exactly 2 arguments
1464 self.assertEqualException(f1, '')
1465 self.assertEqualException(f1, '1')
1466 self.assertEqualException(f1, 'a=2')
1467 self.assertEqualException(f1, 'b=3')
1468 # f2 takes at least 1 argument
1469 self.assertEqualException(f2, '')
1470 self.assertEqualException(f2, 'b=3')
1471 for f in f1, f2:
1472 # f1/f2 takes exactly/at most 2 arguments
1473 self.assertEqualException(f, '2, 3, 4')
1474 self.assertEqualException(f, '1, 2, 3, a=1')
1475 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001476 # XXX: success of this one depends on dict order
1477 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001478 # f got an unexpected keyword argument
1479 self.assertEqualException(f, 'c=2')
1480 self.assertEqualException(f, '2, c=3')
1481 self.assertEqualException(f, '2, 3, c=4')
1482 self.assertEqualException(f, '2, c=4, b=3')
1483 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1484 # f got multiple values for keyword argument
1485 self.assertEqualException(f, '1, a=2')
1486 self.assertEqualException(f, '1, **{"a":2}')
1487 self.assertEqualException(f, '1, 2, b=3')
1488 # XXX: Python inconsistency
1489 # - for functions and bound methods: unexpected keyword 'c'
1490 # - for unbound methods: multiple values for keyword 'a'
1491 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001492 # issue11256:
1493 f3 = self.makeCallable('**c')
1494 self.assertEqualException(f3, '1, 2')
1495 self.assertEqualException(f3, '1, 2, a=1, b=2')
1496 f4 = self.makeCallable('*, a, b=0')
1497 self.assertEqualException(f3, '1, 2')
1498 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001499
Yury Selivanov875df202014-03-27 18:23:03 -04001500 # issue #20816: getcallargs() fails to iterate over non-existent
1501 # kwonlydefaults and raises a wrong TypeError
1502 def f5(*, a): pass
1503 with self.assertRaisesRegex(TypeError,
1504 'missing 1 required keyword-only'):
1505 inspect.getcallargs(f5)
1506
1507
Yury Selivanovdccfa132014-03-27 18:42:52 -04001508 # issue20817:
1509 def f6(a, b, c):
1510 pass
1511 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1512 inspect.getcallargs(f6)
1513
Dong-hee Naa9cab432018-05-30 00:04:08 +09001514 # bpo-33197
1515 with self.assertRaisesRegex(ValueError,
1516 'variadic keyword parameters cannot'
1517 ' have default values'):
1518 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1519 default=42)
1520 with self.assertRaisesRegex(ValueError,
1521 "value 5 is not a valid Parameter.kind"):
1522 inspect.Parameter("bar", kind=5, default=42)
1523
1524 with self.assertRaisesRegex(TypeError,
1525 'name must be a str, not a int'):
1526 inspect.Parameter(123, kind=4)
1527
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001528class TestGetcallargsMethods(TestGetcallargsFunctions):
1529
1530 def setUp(self):
1531 class Foo(object):
1532 pass
1533 self.cls = Foo
1534 self.inst = Foo()
1535
1536 def makeCallable(self, signature):
1537 assert 'self' not in signature
1538 mk = super(TestGetcallargsMethods, self).makeCallable
1539 self.cls.method = mk('self, ' + signature)
1540 return self.inst.method
1541
1542class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1543
1544 def makeCallable(self, signature):
1545 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1546 return self.cls.method
1547
1548 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1549 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1550 *self._getAssertEqualParams(func, call_params_string, locs))
1551
1552 def assertEqualException(self, func, call_params_string, locs=None):
1553 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1554 *self._getAssertEqualParams(func, call_params_string, locs))
1555
1556 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1557 assert 'inst' not in call_params_string
1558 locs = dict(locs or {}, inst=self.inst)
1559 return (func, 'inst,' + call_params_string, locs)
1560
Michael Foord95fc51d2010-11-20 15:07:30 +00001561
1562class TestGetattrStatic(unittest.TestCase):
1563
1564 def test_basic(self):
1565 class Thing(object):
1566 x = object()
1567
1568 thing = Thing()
1569 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1570 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1571 with self.assertRaises(AttributeError):
1572 inspect.getattr_static(thing, 'y')
1573
1574 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1575
1576 def test_inherited(self):
1577 class Thing(object):
1578 x = object()
1579 class OtherThing(Thing):
1580 pass
1581
1582 something = OtherThing()
1583 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1584
1585 def test_instance_attr(self):
1586 class Thing(object):
1587 x = 2
1588 def __init__(self, x):
1589 self.x = x
1590 thing = Thing(3)
1591 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1592 del thing.x
1593 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1594
1595 def test_property(self):
1596 class Thing(object):
1597 @property
1598 def x(self):
1599 raise AttributeError("I'm pretending not to exist")
1600 thing = Thing()
1601 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1602
Ezio Melotti75cbd732011-04-28 00:59:29 +03001603 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001604 class descriptor(object):
1605 def __get__(*_):
1606 raise AttributeError("I'm pretending not to exist")
1607 desc = descriptor()
1608 class Thing(object):
1609 x = desc
1610 thing = Thing()
1611 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1612
1613 def test_classAttribute(self):
1614 class Thing(object):
1615 x = object()
1616
1617 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1618
Ethan Furmane03ea372013-09-25 07:14:41 -07001619 def test_classVirtualAttribute(self):
1620 class Thing(object):
1621 @types.DynamicClassAttribute
1622 def x(self):
1623 return self._x
1624 _x = object()
1625
1626 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1627
Michael Foord95fc51d2010-11-20 15:07:30 +00001628 def test_inherited_classattribute(self):
1629 class Thing(object):
1630 x = object()
1631 class OtherThing(Thing):
1632 pass
1633
1634 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1635
1636 def test_slots(self):
1637 class Thing(object):
1638 y = 'bar'
1639 __slots__ = ['x']
1640 def __init__(self):
1641 self.x = 'foo'
1642 thing = Thing()
1643 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1644 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1645
1646 del thing.x
1647 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1648
1649 def test_metaclass(self):
1650 class meta(type):
1651 attr = 'foo'
1652 class Thing(object, metaclass=meta):
1653 pass
1654 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1655
1656 class sub(meta):
1657 pass
1658 class OtherThing(object, metaclass=sub):
1659 x = 3
1660 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1661
1662 class OtherOtherThing(OtherThing):
1663 pass
1664 # this test is odd, but it was added as it exposed a bug
1665 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1666
1667 def test_no_dict_no_slots(self):
1668 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1669 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1670
1671 def test_no_dict_no_slots_instance_member(self):
1672 # returns descriptor
1673 with open(__file__) as handle:
1674 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1675
1676 def test_inherited_slots(self):
1677 # returns descriptor
1678 class Thing(object):
1679 __slots__ = ['x']
1680 def __init__(self):
1681 self.x = 'foo'
1682
1683 class OtherThing(Thing):
1684 pass
1685 # it would be nice if this worked...
1686 # we get the descriptor instead of the instance attribute
1687 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1688
1689 def test_descriptor(self):
1690 class descriptor(object):
1691 def __get__(self, instance, owner):
1692 return 3
1693 class Foo(object):
1694 d = descriptor()
1695
1696 foo = Foo()
1697
1698 # for a non data descriptor we return the instance attribute
1699 foo.__dict__['d'] = 1
1700 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1701
Mike53f7a7c2017-12-14 14:04:53 +03001702 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001703 # descriptor
1704 descriptor.__set__ = lambda s, i, v: None
1705 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1706
1707
1708 def test_metaclass_with_descriptor(self):
1709 class descriptor(object):
1710 def __get__(self, instance, owner):
1711 return 3
1712 class meta(type):
1713 d = descriptor()
1714 class Thing(object, metaclass=meta):
1715 pass
1716 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1717
1718
Michael Foordcc7ebb82010-11-20 16:20:16 +00001719 def test_class_as_property(self):
1720 class Base(object):
1721 foo = 3
1722
1723 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001724 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001725 @property
1726 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001727 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001728 return object
1729
Michael Foord35184ed2010-11-20 16:58:30 +00001730 instance = Something()
1731 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1732 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001733 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1734
Michael Foorde5162652010-11-20 16:40:44 +00001735 def test_mro_as_property(self):
1736 class Meta(type):
1737 @property
1738 def __mro__(self):
1739 return (object,)
1740
1741 class Base(object):
1742 foo = 3
1743
1744 class Something(Base, metaclass=Meta):
1745 pass
1746
1747 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1748 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1749
Michael Foorddcebe0f2011-03-15 19:20:44 -04001750 def test_dict_as_property(self):
1751 test = self
1752 test.called = False
1753
1754 class Foo(dict):
1755 a = 3
1756 @property
1757 def __dict__(self):
1758 test.called = True
1759 return {}
1760
1761 foo = Foo()
1762 foo.a = 4
1763 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1764 self.assertFalse(test.called)
1765
1766 def test_custom_object_dict(self):
1767 test = self
1768 test.called = False
1769
1770 class Custom(dict):
1771 def get(self, key, default=None):
1772 test.called = True
1773 super().get(key, default)
1774
1775 class Foo(object):
1776 a = 3
1777 foo = Foo()
1778 foo.__dict__ = Custom()
1779 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1780 self.assertFalse(test.called)
1781
1782 def test_metaclass_dict_as_property(self):
1783 class Meta(type):
1784 @property
1785 def __dict__(self):
1786 self.executed = True
1787
1788 class Thing(metaclass=Meta):
1789 executed = False
1790
1791 def __init__(self):
1792 self.spam = 42
1793
1794 instance = Thing()
1795 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1796 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001797
Michael Foorda51623b2011-12-18 22:01:40 +00001798 def test_module(self):
1799 sentinel = object()
1800 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1801 sentinel)
1802
Michael Foord3ba95f82011-12-22 01:13:37 +00001803 def test_metaclass_with_metaclass_with_dict_as_property(self):
1804 class MetaMeta(type):
1805 @property
1806 def __dict__(self):
1807 self.executed = True
1808 return dict(spam=42)
1809
1810 class Meta(type, metaclass=MetaMeta):
1811 executed = False
1812
1813 class Thing(metaclass=Meta):
1814 pass
1815
1816 with self.assertRaises(AttributeError):
1817 inspect.getattr_static(Thing, "spam")
1818 self.assertFalse(Thing.executed)
1819
Nick Coghlane0f04652010-11-21 03:44:04 +00001820class TestGetGeneratorState(unittest.TestCase):
1821
1822 def setUp(self):
1823 def number_generator():
1824 for number in range(5):
1825 yield number
1826 self.generator = number_generator()
1827
1828 def _generatorstate(self):
1829 return inspect.getgeneratorstate(self.generator)
1830
1831 def test_created(self):
1832 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1833
1834 def test_suspended(self):
1835 next(self.generator)
1836 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1837
1838 def test_closed_after_exhaustion(self):
1839 for i in self.generator:
1840 pass
1841 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1842
1843 def test_closed_after_immediate_exception(self):
1844 with self.assertRaises(RuntimeError):
1845 self.generator.throw(RuntimeError)
1846 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1847
1848 def test_running(self):
1849 # As mentioned on issue #10220, checking for the RUNNING state only
1850 # makes sense inside the generator itself.
1851 # The following generator checks for this by using the closure's
1852 # reference to self and the generator state checking helper method
1853 def running_check_generator():
1854 for number in range(5):
1855 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1856 yield number
1857 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1858 self.generator = running_check_generator()
1859 # Running up to the first yield
1860 next(self.generator)
1861 # Running after the first yield
1862 next(self.generator)
1863
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001864 def test_easy_debugging(self):
1865 # repr() and str() of a generator state should contain the state name
1866 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1867 for name in names:
1868 state = getattr(inspect, name)
1869 self.assertIn(name, repr(state))
1870 self.assertIn(name, str(state))
1871
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001872 def test_getgeneratorlocals(self):
1873 def each(lst, a=None):
1874 b=(1, 2, 3)
1875 for v in lst:
1876 if v == 3:
1877 c = 12
1878 yield v
1879
1880 numbers = each([1, 2, 3])
1881 self.assertEqual(inspect.getgeneratorlocals(numbers),
1882 {'a': None, 'lst': [1, 2, 3]})
1883 next(numbers)
1884 self.assertEqual(inspect.getgeneratorlocals(numbers),
1885 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1886 'b': (1, 2, 3)})
1887 next(numbers)
1888 self.assertEqual(inspect.getgeneratorlocals(numbers),
1889 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1890 'b': (1, 2, 3)})
1891 next(numbers)
1892 self.assertEqual(inspect.getgeneratorlocals(numbers),
1893 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1894 'b': (1, 2, 3), 'c': 12})
1895 try:
1896 next(numbers)
1897 except StopIteration:
1898 pass
1899 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1900
1901 def test_getgeneratorlocals_empty(self):
1902 def yield_one():
1903 yield 1
1904 one = yield_one()
1905 self.assertEqual(inspect.getgeneratorlocals(one), {})
1906 try:
1907 next(one)
1908 except StopIteration:
1909 pass
1910 self.assertEqual(inspect.getgeneratorlocals(one), {})
1911
1912 def test_getgeneratorlocals_error(self):
1913 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1914 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1915 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1916 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1917
Nick Coghlane0f04652010-11-21 03:44:04 +00001918
Yury Selivanov5376ba92015-06-22 12:19:30 -04001919class TestGetCoroutineState(unittest.TestCase):
1920
1921 def setUp(self):
1922 @types.coroutine
1923 def number_coroutine():
1924 for number in range(5):
1925 yield number
1926 async def coroutine():
1927 await number_coroutine()
1928 self.coroutine = coroutine()
1929
1930 def tearDown(self):
1931 self.coroutine.close()
1932
1933 def _coroutinestate(self):
1934 return inspect.getcoroutinestate(self.coroutine)
1935
1936 def test_created(self):
1937 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1938
1939 def test_suspended(self):
1940 self.coroutine.send(None)
1941 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1942
1943 def test_closed_after_exhaustion(self):
1944 while True:
1945 try:
1946 self.coroutine.send(None)
1947 except StopIteration:
1948 break
1949
1950 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1951
1952 def test_closed_after_immediate_exception(self):
1953 with self.assertRaises(RuntimeError):
1954 self.coroutine.throw(RuntimeError)
1955 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1956
1957 def test_easy_debugging(self):
1958 # repr() and str() of a coroutine state should contain the state name
1959 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1960 for name in names:
1961 state = getattr(inspect, name)
1962 self.assertIn(name, repr(state))
1963 self.assertIn(name, str(state))
1964
1965 def test_getcoroutinelocals(self):
1966 @types.coroutine
1967 def gencoro():
1968 yield
1969
1970 gencoro = gencoro()
1971 async def func(a=None):
1972 b = 'spam'
1973 await gencoro
1974
1975 coro = func()
1976 self.assertEqual(inspect.getcoroutinelocals(coro),
1977 {'a': None, 'gencoro': gencoro})
1978 coro.send(None)
1979 self.assertEqual(inspect.getcoroutinelocals(coro),
1980 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
1981
1982
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001983class MySignature(inspect.Signature):
1984 # Top-level to make it picklable;
1985 # used in test_signature_object_pickle
1986 pass
1987
1988class MyParameter(inspect.Parameter):
1989 # Top-level to make it picklable;
1990 # used in test_signature_object_pickle
1991 pass
1992
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001993
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001994
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001995class TestSignatureObject(unittest.TestCase):
1996 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04001997 def signature(func, **kw):
1998 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001999 return (tuple((param.name,
2000 (... if param.default is param.empty else param.default),
2001 (... if param.annotation is param.empty
2002 else param.annotation),
2003 str(param.kind).lower())
2004 for param in sig.parameters.values()),
2005 (... if sig.return_annotation is sig.empty
2006 else sig.return_annotation))
2007
2008 def test_signature_object(self):
2009 S = inspect.Signature
2010 P = inspect.Parameter
2011
2012 self.assertEqual(str(S()), '()')
2013
Yury Selivanov07a9e452014-01-29 10:58:16 -05002014 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002015 pass
2016 sig = inspect.signature(test)
2017 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002018 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002019 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002020 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002021 args = sig.parameters['args']
2022 ko = sig.parameters['ko']
2023 kwargs = sig.parameters['kwargs']
2024
2025 S((po, pk, args, ko, kwargs))
2026
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002027 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002028 S((pk, po, args, ko, kwargs))
2029
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002030 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002031 S((po, args, pk, ko, kwargs))
2032
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002033 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002034 S((args, po, pk, ko, kwargs))
2035
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002036 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002037 S((po, pk, args, kwargs, ko))
2038
2039 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002040 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002041 S((po, pk, args, kwargs2, ko))
2042
Yury Selivanov07a9e452014-01-29 10:58:16 -05002043 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2044 S((pod, po))
2045
2046 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2047 S((po, pkd, pk))
2048
2049 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2050 S((pkd, pk))
2051
Yury Selivanov374375d2014-03-27 12:41:53 -04002052 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002053 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002054
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002055 def test_signature_object_pickle(self):
2056 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2057 foo_partial = functools.partial(foo, a=1)
2058
2059 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002060
2061 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2062 with self.subTest(pickle_ver=ver, subclass=False):
2063 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2064 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002065
2066 # Test that basic sub-classing works
2067 sig = inspect.signature(foo)
2068 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2069 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2070 mysig = MySignature().replace(parameters=myparams.values(),
2071 return_annotation=sig.return_annotation)
2072 self.assertTrue(isinstance(mysig, MySignature))
2073 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2074
2075 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2076 with self.subTest(pickle_ver=ver, subclass=True):
2077 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2078 self.assertEqual(mysig, sig_pickled)
2079 self.assertTrue(isinstance(sig_pickled, MySignature))
2080 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2081 MyParameter))
2082
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002083 def test_signature_immutability(self):
2084 def test(a):
2085 pass
2086 sig = inspect.signature(test)
2087
2088 with self.assertRaises(AttributeError):
2089 sig.foo = 'bar'
2090
2091 with self.assertRaises(TypeError):
2092 sig.parameters['a'] = None
2093
2094 def test_signature_on_noarg(self):
2095 def test():
2096 pass
2097 self.assertEqual(self.signature(test), ((), ...))
2098
2099 def test_signature_on_wargs(self):
2100 def test(a, b:'foo') -> 123:
2101 pass
2102 self.assertEqual(self.signature(test),
2103 ((('a', ..., ..., "positional_or_keyword"),
2104 ('b', ..., 'foo', "positional_or_keyword")),
2105 123))
2106
2107 def test_signature_on_wkwonly(self):
2108 def test(*, a:float, b:str) -> int:
2109 pass
2110 self.assertEqual(self.signature(test),
2111 ((('a', ..., float, "keyword_only"),
2112 ('b', ..., str, "keyword_only")),
2113 int))
2114
2115 def test_signature_on_complex_args(self):
2116 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2117 pass
2118 self.assertEqual(self.signature(test),
2119 ((('a', ..., ..., "positional_or_keyword"),
2120 ('b', 10, 'foo', "positional_or_keyword"),
2121 ('args', ..., 'bar', "var_positional"),
2122 ('spam', ..., 'baz', "keyword_only"),
2123 ('ham', 123, ..., "keyword_only"),
2124 ('kwargs', ..., int, "var_keyword")),
2125 ...))
2126
Dong-hee Na378d7062017-05-18 04:00:51 +09002127 def test_signature_without_self(self):
2128 def test_args_only(*args): # NOQA
2129 pass
2130
2131 def test_args_kwargs_only(*args, **kwargs): # NOQA
2132 pass
2133
2134 class A:
2135 @classmethod
2136 def test_classmethod(*args): # NOQA
2137 pass
2138
2139 @staticmethod
2140 def test_staticmethod(*args): # NOQA
2141 pass
2142
2143 f1 = functools.partialmethod((test_classmethod), 1)
2144 f2 = functools.partialmethod((test_args_only), 1)
2145 f3 = functools.partialmethod((test_staticmethod), 1)
2146 f4 = functools.partialmethod((test_args_kwargs_only),1)
2147
2148 self.assertEqual(self.signature(test_args_only),
2149 ((('args', ..., ..., 'var_positional'),), ...))
2150 self.assertEqual(self.signature(test_args_kwargs_only),
2151 ((('args', ..., ..., 'var_positional'),
2152 ('kwargs', ..., ..., 'var_keyword')), ...))
2153 self.assertEqual(self.signature(A.f1),
2154 ((('args', ..., ..., 'var_positional'),), ...))
2155 self.assertEqual(self.signature(A.f2),
2156 ((('args', ..., ..., 'var_positional'),), ...))
2157 self.assertEqual(self.signature(A.f3),
2158 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002159 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002160 ((('args', ..., ..., 'var_positional'),
2161 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002162 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002163 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2164 "Signature information for builtins requires docstrings")
2165 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002166 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002167
Larry Hastings5c661892014-01-24 06:17:25 -08002168 def test_unbound_method(o):
2169 """Use this to test unbound methods (things that should have a self)"""
2170 signature = inspect.signature(o)
2171 self.assertTrue(isinstance(signature, inspect.Signature))
2172 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2173 return signature
2174
2175 def test_callable(o):
2176 """Use this to test bound methods or normal callables (things that don't expect self)"""
2177 signature = inspect.signature(o)
2178 self.assertTrue(isinstance(signature, inspect.Signature))
2179 if signature.parameters:
2180 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2181 return signature
2182
2183 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002184 def p(name): return signature.parameters[name].default
2185 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002186 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002187 self.assertEqual(p('d'), 3.14)
2188 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002189 self.assertEqual(p('n'), None)
2190 self.assertEqual(p('t'), True)
2191 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002192 self.assertEqual(p('local'), 3)
2193 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002194 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002195
Larry Hastings5c661892014-01-24 06:17:25 -08002196 test_callable(object)
2197
2198 # normal method
2199 # (PyMethodDescr_Type, "method_descriptor")
2200 test_unbound_method(_pickle.Pickler.dump)
2201 d = _pickle.Pickler(io.StringIO())
2202 test_callable(d.dump)
2203
2204 # static method
2205 test_callable(str.maketrans)
2206 test_callable('abc'.maketrans)
2207
2208 # class method
2209 test_callable(dict.fromkeys)
2210 test_callable({}.fromkeys)
2211
2212 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2213 test_unbound_method(type.__call__)
2214 test_unbound_method(int.__add__)
2215 test_callable((3).__add__)
2216
2217 # _PyMethodWrapper_Type
2218 # support for 'method-wrapper'
2219 test_callable(min.__call__)
2220
Larry Hastings2623c8c2014-02-08 22:15:29 -08002221 # This doesn't work now.
2222 # (We don't have a valid signature for "type" in 3.4)
2223 with self.assertRaisesRegex(ValueError, "no signature found"):
2224 class ThisWorksNow:
2225 __call__ = type
2226 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002227
Yury Selivanov056e2652014-03-02 12:25:27 -05002228 # Regression test for issue #20786
2229 test_unbound_method(dict.__delitem__)
2230 test_unbound_method(property.__delete__)
2231
Zachary Ware8ef887c2015-04-13 18:22:35 -05002232 # Regression test for issue #20586
2233 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2234
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002235 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002236 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2237 "Signature information for builtins requires docstrings")
2238 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002239 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002240 func = _testcapi.docstring_with_signature_with_defaults
2241
2242 def decorator(func):
2243 @functools.wraps(func)
2244 def wrapper(*args, **kwargs) -> int:
2245 return func(*args, **kwargs)
2246 return wrapper
2247
2248 decorated_func = decorator(func)
2249
2250 self.assertEqual(inspect.signature(func),
2251 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002252
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002253 def wrapper_like(*args, **kwargs) -> int: pass
2254 self.assertEqual(inspect.signature(decorated_func,
2255 follow_wrapped=False),
2256 inspect.signature(wrapper_like))
2257
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002258 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002259 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002260 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002261 with self.assertRaisesRegex(ValueError,
2262 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002263 inspect.signature(_testcapi.docstring_no_signature)
2264
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002265 with self.assertRaisesRegex(ValueError,
2266 'no signature found for builtin'):
2267 inspect.signature(str)
2268
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002269 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002270 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002271 inspect.signature(42)
2272
Yury Selivanov63da7c72014-01-31 14:48:37 -05002273 def test_signature_from_functionlike_object(self):
2274 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2275 pass
2276
2277 class funclike:
2278 # Has to be callable, and have correct
2279 # __code__, __annotations__, __defaults__, __name__,
2280 # and __kwdefaults__ attributes
2281
2282 def __init__(self, func):
2283 self.__name__ = func.__name__
2284 self.__code__ = func.__code__
2285 self.__annotations__ = func.__annotations__
2286 self.__defaults__ = func.__defaults__
2287 self.__kwdefaults__ = func.__kwdefaults__
2288 self.func = func
2289
2290 def __call__(self, *args, **kwargs):
2291 return self.func(*args, **kwargs)
2292
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002293 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002294
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002295 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002296 self.assertEqual(sig_funclike, sig_func)
2297
2298 sig_funclike = inspect.signature(funclike(func))
2299 self.assertEqual(sig_funclike, sig_func)
2300
2301 # If object is not a duck type of function, then
2302 # signature will try to get a signature for its '__call__'
2303 # method
2304 fl = funclike(func)
2305 del fl.__defaults__
2306 self.assertEqual(self.signature(fl),
2307 ((('args', ..., ..., "var_positional"),
2308 ('kwargs', ..., ..., "var_keyword")),
2309 ...))
2310
Yury Selivanova773de02014-02-21 18:30:53 -05002311 # Test with cython-like builtins:
2312 _orig_isdesc = inspect.ismethoddescriptor
2313 def _isdesc(obj):
2314 if hasattr(obj, '_builtinmock'):
2315 return True
2316 return _orig_isdesc(obj)
2317
2318 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2319 builtin_func = funclike(func)
2320 # Make sure that our mock setup is working
2321 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2322 builtin_func._builtinmock = True
2323 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2324 self.assertEqual(inspect.signature(builtin_func), sig_func)
2325
Yury Selivanov63da7c72014-01-31 14:48:37 -05002326 def test_signature_functionlike_class(self):
2327 # We only want to duck type function-like objects,
2328 # not classes.
2329
2330 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2331 pass
2332
2333 class funclike:
2334 def __init__(self, marker):
2335 pass
2336
2337 __name__ = func.__name__
2338 __code__ = func.__code__
2339 __annotations__ = func.__annotations__
2340 __defaults__ = func.__defaults__
2341 __kwdefaults__ = func.__kwdefaults__
2342
Yury Selivanov63da7c72014-01-31 14:48:37 -05002343 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2344
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002345 def test_signature_on_method(self):
2346 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002347 def __init__(*args):
2348 pass
2349 def m1(self, arg1, arg2=1) -> int:
2350 pass
2351 def m2(*args):
2352 pass
2353 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002354 pass
2355
Yury Selivanov62560fb2014-01-28 12:26:24 -05002356 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002357 ((('arg1', ..., ..., "positional_or_keyword"),
2358 ('arg2', 1, ..., "positional_or_keyword")),
2359 int))
2360
Yury Selivanov62560fb2014-01-28 12:26:24 -05002361 self.assertEqual(self.signature(Test().m2),
2362 ((('args', ..., ..., "var_positional"),),
2363 ...))
2364
2365 self.assertEqual(self.signature(Test),
2366 ((('args', ..., ..., "var_positional"),),
2367 ...))
2368
2369 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2370 self.signature(Test())
2371
Yury Selivanov46c759d2015-05-27 21:56:53 -04002372 def test_signature_wrapped_bound_method(self):
2373 # Issue 24298
2374 class Test:
2375 def m1(self, arg1, arg2=1) -> int:
2376 pass
2377 @functools.wraps(Test().m1)
2378 def m1d(*args, **kwargs):
2379 pass
2380 self.assertEqual(self.signature(m1d),
2381 ((('arg1', ..., ..., "positional_or_keyword"),
2382 ('arg2', 1, ..., "positional_or_keyword")),
2383 int))
2384
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002385 def test_signature_on_classmethod(self):
2386 class Test:
2387 @classmethod
2388 def foo(cls, arg1, *, arg2=1):
2389 pass
2390
2391 meth = Test().foo
2392 self.assertEqual(self.signature(meth),
2393 ((('arg1', ..., ..., "positional_or_keyword"),
2394 ('arg2', 1, ..., "keyword_only")),
2395 ...))
2396
2397 meth = Test.foo
2398 self.assertEqual(self.signature(meth),
2399 ((('arg1', ..., ..., "positional_or_keyword"),
2400 ('arg2', 1, ..., "keyword_only")),
2401 ...))
2402
2403 def test_signature_on_staticmethod(self):
2404 class Test:
2405 @staticmethod
2406 def foo(cls, *, arg):
2407 pass
2408
2409 meth = Test().foo
2410 self.assertEqual(self.signature(meth),
2411 ((('cls', ..., ..., "positional_or_keyword"),
2412 ('arg', ..., ..., "keyword_only")),
2413 ...))
2414
2415 meth = Test.foo
2416 self.assertEqual(self.signature(meth),
2417 ((('cls', ..., ..., "positional_or_keyword"),
2418 ('arg', ..., ..., "keyword_only")),
2419 ...))
2420
2421 def test_signature_on_partial(self):
2422 from functools import partial
2423
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002424 Parameter = inspect.Parameter
2425
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002426 def test():
2427 pass
2428
2429 self.assertEqual(self.signature(partial(test)), ((), ...))
2430
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002431 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002432 inspect.signature(partial(test, 1))
2433
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002434 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002435 inspect.signature(partial(test, a=1))
2436
2437 def test(a, b, *, c, d):
2438 pass
2439
2440 self.assertEqual(self.signature(partial(test)),
2441 ((('a', ..., ..., "positional_or_keyword"),
2442 ('b', ..., ..., "positional_or_keyword"),
2443 ('c', ..., ..., "keyword_only"),
2444 ('d', ..., ..., "keyword_only")),
2445 ...))
2446
2447 self.assertEqual(self.signature(partial(test, 1)),
2448 ((('b', ..., ..., "positional_or_keyword"),
2449 ('c', ..., ..., "keyword_only"),
2450 ('d', ..., ..., "keyword_only")),
2451 ...))
2452
2453 self.assertEqual(self.signature(partial(test, 1, c=2)),
2454 ((('b', ..., ..., "positional_or_keyword"),
2455 ('c', 2, ..., "keyword_only"),
2456 ('d', ..., ..., "keyword_only")),
2457 ...))
2458
2459 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2460 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002461 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002462 ('c', 2, ..., "keyword_only"),
2463 ('d', ..., ..., "keyword_only")),
2464 ...))
2465
2466 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002467 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002468 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002469 ('d', ..., ..., "keyword_only")),
2470 ...))
2471
2472 self.assertEqual(self.signature(partial(test, a=1)),
2473 ((('a', 1, ..., "keyword_only"),
2474 ('b', ..., ..., "keyword_only"),
2475 ('c', ..., ..., "keyword_only"),
2476 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002477 ...))
2478
2479 def test(a, *args, b, **kwargs):
2480 pass
2481
2482 self.assertEqual(self.signature(partial(test, 1)),
2483 ((('args', ..., ..., "var_positional"),
2484 ('b', ..., ..., "keyword_only"),
2485 ('kwargs', ..., ..., "var_keyword")),
2486 ...))
2487
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002488 self.assertEqual(self.signature(partial(test, a=1)),
2489 ((('a', 1, ..., "keyword_only"),
2490 ('b', ..., ..., "keyword_only"),
2491 ('kwargs', ..., ..., "var_keyword")),
2492 ...))
2493
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002494 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2495 ((('args', ..., ..., "var_positional"),
2496 ('b', ..., ..., "keyword_only"),
2497 ('kwargs', ..., ..., "var_keyword")),
2498 ...))
2499
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002500 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2501 ((('args', ..., ..., "var_positional"),
2502 ('b', ..., ..., "keyword_only"),
2503 ('kwargs', ..., ..., "var_keyword")),
2504 ...))
2505
2506 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2507 ((('args', ..., ..., "var_positional"),
2508 ('b', 0, ..., "keyword_only"),
2509 ('kwargs', ..., ..., "var_keyword")),
2510 ...))
2511
2512 self.assertEqual(self.signature(partial(test, b=0)),
2513 ((('a', ..., ..., "positional_or_keyword"),
2514 ('args', ..., ..., "var_positional"),
2515 ('b', 0, ..., "keyword_only"),
2516 ('kwargs', ..., ..., "var_keyword")),
2517 ...))
2518
2519 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2520 ((('a', ..., ..., "positional_or_keyword"),
2521 ('args', ..., ..., "var_positional"),
2522 ('b', 0, ..., "keyword_only"),
2523 ('kwargs', ..., ..., "var_keyword")),
2524 ...))
2525
2526 def test(a, b, c:int) -> 42:
2527 pass
2528
2529 sig = test.__signature__ = inspect.signature(test)
2530
2531 self.assertEqual(self.signature(partial(partial(test, 1))),
2532 ((('b', ..., ..., "positional_or_keyword"),
2533 ('c', ..., int, "positional_or_keyword")),
2534 42))
2535
2536 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2537 ((('c', ..., int, "positional_or_keyword"),),
2538 42))
2539
2540 psig = inspect.signature(partial(partial(test, 1), 2))
2541
2542 def foo(a):
2543 return a
2544 _foo = partial(partial(foo, a=10), a=20)
2545 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002546 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002547 ...))
2548 # check that we don't have any side-effects in signature(),
2549 # and the partial object is still functioning
2550 self.assertEqual(_foo(), 20)
2551
2552 def foo(a, b, c):
2553 return a, b, c
2554 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002555
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002556 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002557 ((('b', 30, ..., "keyword_only"),
2558 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002559 ...))
2560 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002561
2562 def foo(a, b, c, *, d):
2563 return a, b, c, d
2564 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2565 self.assertEqual(self.signature(_foo),
2566 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002567 ('b', 10, ..., "keyword_only"),
2568 ('c', 20, ..., "keyword_only"),
2569 ('d', 30, ..., "keyword_only"),
2570 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002571 ...))
2572 ba = inspect.signature(_foo).bind(a=200, b=11)
2573 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2574
2575 def foo(a=1, b=2, c=3):
2576 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002577 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2578
2579 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002580 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002581
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002582 ba = inspect.signature(_foo).bind(11, 12)
2583 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002584
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002585 ba = inspect.signature(_foo).bind(11, b=12)
2586 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002587
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002588 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002589 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2590
2591 _foo = partial(_foo, b=10, c=20)
2592 ba = inspect.signature(_foo).bind(12)
2593 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2594
2595
2596 def foo(a, b, c, d, **kwargs):
2597 pass
2598 sig = inspect.signature(foo)
2599 params = sig.parameters.copy()
2600 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2601 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2602 foo.__signature__ = inspect.Signature(params.values())
2603 sig = inspect.signature(foo)
2604 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2605
2606 self.assertEqual(self.signature(partial(foo, 1)),
2607 ((('b', ..., ..., 'positional_only'),
2608 ('c', ..., ..., 'positional_or_keyword'),
2609 ('d', ..., ..., 'positional_or_keyword'),
2610 ('kwargs', ..., ..., 'var_keyword')),
2611 ...))
2612
2613 self.assertEqual(self.signature(partial(foo, 1, 2)),
2614 ((('c', ..., ..., 'positional_or_keyword'),
2615 ('d', ..., ..., 'positional_or_keyword'),
2616 ('kwargs', ..., ..., 'var_keyword')),
2617 ...))
2618
2619 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2620 ((('d', ..., ..., 'positional_or_keyword'),
2621 ('kwargs', ..., ..., 'var_keyword')),
2622 ...))
2623
2624 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2625 ((('c', 3, ..., 'keyword_only'),
2626 ('d', ..., ..., 'keyword_only'),
2627 ('kwargs', ..., ..., 'var_keyword')),
2628 ...))
2629
2630 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2631 ((('b', ..., ..., 'positional_only'),
2632 ('c', 3, ..., 'keyword_only'),
2633 ('d', ..., ..., 'keyword_only'),
2634 ('kwargs', ..., ..., 'var_keyword')),
2635 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002636
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002637 def test_signature_on_partialmethod(self):
2638 from functools import partialmethod
2639
2640 class Spam:
2641 def test():
2642 pass
2643 ham = partialmethod(test)
2644
2645 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2646 inspect.signature(Spam.ham)
2647
2648 class Spam:
2649 def test(it, a, *, c) -> 'spam':
2650 pass
2651 ham = partialmethod(test, c=1)
2652
2653 self.assertEqual(self.signature(Spam.ham),
2654 ((('it', ..., ..., 'positional_or_keyword'),
2655 ('a', ..., ..., 'positional_or_keyword'),
2656 ('c', 1, ..., 'keyword_only')),
2657 'spam'))
2658
2659 self.assertEqual(self.signature(Spam().ham),
2660 ((('a', ..., ..., 'positional_or_keyword'),
2661 ('c', 1, ..., 'keyword_only')),
2662 'spam'))
2663
Yury Selivanov8a387212018-03-06 12:59:45 -05002664 class Spam:
2665 def test(self: 'anno', x):
2666 pass
2667
2668 g = partialmethod(test, 1)
2669
2670 self.assertEqual(self.signature(Spam.g),
2671 ((('self', ..., 'anno', 'positional_or_keyword'),),
2672 ...))
2673
Yury Selivanov0486f812014-01-29 12:18:59 -05002674 def test_signature_on_fake_partialmethod(self):
2675 def foo(a): pass
2676 foo._partialmethod = 'spam'
2677 self.assertEqual(str(inspect.signature(foo)), '(a)')
2678
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002679 def test_signature_on_decorated(self):
2680 import functools
2681
2682 def decorator(func):
2683 @functools.wraps(func)
2684 def wrapper(*args, **kwargs) -> int:
2685 return func(*args, **kwargs)
2686 return wrapper
2687
2688 class Foo:
2689 @decorator
2690 def bar(self, a, b):
2691 pass
2692
2693 self.assertEqual(self.signature(Foo.bar),
2694 ((('self', ..., ..., "positional_or_keyword"),
2695 ('a', ..., ..., "positional_or_keyword"),
2696 ('b', ..., ..., "positional_or_keyword")),
2697 ...))
2698
2699 self.assertEqual(self.signature(Foo().bar),
2700 ((('a', ..., ..., "positional_or_keyword"),
2701 ('b', ..., ..., "positional_or_keyword")),
2702 ...))
2703
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002704 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2705 ((('args', ..., ..., "var_positional"),
2706 ('kwargs', ..., ..., "var_keyword")),
2707 ...)) # functools.wraps will copy __annotations__
2708 # from "func" to "wrapper", hence no
2709 # return_annotation
2710
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002711 # Test that we handle method wrappers correctly
2712 def decorator(func):
2713 @functools.wraps(func)
2714 def wrapper(*args, **kwargs) -> int:
2715 return func(42, *args, **kwargs)
2716 sig = inspect.signature(func)
2717 new_params = tuple(sig.parameters.values())[1:]
2718 wrapper.__signature__ = sig.replace(parameters=new_params)
2719 return wrapper
2720
2721 class Foo:
2722 @decorator
2723 def __call__(self, a, b):
2724 pass
2725
2726 self.assertEqual(self.signature(Foo.__call__),
2727 ((('a', ..., ..., "positional_or_keyword"),
2728 ('b', ..., ..., "positional_or_keyword")),
2729 ...))
2730
2731 self.assertEqual(self.signature(Foo().__call__),
2732 ((('b', ..., ..., "positional_or_keyword"),),
2733 ...))
2734
Nick Coghlane8c45d62013-07-28 20:00:01 +10002735 # Test we handle __signature__ partway down the wrapper stack
2736 def wrapped_foo_call():
2737 pass
2738 wrapped_foo_call.__wrapped__ = Foo.__call__
2739
2740 self.assertEqual(self.signature(wrapped_foo_call),
2741 ((('a', ..., ..., "positional_or_keyword"),
2742 ('b', ..., ..., "positional_or_keyword")),
2743 ...))
2744
2745
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002746 def test_signature_on_class(self):
2747 class C:
2748 def __init__(self, a):
2749 pass
2750
2751 self.assertEqual(self.signature(C),
2752 ((('a', ..., ..., "positional_or_keyword"),),
2753 ...))
2754
2755 class CM(type):
2756 def __call__(cls, a):
2757 pass
2758 class C(metaclass=CM):
2759 def __init__(self, b):
2760 pass
2761
2762 self.assertEqual(self.signature(C),
2763 ((('a', ..., ..., "positional_or_keyword"),),
2764 ...))
2765
2766 class CM(type):
2767 def __new__(mcls, name, bases, dct, *, foo=1):
2768 return super().__new__(mcls, name, bases, dct)
2769 class C(metaclass=CM):
2770 def __init__(self, b):
2771 pass
2772
2773 self.assertEqual(self.signature(C),
2774 ((('b', ..., ..., "positional_or_keyword"),),
2775 ...))
2776
2777 self.assertEqual(self.signature(CM),
2778 ((('name', ..., ..., "positional_or_keyword"),
2779 ('bases', ..., ..., "positional_or_keyword"),
2780 ('dct', ..., ..., "positional_or_keyword"),
2781 ('foo', 1, ..., "keyword_only")),
2782 ...))
2783
2784 class CMM(type):
2785 def __new__(mcls, name, bases, dct, *, foo=1):
2786 return super().__new__(mcls, name, bases, dct)
2787 def __call__(cls, nm, bs, dt):
2788 return type(nm, bs, dt)
2789 class CM(type, metaclass=CMM):
2790 def __new__(mcls, name, bases, dct, *, bar=2):
2791 return super().__new__(mcls, name, bases, dct)
2792 class C(metaclass=CM):
2793 def __init__(self, b):
2794 pass
2795
2796 self.assertEqual(self.signature(CMM),
2797 ((('name', ..., ..., "positional_or_keyword"),
2798 ('bases', ..., ..., "positional_or_keyword"),
2799 ('dct', ..., ..., "positional_or_keyword"),
2800 ('foo', 1, ..., "keyword_only")),
2801 ...))
2802
2803 self.assertEqual(self.signature(CM),
2804 ((('nm', ..., ..., "positional_or_keyword"),
2805 ('bs', ..., ..., "positional_or_keyword"),
2806 ('dt', ..., ..., "positional_or_keyword")),
2807 ...))
2808
2809 self.assertEqual(self.signature(C),
2810 ((('b', ..., ..., "positional_or_keyword"),),
2811 ...))
2812
2813 class CM(type):
2814 def __init__(cls, name, bases, dct, *, bar=2):
2815 return super().__init__(name, bases, dct)
2816 class C(metaclass=CM):
2817 def __init__(self, b):
2818 pass
2819
2820 self.assertEqual(self.signature(CM),
2821 ((('name', ..., ..., "positional_or_keyword"),
2822 ('bases', ..., ..., "positional_or_keyword"),
2823 ('dct', ..., ..., "positional_or_keyword"),
2824 ('bar', 2, ..., "keyword_only")),
2825 ...))
2826
Yury Selivanov145dff82014-02-01 13:49:29 -05002827 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2828 "Signature information for builtins requires docstrings")
2829 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002830 # Test classes without user-defined __init__ or __new__
2831 class C: pass
2832 self.assertEqual(str(inspect.signature(C)), '()')
2833 class D(C): pass
2834 self.assertEqual(str(inspect.signature(D)), '()')
2835
2836 # Test meta-classes without user-defined __init__ or __new__
2837 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002838 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002839 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2840 self.assertEqual(inspect.signature(C), None)
2841 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2842 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002843
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002844 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2845 "Signature information for builtins requires docstrings")
2846 def test_signature_on_builtin_class(self):
2847 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2848 '(file, protocol=None, fix_imports=True)')
2849
2850 class P(_pickle.Pickler): pass
2851 class EmptyTrait: pass
2852 class P2(EmptyTrait, P): pass
2853 self.assertEqual(str(inspect.signature(P)),
2854 '(file, protocol=None, fix_imports=True)')
2855 self.assertEqual(str(inspect.signature(P2)),
2856 '(file, protocol=None, fix_imports=True)')
2857
2858 class P3(P2):
2859 def __init__(self, spam):
2860 pass
2861 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2862
2863 class MetaP(type):
2864 def __call__(cls, foo, bar):
2865 pass
2866 class P4(P2, metaclass=MetaP):
2867 pass
2868 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2869
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002870 def test_signature_on_callable_objects(self):
2871 class Foo:
2872 def __call__(self, a):
2873 pass
2874
2875 self.assertEqual(self.signature(Foo()),
2876 ((('a', ..., ..., "positional_or_keyword"),),
2877 ...))
2878
2879 class Spam:
2880 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002881 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002882 inspect.signature(Spam())
2883
2884 class Bar(Spam, Foo):
2885 pass
2886
2887 self.assertEqual(self.signature(Bar()),
2888 ((('a', ..., ..., "positional_or_keyword"),),
2889 ...))
2890
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002891 class Wrapped:
2892 pass
2893 Wrapped.__wrapped__ = lambda a: None
2894 self.assertEqual(self.signature(Wrapped),
2895 ((('a', ..., ..., "positional_or_keyword"),),
2896 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002897 # wrapper loop:
2898 Wrapped.__wrapped__ = Wrapped
2899 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2900 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002901
2902 def test_signature_on_lambdas(self):
2903 self.assertEqual(self.signature((lambda a=10: a)),
2904 ((('a', 10, ..., "positional_or_keyword"),),
2905 ...))
2906
2907 def test_signature_equality(self):
2908 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002909 self.assertFalse(inspect.signature(foo) == 42)
2910 self.assertTrue(inspect.signature(foo) != 42)
2911 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2912 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002913
2914 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002915 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2916 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002917 self.assertEqual(
2918 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002919
2920 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002921 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2922 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002923 self.assertNotEqual(
2924 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002925
2926 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002927 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2928 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002929 self.assertNotEqual(
2930 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002931
2932 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002933 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2934 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002935 self.assertNotEqual(
2936 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002937
2938 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002939 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2940 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002941 self.assertNotEqual(
2942 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002943
2944 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002945 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2946 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002947 self.assertNotEqual(
2948 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002949 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002950 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
2951 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002952 self.assertNotEqual(
2953 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002954
2955 def foo(*, a, b, c): pass
2956 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002957 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2958 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002959 self.assertEqual(
2960 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002961
2962 def foo(*, a=1, b, c): pass
2963 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002964 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2965 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002966 self.assertEqual(
2967 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002968
2969 def foo(pos, *, a=1, b, c): pass
2970 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002971 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2972 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002973 self.assertEqual(
2974 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002975
2976 def foo(pos, *, a, b, c): pass
2977 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002978 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2979 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002980 self.assertNotEqual(
2981 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002982
2983 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2984 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002985 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2986 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002987 self.assertEqual(
2988 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002989
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002990 def test_signature_hashable(self):
2991 S = inspect.Signature
2992 P = inspect.Parameter
2993
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002994 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002995 foo_sig = inspect.signature(foo)
2996
2997 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2998
2999 self.assertEqual(hash(foo_sig), hash(manual_sig))
3000 self.assertNotEqual(hash(foo_sig),
3001 hash(manual_sig.replace(return_annotation='spam')))
3002
3003 def bar(a) -> 1: pass
3004 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3005
3006 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003007 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003008 hash(inspect.signature(foo))
3009
3010 def foo(a) -> {}: pass
3011 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3012 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003013
3014 def test_signature_str(self):
3015 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3016 pass
3017 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003018 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003019
3020 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3021 pass
3022 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003023 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003024
3025 def foo():
3026 pass
3027 self.assertEqual(str(inspect.signature(foo)), '()')
3028
3029 def test_signature_str_positional_only(self):
3030 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003031 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003032
3033 def test(a_po, *, b, **kwargs):
3034 return a_po, kwargs
3035
3036 sig = inspect.signature(test)
3037 new_params = list(sig.parameters.values())
3038 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3039 test.__signature__ = sig.replace(parameters=new_params)
3040
3041 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003042 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003043
Yury Selivanov2393dca2014-01-27 15:07:58 -05003044 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3045 '(foo, /)')
3046
3047 self.assertEqual(str(S(parameters=[
3048 P('foo', P.POSITIONAL_ONLY),
3049 P('bar', P.VAR_KEYWORD)])),
3050 '(foo, /, **bar)')
3051
3052 self.assertEqual(str(S(parameters=[
3053 P('foo', P.POSITIONAL_ONLY),
3054 P('bar', P.VAR_POSITIONAL)])),
3055 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003056
3057 def test_signature_replace_anno(self):
3058 def test() -> 42:
3059 pass
3060
3061 sig = inspect.signature(test)
3062 sig = sig.replace(return_annotation=None)
3063 self.assertIs(sig.return_annotation, None)
3064 sig = sig.replace(return_annotation=sig.empty)
3065 self.assertIs(sig.return_annotation, sig.empty)
3066 sig = sig.replace(return_annotation=42)
3067 self.assertEqual(sig.return_annotation, 42)
3068 self.assertEqual(sig, inspect.signature(test))
3069
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003070 def test_signature_on_mangled_parameters(self):
3071 class Spam:
3072 def foo(self, __p1:1=2, *, __p2:2=3):
3073 pass
3074 class Ham(Spam):
3075 pass
3076
3077 self.assertEqual(self.signature(Spam.foo),
3078 ((('self', ..., ..., "positional_or_keyword"),
3079 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3080 ('_Spam__p2', 3, 2, "keyword_only")),
3081 ...))
3082
3083 self.assertEqual(self.signature(Spam.foo),
3084 self.signature(Ham.foo))
3085
Yury Selivanovda396452014-03-27 12:09:24 -04003086 def test_signature_from_callable_python_obj(self):
3087 class MySignature(inspect.Signature): pass
3088 def foo(a, *, b:1): pass
3089 foo_sig = MySignature.from_callable(foo)
3090 self.assertTrue(isinstance(foo_sig, MySignature))
3091
3092 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3093 "Signature information for builtins requires docstrings")
3094 def test_signature_from_callable_builtin_obj(self):
3095 class MySignature(inspect.Signature): pass
3096 sig = MySignature.from_callable(_pickle.Pickler)
3097 self.assertTrue(isinstance(sig, MySignature))
3098
larryhastingsf36ba122018-01-28 11:13:09 -08003099 def test_signature_definition_order_preserved_on_kwonly(self):
3100 for fn in signatures_with_lexicographic_keyword_only_parameters():
3101 signature = inspect.signature(fn)
3102 l = list(signature.parameters)
3103 sorted_l = sorted(l)
3104 self.assertTrue(l)
3105 self.assertEqual(l, sorted_l)
3106 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3107 l = list(signature.parameters)
3108 self.assertEqual(l, unsorted_keyword_only_parameters)
3109
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003110
3111class TestParameterObject(unittest.TestCase):
3112 def test_signature_parameter_kinds(self):
3113 P = inspect.Parameter
3114 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3115 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3116
3117 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3118 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3119
3120 def test_signature_parameter_object(self):
3121 p = inspect.Parameter('foo', default=10,
3122 kind=inspect.Parameter.POSITIONAL_ONLY)
3123 self.assertEqual(p.name, 'foo')
3124 self.assertEqual(p.default, 10)
3125 self.assertIs(p.annotation, p.empty)
3126 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3127
Dong-hee Naa9cab432018-05-30 00:04:08 +09003128 with self.assertRaisesRegex(ValueError, "value '123' is "
3129 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003130 inspect.Parameter('foo', default=10, kind='123')
3131
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003132 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003133 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3134
Yury Selivanov2393dca2014-01-27 15:07:58 -05003135 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003136 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3137
Yury Selivanov2393dca2014-01-27 15:07:58 -05003138 with self.assertRaisesRegex(ValueError,
3139 'is not a valid parameter name'):
3140 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3141
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003142 with self.assertRaisesRegex(ValueError,
3143 'is not a valid parameter name'):
3144 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3145
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003146 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003147 inspect.Parameter('a', default=42,
3148 kind=inspect.Parameter.VAR_KEYWORD)
3149
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003150 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003151 inspect.Parameter('a', default=42,
3152 kind=inspect.Parameter.VAR_POSITIONAL)
3153
3154 p = inspect.Parameter('a', default=42,
3155 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003156 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003157 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3158
3159 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003160 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003161
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003162 def test_signature_parameter_hashable(self):
3163 P = inspect.Parameter
3164 foo = P('foo', kind=P.POSITIONAL_ONLY)
3165 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3166 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3167 default=42)))
3168 self.assertNotEqual(hash(foo),
3169 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3170
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003171 def test_signature_parameter_equality(self):
3172 P = inspect.Parameter
3173 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3174
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003175 self.assertTrue(p == p)
3176 self.assertFalse(p != p)
3177 self.assertFalse(p == 42)
3178 self.assertTrue(p != 42)
3179 self.assertTrue(p == EqualsToAll())
3180 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003181
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003182 self.assertTrue(p == P('foo', default=42,
3183 kind=inspect.Parameter.KEYWORD_ONLY))
3184 self.assertFalse(p != P('foo', default=42,
3185 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003186
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003187 def test_signature_parameter_replace(self):
3188 p = inspect.Parameter('foo', default=42,
3189 kind=inspect.Parameter.KEYWORD_ONLY)
3190
3191 self.assertIsNot(p, p.replace())
3192 self.assertEqual(p, p.replace())
3193
3194 p2 = p.replace(annotation=1)
3195 self.assertEqual(p2.annotation, 1)
3196 p2 = p2.replace(annotation=p2.empty)
3197 self.assertEqual(p, p2)
3198
3199 p2 = p2.replace(name='bar')
3200 self.assertEqual(p2.name, 'bar')
3201 self.assertNotEqual(p2, p)
3202
Yury Selivanov2393dca2014-01-27 15:07:58 -05003203 with self.assertRaisesRegex(ValueError,
3204 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003205 p2 = p2.replace(name=p2.empty)
3206
3207 p2 = p2.replace(name='foo', default=None)
3208 self.assertIs(p2.default, None)
3209 self.assertNotEqual(p2, p)
3210
3211 p2 = p2.replace(name='foo', default=p2.empty)
3212 self.assertIs(p2.default, p2.empty)
3213
3214
3215 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3216 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3217 self.assertNotEqual(p2, p)
3218
Dong-hee Naa9cab432018-05-30 00:04:08 +09003219 with self.assertRaisesRegex(ValueError,
3220 "value <class 'inspect._empty'> "
3221 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003222 p2 = p2.replace(kind=p2.empty)
3223
3224 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3225 self.assertEqual(p2, p)
3226
3227 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003228 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3229 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003230
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003231 @cpython_only
3232 def test_signature_parameter_implicit(self):
3233 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003234 'implicit arguments must be passed as '
3235 'positional or keyword arguments, '
3236 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003237 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3238
3239 param = inspect.Parameter(
3240 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3241 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3242 self.assertEqual(param.name, 'implicit0')
3243
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003244 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003245 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003246
3247 with self.assertRaises(AttributeError):
3248 p.foo = 'bar'
3249
3250 with self.assertRaises(AttributeError):
3251 p.kind = 123
3252
3253
3254class TestSignatureBind(unittest.TestCase):
3255 @staticmethod
3256 def call(func, *args, **kwargs):
3257 sig = inspect.signature(func)
3258 ba = sig.bind(*args, **kwargs)
3259 return func(*ba.args, **ba.kwargs)
3260
3261 def test_signature_bind_empty(self):
3262 def test():
3263 return 42
3264
3265 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003266 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003267 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003268 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003269 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003270 with self.assertRaisesRegex(
3271 TypeError, "got an unexpected keyword argument 'spam'"):
3272
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003273 self.call(test, spam=1)
3274
3275 def test_signature_bind_var(self):
3276 def test(*args, **kwargs):
3277 return args, kwargs
3278
3279 self.assertEqual(self.call(test), ((), {}))
3280 self.assertEqual(self.call(test, 1), ((1,), {}))
3281 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3282 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3283 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3284 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3285 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3286 ((1, 2), {'foo': 'bar'}))
3287
3288 def test_signature_bind_just_args(self):
3289 def test(a, b, c):
3290 return a, b, c
3291
3292 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3293
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003294 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003295 self.call(test, 1, 2, 3, 4)
3296
Yury Selivanov86872752015-05-19 00:27:49 -04003297 with self.assertRaisesRegex(TypeError,
3298 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003299 self.call(test, 1)
3300
Yury Selivanov86872752015-05-19 00:27:49 -04003301 with self.assertRaisesRegex(TypeError,
3302 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003303 self.call(test)
3304
3305 def test(a, b, c=10):
3306 return a, b, c
3307 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3308 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3309
3310 def test(a=1, b=2, c=3):
3311 return a, b, c
3312 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3313 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3314 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3315
3316 def test_signature_bind_varargs_order(self):
3317 def test(*args):
3318 return args
3319
3320 self.assertEqual(self.call(test), ())
3321 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3322
3323 def test_signature_bind_args_and_varargs(self):
3324 def test(a, b, c=3, *args):
3325 return a, b, c, args
3326
3327 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3328 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3329 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3330 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3331
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003332 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003333 "multiple values for argument 'c'"):
3334 self.call(test, 1, 2, 3, c=4)
3335
3336 def test_signature_bind_just_kwargs(self):
3337 def test(**kwargs):
3338 return kwargs
3339
3340 self.assertEqual(self.call(test), {})
3341 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3342 {'foo': 'bar', 'spam': 'ham'})
3343
3344 def test_signature_bind_args_and_kwargs(self):
3345 def test(a, b, c=3, **kwargs):
3346 return a, b, c, kwargs
3347
3348 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3349 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3350 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3351 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3352 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3353 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3354 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3355 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3356 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3357 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3358 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3359 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3360 (1, 2, 4, {'foo': 'bar'}))
3361 self.assertEqual(self.call(test, c=5, a=4, b=3),
3362 (4, 3, 5, {}))
3363
3364 def test_signature_bind_kwonly(self):
3365 def test(*, foo):
3366 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003367 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003368 'too many positional arguments'):
3369 self.call(test, 1)
3370 self.assertEqual(self.call(test, foo=1), 1)
3371
3372 def test(a, *, foo=1, bar):
3373 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003374 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003375 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003376 self.call(test, 1)
3377
3378 def test(foo, *, bar):
3379 return foo, bar
3380 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3381 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3382
Yury Selivanov86872752015-05-19 00:27:49 -04003383 with self.assertRaisesRegex(
3384 TypeError, "got an unexpected keyword argument 'spam'"):
3385
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003386 self.call(test, bar=2, foo=1, spam=10)
3387
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003388 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003389 'too many positional arguments'):
3390 self.call(test, 1, 2)
3391
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003392 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003393 'too many positional arguments'):
3394 self.call(test, 1, 2, bar=2)
3395
Yury Selivanov86872752015-05-19 00:27:49 -04003396 with self.assertRaisesRegex(
3397 TypeError, "got an unexpected keyword argument 'spam'"):
3398
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003399 self.call(test, 1, bar=2, spam='ham')
3400
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003401 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003402 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003403 self.call(test, 1)
3404
3405 def test(foo, *, bar, **bin):
3406 return foo, bar, bin
3407 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3408 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3409 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3410 (1, 2, {'spam': 'ham'}))
3411 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3412 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003413 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003414 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003415 self.call(test, spam='ham', bar=2)
3416 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3417 (1, 2, {'bin': 1, 'spam': 10}))
3418
3419 def test_signature_bind_arguments(self):
3420 def test(a, *args, b, z=100, **kwargs):
3421 pass
3422 sig = inspect.signature(test)
3423 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3424 # we won't have 'z' argument in the bound arguments object, as we didn't
3425 # pass it to the 'bind'
3426 self.assertEqual(tuple(ba.arguments.items()),
3427 (('a', 10), ('args', (20,)), ('b', 30),
3428 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3429 self.assertEqual(ba.kwargs,
3430 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3431 self.assertEqual(ba.args, (10, 20))
3432
3433 def test_signature_bind_positional_only(self):
3434 P = inspect.Parameter
3435
3436 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3437 return a_po, b_po, c_po, foo, bar, kwargs
3438
3439 sig = inspect.signature(test)
3440 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3441 for name in ('a_po', 'b_po', 'c_po'):
3442 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3443 new_sig = sig.replace(parameters=new_params.values())
3444 test.__signature__ = new_sig
3445
3446 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3447 (1, 2, 4, 5, 6, {}))
3448
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003449 self.assertEqual(self.call(test, 1, 2),
3450 (1, 2, 3, 42, 50, {}))
3451
3452 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3453 (1, 2, 3, 4, 5, {}))
3454
3455 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3456 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3457
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003458 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003459 self.call(test, 1, 2, c_po=4)
3460
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003461 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003462 self.call(test, a_po=1, b_po=2)
3463
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003464 def test_signature_bind_with_self_arg(self):
3465 # Issue #17071: one of the parameters is named "self
3466 def test(a, self, b):
3467 pass
3468 sig = inspect.signature(test)
3469 ba = sig.bind(1, 2, 3)
3470 self.assertEqual(ba.args, (1, 2, 3))
3471 ba = sig.bind(1, self=2, b=3)
3472 self.assertEqual(ba.args, (1, 2, 3))
3473
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003474 def test_signature_bind_vararg_name(self):
3475 def test(a, *args):
3476 return a, args
3477 sig = inspect.signature(test)
3478
Yury Selivanov86872752015-05-19 00:27:49 -04003479 with self.assertRaisesRegex(
3480 TypeError, "got an unexpected keyword argument 'args'"):
3481
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003482 sig.bind(a=0, args=1)
3483
3484 def test(*args, **kwargs):
3485 return args, kwargs
3486 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3487
3488 sig = inspect.signature(test)
3489 ba = sig.bind(args=1)
3490 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3491
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003492 @cpython_only
3493 def test_signature_bind_implicit_arg(self):
3494 # Issue #19611: getcallargs should work with set comprehensions
3495 def make_set():
3496 return {z * z for z in range(5)}
3497 setcomp_code = make_set.__code__.co_consts[1]
3498 setcomp_func = types.FunctionType(setcomp_code, {})
3499
3500 iterator = iter(range(5))
3501 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3502
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003503
3504class TestBoundArguments(unittest.TestCase):
3505 def test_signature_bound_arguments_unhashable(self):
3506 def foo(a): pass
3507 ba = inspect.signature(foo).bind(1)
3508
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003509 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003510 hash(ba)
3511
3512 def test_signature_bound_arguments_equality(self):
3513 def foo(a): pass
3514 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003515 self.assertTrue(ba == ba)
3516 self.assertFalse(ba != ba)
3517 self.assertTrue(ba == EqualsToAll())
3518 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003519
3520 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003521 self.assertTrue(ba == ba2)
3522 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003523
3524 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003525 self.assertFalse(ba == ba3)
3526 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003527 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003528 self.assertTrue(ba == ba3)
3529 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003530
3531 def bar(b): pass
3532 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003533 self.assertFalse(ba == ba4)
3534 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003535
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003536 def foo(*, a, b): pass
3537 sig = inspect.signature(foo)
3538 ba1 = sig.bind(a=1, b=2)
3539 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003540 self.assertTrue(ba1 == ba2)
3541 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003542
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003543 def test_signature_bound_arguments_pickle(self):
3544 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3545 sig = inspect.signature(foo)
3546 ba = sig.bind(20, 30, z={})
3547
3548 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3549 with self.subTest(pickle_ver=ver):
3550 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3551 self.assertEqual(ba, ba_pickled)
3552
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003553 def test_signature_bound_arguments_repr(self):
3554 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3555 sig = inspect.signature(foo)
3556 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003557 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003558
Yury Selivanovb907a512015-05-16 13:45:09 -04003559 def test_signature_bound_arguments_apply_defaults(self):
3560 def foo(a, b=1, *args, c:1={}, **kw): pass
3561 sig = inspect.signature(foo)
3562
3563 ba = sig.bind(20)
3564 ba.apply_defaults()
3565 self.assertEqual(
3566 list(ba.arguments.items()),
3567 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3568
3569 # Make sure that we preserve the order:
3570 # i.e. 'c' should be *before* 'kw'.
3571 ba = sig.bind(10, 20, 30, d=1)
3572 ba.apply_defaults()
3573 self.assertEqual(
3574 list(ba.arguments.items()),
3575 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3576
3577 # Make sure that BoundArguments produced by bind_partial()
3578 # are supported.
3579 def foo(a, b): pass
3580 sig = inspect.signature(foo)
3581 ba = sig.bind_partial(20)
3582 ba.apply_defaults()
3583 self.assertEqual(
3584 list(ba.arguments.items()),
3585 [('a', 20)])
3586
3587 # Test no args
3588 def foo(): pass
3589 sig = inspect.signature(foo)
3590 ba = sig.bind()
3591 ba.apply_defaults()
3592 self.assertEqual(list(ba.arguments.items()), [])
3593
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003594 # Make sure a no-args binding still acquires proper defaults.
3595 def foo(a='spam'): pass
3596 sig = inspect.signature(foo)
3597 ba = sig.bind()
3598 ba.apply_defaults()
3599 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3600
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003601
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003602class TestSignaturePrivateHelpers(unittest.TestCase):
3603 def test_signature_get_bound_param(self):
3604 getter = inspect._signature_get_bound_param
3605
3606 self.assertEqual(getter('($self)'), 'self')
3607 self.assertEqual(getter('($self, obj)'), 'self')
3608 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3609
Larry Hastings2623c8c2014-02-08 22:15:29 -08003610 def _strip_non_python_syntax(self, input,
3611 clean_signature, self_parameter, last_positional_only):
3612 computed_clean_signature, \
3613 computed_self_parameter, \
3614 computed_last_positional_only = \
3615 inspect._signature_strip_non_python_syntax(input)
3616 self.assertEqual(computed_clean_signature, clean_signature)
3617 self.assertEqual(computed_self_parameter, self_parameter)
3618 self.assertEqual(computed_last_positional_only, last_positional_only)
3619
3620 def test_signature_strip_non_python_syntax(self):
3621 self._strip_non_python_syntax(
3622 "($module, /, path, mode, *, dir_fd=None, " +
3623 "effective_ids=False,\n follow_symlinks=True)",
3624 "(module, path, mode, *, dir_fd=None, " +
3625 "effective_ids=False, follow_symlinks=True)",
3626 0,
3627 0)
3628
3629 self._strip_non_python_syntax(
3630 "($module, word, salt, /)",
3631 "(module, word, salt)",
3632 0,
3633 2)
3634
3635 self._strip_non_python_syntax(
3636 "(x, y=None, z=None, /)",
3637 "(x, y=None, z=None)",
3638 None,
3639 2)
3640
3641 self._strip_non_python_syntax(
3642 "(x, y=None, z=None)",
3643 "(x, y=None, z=None)",
3644 None,
3645 None)
3646
3647 self._strip_non_python_syntax(
3648 "(x,\n y=None,\n z = None )",
3649 "(x, y=None, z=None)",
3650 None,
3651 None)
3652
3653 self._strip_non_python_syntax(
3654 "",
3655 "",
3656 None,
3657 None)
3658
3659 self._strip_non_python_syntax(
3660 None,
3661 None,
3662 None,
3663 None)
3664
Nick Coghlan9c680b02015-04-13 12:54:54 -04003665class TestSignatureDefinitions(unittest.TestCase):
3666 # This test case provides a home for checking that particular APIs
3667 # have signatures available for introspection
3668
3669 @cpython_only
3670 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3671 "Signature information for builtins requires docstrings")
3672 def test_builtins_have_signatures(self):
3673 # This checks all builtin callables in CPython have signatures
3674 # A few have signatures Signature can't yet handle, so we skip those
3675 # since they will have to wait until PEP 457 adds the required
3676 # introspection support to the inspect module
3677 # Some others also haven't been converted yet for various other
3678 # reasons, so we also skip those for the time being, but design
3679 # the test to fail in order to indicate when it needs to be
3680 # updated.
3681 no_signature = set()
3682 # These need PEP 457 groups
3683 needs_groups = {"range", "slice", "dir", "getattr",
3684 "next", "iter", "vars"}
3685 no_signature |= needs_groups
3686 # These need PEP 457 groups or a signature change to accept None
3687 needs_semantic_update = {"round"}
3688 no_signature |= needs_semantic_update
3689 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003690 needs_varargs = {"breakpoint", "min", "max", "print",
3691 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003692 no_signature |= needs_varargs
3693 # These simply weren't covered in the initial AC conversion
3694 # for builtin callables
3695 not_converted_yet = {"open", "__import__"}
3696 no_signature |= not_converted_yet
3697 # These builtin types are expected to provide introspection info
3698 types_with_signatures = set()
3699 # Check the signatures we expect to be there
3700 ns = vars(builtins)
3701 for name, obj in sorted(ns.items()):
3702 if not callable(obj):
3703 continue
3704 # The builtin types haven't been converted to AC yet
3705 if isinstance(obj, type) and (name not in types_with_signatures):
3706 # Note that this also skips all the exception types
3707 no_signature.add(name)
3708 if (name in no_signature):
3709 # Not yet converted
3710 continue
3711 with self.subTest(builtin=name):
3712 self.assertIsNotNone(inspect.signature(obj))
3713 # Check callables that haven't been converted don't claim a signature
3714 # This ensures this test will start failing as more signatures are
3715 # added, so the affected items can be moved into the scope of the
3716 # regression test above
3717 for name in no_signature:
3718 with self.subTest(builtin=name):
3719 self.assertIsNone(obj.__text_signature__)
3720
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003721
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003722class NTimesUnwrappable:
3723 def __init__(self, n):
3724 self.n = n
3725 self._next = None
3726
3727 @property
3728 def __wrapped__(self):
3729 if self.n <= 0:
3730 raise Exception("Unwrapped too many times")
3731 if self._next is None:
3732 self._next = NTimesUnwrappable(self.n - 1)
3733 return self._next
3734
Nick Coghlane8c45d62013-07-28 20:00:01 +10003735class TestUnwrap(unittest.TestCase):
3736
3737 def test_unwrap_one(self):
3738 def func(a, b):
3739 return a + b
3740 wrapper = functools.lru_cache(maxsize=20)(func)
3741 self.assertIs(inspect.unwrap(wrapper), func)
3742
3743 def test_unwrap_several(self):
3744 def func(a, b):
3745 return a + b
3746 wrapper = func
3747 for __ in range(10):
3748 @functools.wraps(wrapper)
3749 def wrapper():
3750 pass
3751 self.assertIsNot(wrapper.__wrapped__, func)
3752 self.assertIs(inspect.unwrap(wrapper), func)
3753
3754 def test_stop(self):
3755 def func1(a, b):
3756 return a + b
3757 @functools.wraps(func1)
3758 def func2():
3759 pass
3760 @functools.wraps(func2)
3761 def wrapper():
3762 pass
3763 func2.stop_here = 1
3764 unwrapped = inspect.unwrap(wrapper,
3765 stop=(lambda f: hasattr(f, "stop_here")))
3766 self.assertIs(unwrapped, func2)
3767
3768 def test_cycle(self):
3769 def func1(): pass
3770 func1.__wrapped__ = func1
3771 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3772 inspect.unwrap(func1)
3773
3774 def func2(): pass
3775 func2.__wrapped__ = func1
3776 func1.__wrapped__ = func2
3777 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3778 inspect.unwrap(func1)
3779 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3780 inspect.unwrap(func2)
3781
3782 def test_unhashable(self):
3783 def func(): pass
3784 func.__wrapped__ = None
3785 class C:
3786 __hash__ = None
3787 __wrapped__ = func
3788 self.assertIsNone(inspect.unwrap(C()))
3789
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003790 def test_recursion_limit(self):
3791 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3792 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3793 inspect.unwrap(obj)
3794
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003795class TestMain(unittest.TestCase):
3796 def test_only_source(self):
3797 module = importlib.import_module('unittest')
3798 rc, out, err = assert_python_ok('-m', 'inspect',
3799 'unittest')
3800 lines = out.decode().splitlines()
3801 # ignore the final newline
3802 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3803 self.assertEqual(err, b'')
3804
Yury Selivanov42407ab2014-06-23 10:23:50 -07003805 def test_custom_getattr(self):
3806 def foo():
3807 pass
3808 foo.__signature__ = 42
3809 with self.assertRaises(TypeError):
3810 inspect.signature(foo)
3811
Brett Cannon634a8fc2013-10-02 10:25:42 -04003812 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003813 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003814 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003815 rc, out, err = assert_python_ok('-m', 'inspect',
3816 'concurrent.futures:ThreadPoolExecutor')
3817 lines = out.decode().splitlines()
3818 # ignore the final newline
3819 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003820 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003821 self.assertEqual(err, b'')
3822
3823 def test_builtins(self):
3824 module = importlib.import_module('unittest')
3825 _, out, err = assert_python_failure('-m', 'inspect',
3826 'sys')
3827 lines = err.decode().splitlines()
3828 self.assertEqual(lines, ["Can't get info for builtin modules."])
3829
3830 def test_details(self):
3831 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003832 args = support.optim_args_from_interpreter_flags()
3833 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003834 'unittest', '--details')
3835 output = out.decode()
3836 # Just a quick sanity check on the output
3837 self.assertIn(module.__name__, output)
3838 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003839 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003840 self.assertEqual(err, b'')
3841
3842
Yury Selivanovef1e7502014-12-08 16:05:34 -05003843class TestReload(unittest.TestCase):
3844
3845 src_before = textwrap.dedent("""\
3846def foo():
3847 print("Bla")
3848 """)
3849
3850 src_after = textwrap.dedent("""\
3851def foo():
3852 print("Oh no!")
3853 """)
3854
3855 def assertInspectEqual(self, path, source):
3856 inspected_src = inspect.getsource(source)
3857 with open(path) as src:
3858 self.assertEqual(
3859 src.read().splitlines(True),
3860 inspected_src.splitlines(True)
3861 )
3862
3863 def test_getsource_reload(self):
3864 # see issue 1218234
3865 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3866 module = importlib.import_module(name)
3867 self.assertInspectEqual(path, module)
3868 with open(path, 'w') as src:
3869 src.write(self.src_after)
3870 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003871
Nick Coghlane8c45d62013-07-28 20:00:01 +10003872
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003873def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003874 run_unittest(
3875 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3876 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3877 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003878 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003879 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003880 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04003881 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003882 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07003883 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00003884 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003885
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003886if __name__ == "__main__":
3887 test_main()