blob: ee5a2d4c158d55965993e5f649005dfde9b5dfdd [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")
Miss Islington (bot)3e6020c2018-08-24 10:44:47 -0400347 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
Miss Islington (bot)3e6020c2018-08-24 10:44:47 -0400530class 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:
Miss Islington (bot)60b82742018-06-11 13:44:16 -0700725 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:
Miss Islington (bot)60b82742018-06-11 13:44:16 -0700743 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
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001149
Nick Coghlan2f92e542012-06-23 19:39:55 +10001150_global_ref = object()
1151class TestGetClosureVars(unittest.TestCase):
1152
1153 def test_name_resolution(self):
1154 # Basic test of the 4 different resolution mechanisms
1155 def f(nonlocal_ref):
1156 def g(local_ref):
1157 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1158 return g
1159 _arg = object()
1160 nonlocal_vars = {"nonlocal_ref": _arg}
1161 global_vars = {"_global_ref": _global_ref}
1162 builtin_vars = {"print": print}
1163 unbound_names = {"unbound_ref"}
1164 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1165 builtin_vars, unbound_names)
1166 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1167
1168 def test_generator_closure(self):
1169 def f(nonlocal_ref):
1170 def g(local_ref):
1171 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1172 yield
1173 return g
1174 _arg = object()
1175 nonlocal_vars = {"nonlocal_ref": _arg}
1176 global_vars = {"_global_ref": _global_ref}
1177 builtin_vars = {"print": print}
1178 unbound_names = {"unbound_ref"}
1179 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1180 builtin_vars, unbound_names)
1181 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1182
1183 def test_method_closure(self):
1184 class C:
1185 def f(self, nonlocal_ref):
1186 def g(local_ref):
1187 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1188 return g
1189 _arg = object()
1190 nonlocal_vars = {"nonlocal_ref": _arg}
1191 global_vars = {"_global_ref": _global_ref}
1192 builtin_vars = {"print": print}
1193 unbound_names = {"unbound_ref"}
1194 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1195 builtin_vars, unbound_names)
1196 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1197
1198 def test_nonlocal_vars(self):
1199 # More complex tests of nonlocal resolution
1200 def _nonlocal_vars(f):
1201 return inspect.getclosurevars(f).nonlocals
1202
1203 def make_adder(x):
1204 def add(y):
1205 return x + y
1206 return add
1207
1208 def curry(func, arg1):
1209 return lambda arg2: func(arg1, arg2)
1210
1211 def less_than(a, b):
1212 return a < b
1213
1214 # The infamous Y combinator.
1215 def Y(le):
1216 def g(f):
1217 return le(lambda x: f(f)(x))
1218 Y.g_ref = g
1219 return g(g)
1220
1221 def check_y_combinator(func):
1222 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1223
1224 inc = make_adder(1)
1225 add_two = make_adder(2)
1226 greater_than_five = curry(less_than, 5)
1227
1228 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1229 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1230 self.assertEqual(_nonlocal_vars(greater_than_five),
1231 {'arg1': 5, 'func': less_than})
1232 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1233 {'x': 3})
1234 Y(check_y_combinator)
1235
1236 def test_getclosurevars_empty(self):
1237 def foo(): pass
1238 _empty = inspect.ClosureVars({}, {}, {}, set())
1239 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1240 self.assertEqual(inspect.getclosurevars(foo), _empty)
1241
1242 def test_getclosurevars_error(self):
1243 class T: pass
1244 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1245 self.assertRaises(TypeError, inspect.getclosurevars, list)
1246 self.assertRaises(TypeError, inspect.getclosurevars, {})
1247
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001248 def _private_globals(self):
1249 code = """def f(): print(path)"""
1250 ns = {}
1251 exec(code, ns)
1252 return ns["f"], ns
1253
1254 def test_builtins_fallback(self):
1255 f, ns = self._private_globals()
1256 ns.pop("__builtins__", None)
1257 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1258 self.assertEqual(inspect.getclosurevars(f), expected)
1259
1260 def test_builtins_as_dict(self):
1261 f, ns = self._private_globals()
1262 ns["__builtins__"] = {"path":1}
1263 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1264 self.assertEqual(inspect.getclosurevars(f), expected)
1265
1266 def test_builtins_as_module(self):
1267 f, ns = self._private_globals()
1268 ns["__builtins__"] = os
1269 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1270 self.assertEqual(inspect.getclosurevars(f), expected)
1271
Nick Coghlan2f92e542012-06-23 19:39:55 +10001272
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001273class TestGetcallargsFunctions(unittest.TestCase):
1274
1275 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1276 locs = dict(locs or {}, func=func)
1277 r1 = eval('func(%s)' % call_params_string, None, locs)
1278 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1279 locs)
1280 self.assertEqual(r1, r2)
1281
1282 def assertEqualException(self, func, call_param_string, locs=None):
1283 locs = dict(locs or {}, func=func)
1284 try:
1285 eval('func(%s)' % call_param_string, None, locs)
1286 except Exception as e:
1287 ex1 = e
1288 else:
1289 self.fail('Exception not raised')
1290 try:
1291 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1292 locs)
1293 except Exception as e:
1294 ex2 = e
1295 else:
1296 self.fail('Exception not raised')
1297 self.assertIs(type(ex1), type(ex2))
1298 self.assertEqual(str(ex1), str(ex2))
1299 del ex1, ex2
1300
1301 def makeCallable(self, signature):
1302 """Create a function that returns its locals()"""
1303 code = "lambda %s: locals()"
1304 return eval(code % signature)
1305
1306 def test_plain(self):
1307 f = self.makeCallable('a, b=1')
1308 self.assertEqualCallArgs(f, '2')
1309 self.assertEqualCallArgs(f, '2, 3')
1310 self.assertEqualCallArgs(f, 'a=2')
1311 self.assertEqualCallArgs(f, 'b=3, a=2')
1312 self.assertEqualCallArgs(f, '2, b=3')
1313 # expand *iterable / **mapping
1314 self.assertEqualCallArgs(f, '*(2,)')
1315 self.assertEqualCallArgs(f, '*[2]')
1316 self.assertEqualCallArgs(f, '*(2, 3)')
1317 self.assertEqualCallArgs(f, '*[2, 3]')
1318 self.assertEqualCallArgs(f, '**{"a":2}')
1319 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1320 self.assertEqualCallArgs(f, '2, **{"b":3}')
1321 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1322 # expand UserList / UserDict
1323 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1324 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1325 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1326 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1327 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1328
1329 def test_varargs(self):
1330 f = self.makeCallable('a, b=1, *c')
1331 self.assertEqualCallArgs(f, '2')
1332 self.assertEqualCallArgs(f, '2, 3')
1333 self.assertEqualCallArgs(f, '2, 3, 4')
1334 self.assertEqualCallArgs(f, '*(2,3,4)')
1335 self.assertEqualCallArgs(f, '2, *[3,4]')
1336 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1337
1338 def test_varkw(self):
1339 f = self.makeCallable('a, b=1, **c')
1340 self.assertEqualCallArgs(f, 'a=2')
1341 self.assertEqualCallArgs(f, '2, b=3, c=4')
1342 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1343 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1344 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1345 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1346 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1347 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1348 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1349
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001350 def test_varkw_only(self):
1351 # issue11256:
1352 f = self.makeCallable('**c')
1353 self.assertEqualCallArgs(f, '')
1354 self.assertEqualCallArgs(f, 'a=1')
1355 self.assertEqualCallArgs(f, 'a=1, b=2')
1356 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1357 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1358 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1359
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001360 def test_keyword_only(self):
1361 f = self.makeCallable('a=3, *, c, d=2')
1362 self.assertEqualCallArgs(f, 'c=3')
1363 self.assertEqualCallArgs(f, 'c=3, a=3')
1364 self.assertEqualCallArgs(f, 'a=2, c=4')
1365 self.assertEqualCallArgs(f, '4, c=4')
1366 self.assertEqualException(f, '')
1367 self.assertEqualException(f, '3')
1368 self.assertEqualException(f, 'a=3')
1369 self.assertEqualException(f, 'd=4')
1370
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001371 f = self.makeCallable('*, c, d=2')
1372 self.assertEqualCallArgs(f, 'c=3')
1373 self.assertEqualCallArgs(f, 'c=3, d=4')
1374 self.assertEqualCallArgs(f, 'd=4, c=3')
1375
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001376 def test_multiple_features(self):
1377 f = self.makeCallable('a, b=2, *f, **g')
1378 self.assertEqualCallArgs(f, '2, 3, 7')
1379 self.assertEqualCallArgs(f, '2, 3, x=8')
1380 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1381 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1382 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1383 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1384 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1385 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1386 '(4,[5,6])]), **collections.UserDict('
1387 'y=9, z=10)')
1388
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001389 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1390 self.assertEqualCallArgs(f, '2, 3, x=8')
1391 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1392 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1393 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1394 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1395 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1396 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1397 '(4,[5,6])]), q=0, **collections.UserDict('
1398 'y=9, z=10)')
1399
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001400 def test_errors(self):
1401 f0 = self.makeCallable('')
1402 f1 = self.makeCallable('a, b')
1403 f2 = self.makeCallable('a, b=1')
1404 # f0 takes no arguments
1405 self.assertEqualException(f0, '1')
1406 self.assertEqualException(f0, 'x=1')
1407 self.assertEqualException(f0, '1,x=1')
1408 # f1 takes exactly 2 arguments
1409 self.assertEqualException(f1, '')
1410 self.assertEqualException(f1, '1')
1411 self.assertEqualException(f1, 'a=2')
1412 self.assertEqualException(f1, 'b=3')
1413 # f2 takes at least 1 argument
1414 self.assertEqualException(f2, '')
1415 self.assertEqualException(f2, 'b=3')
1416 for f in f1, f2:
1417 # f1/f2 takes exactly/at most 2 arguments
1418 self.assertEqualException(f, '2, 3, 4')
1419 self.assertEqualException(f, '1, 2, 3, a=1')
1420 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001421 # XXX: success of this one depends on dict order
1422 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001423 # f got an unexpected keyword argument
1424 self.assertEqualException(f, 'c=2')
1425 self.assertEqualException(f, '2, c=3')
1426 self.assertEqualException(f, '2, 3, c=4')
1427 self.assertEqualException(f, '2, c=4, b=3')
1428 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1429 # f got multiple values for keyword argument
1430 self.assertEqualException(f, '1, a=2')
1431 self.assertEqualException(f, '1, **{"a":2}')
1432 self.assertEqualException(f, '1, 2, b=3')
1433 # XXX: Python inconsistency
1434 # - for functions and bound methods: unexpected keyword 'c'
1435 # - for unbound methods: multiple values for keyword 'a'
1436 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001437 # issue11256:
1438 f3 = self.makeCallable('**c')
1439 self.assertEqualException(f3, '1, 2')
1440 self.assertEqualException(f3, '1, 2, a=1, b=2')
1441 f4 = self.makeCallable('*, a, b=0')
1442 self.assertEqualException(f3, '1, 2')
1443 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001444
Yury Selivanov875df202014-03-27 18:23:03 -04001445 # issue #20816: getcallargs() fails to iterate over non-existent
1446 # kwonlydefaults and raises a wrong TypeError
1447 def f5(*, a): pass
1448 with self.assertRaisesRegex(TypeError,
1449 'missing 1 required keyword-only'):
1450 inspect.getcallargs(f5)
1451
1452
Yury Selivanovdccfa132014-03-27 18:42:52 -04001453 # issue20817:
1454 def f6(a, b, c):
1455 pass
1456 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1457 inspect.getcallargs(f6)
1458
Miss Islington (bot)cb055bc2018-05-29 08:43:54 -07001459 # bpo-33197
1460 with self.assertRaisesRegex(ValueError,
1461 'variadic keyword parameters cannot'
1462 ' have default values'):
1463 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1464 default=42)
1465 with self.assertRaisesRegex(ValueError,
1466 "value 5 is not a valid Parameter.kind"):
1467 inspect.Parameter("bar", kind=5, default=42)
1468
1469 with self.assertRaisesRegex(TypeError,
1470 'name must be a str, not a int'):
1471 inspect.Parameter(123, kind=4)
1472
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001473class TestGetcallargsMethods(TestGetcallargsFunctions):
1474
1475 def setUp(self):
1476 class Foo(object):
1477 pass
1478 self.cls = Foo
1479 self.inst = Foo()
1480
1481 def makeCallable(self, signature):
1482 assert 'self' not in signature
1483 mk = super(TestGetcallargsMethods, self).makeCallable
1484 self.cls.method = mk('self, ' + signature)
1485 return self.inst.method
1486
1487class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1488
1489 def makeCallable(self, signature):
1490 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1491 return self.cls.method
1492
1493 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1494 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1495 *self._getAssertEqualParams(func, call_params_string, locs))
1496
1497 def assertEqualException(self, func, call_params_string, locs=None):
1498 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1499 *self._getAssertEqualParams(func, call_params_string, locs))
1500
1501 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1502 assert 'inst' not in call_params_string
1503 locs = dict(locs or {}, inst=self.inst)
1504 return (func, 'inst,' + call_params_string, locs)
1505
Michael Foord95fc51d2010-11-20 15:07:30 +00001506
1507class TestGetattrStatic(unittest.TestCase):
1508
1509 def test_basic(self):
1510 class Thing(object):
1511 x = object()
1512
1513 thing = Thing()
1514 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1515 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1516 with self.assertRaises(AttributeError):
1517 inspect.getattr_static(thing, 'y')
1518
1519 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1520
1521 def test_inherited(self):
1522 class Thing(object):
1523 x = object()
1524 class OtherThing(Thing):
1525 pass
1526
1527 something = OtherThing()
1528 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1529
1530 def test_instance_attr(self):
1531 class Thing(object):
1532 x = 2
1533 def __init__(self, x):
1534 self.x = x
1535 thing = Thing(3)
1536 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1537 del thing.x
1538 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1539
1540 def test_property(self):
1541 class Thing(object):
1542 @property
1543 def x(self):
1544 raise AttributeError("I'm pretending not to exist")
1545 thing = Thing()
1546 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1547
Ezio Melotti75cbd732011-04-28 00:59:29 +03001548 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001549 class descriptor(object):
1550 def __get__(*_):
1551 raise AttributeError("I'm pretending not to exist")
1552 desc = descriptor()
1553 class Thing(object):
1554 x = desc
1555 thing = Thing()
1556 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1557
1558 def test_classAttribute(self):
1559 class Thing(object):
1560 x = object()
1561
1562 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1563
Ethan Furmane03ea372013-09-25 07:14:41 -07001564 def test_classVirtualAttribute(self):
1565 class Thing(object):
1566 @types.DynamicClassAttribute
1567 def x(self):
1568 return self._x
1569 _x = object()
1570
1571 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1572
Michael Foord95fc51d2010-11-20 15:07:30 +00001573 def test_inherited_classattribute(self):
1574 class Thing(object):
1575 x = object()
1576 class OtherThing(Thing):
1577 pass
1578
1579 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1580
1581 def test_slots(self):
1582 class Thing(object):
1583 y = 'bar'
1584 __slots__ = ['x']
1585 def __init__(self):
1586 self.x = 'foo'
1587 thing = Thing()
1588 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1589 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1590
1591 del thing.x
1592 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1593
1594 def test_metaclass(self):
1595 class meta(type):
1596 attr = 'foo'
1597 class Thing(object, metaclass=meta):
1598 pass
1599 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1600
1601 class sub(meta):
1602 pass
1603 class OtherThing(object, metaclass=sub):
1604 x = 3
1605 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1606
1607 class OtherOtherThing(OtherThing):
1608 pass
1609 # this test is odd, but it was added as it exposed a bug
1610 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1611
1612 def test_no_dict_no_slots(self):
1613 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1614 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1615
1616 def test_no_dict_no_slots_instance_member(self):
1617 # returns descriptor
1618 with open(__file__) as handle:
1619 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1620
1621 def test_inherited_slots(self):
1622 # returns descriptor
1623 class Thing(object):
1624 __slots__ = ['x']
1625 def __init__(self):
1626 self.x = 'foo'
1627
1628 class OtherThing(Thing):
1629 pass
1630 # it would be nice if this worked...
1631 # we get the descriptor instead of the instance attribute
1632 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1633
1634 def test_descriptor(self):
1635 class descriptor(object):
1636 def __get__(self, instance, owner):
1637 return 3
1638 class Foo(object):
1639 d = descriptor()
1640
1641 foo = Foo()
1642
1643 # for a non data descriptor we return the instance attribute
1644 foo.__dict__['d'] = 1
1645 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1646
Mike53f7a7c2017-12-14 14:04:53 +03001647 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001648 # descriptor
1649 descriptor.__set__ = lambda s, i, v: None
1650 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1651
1652
1653 def test_metaclass_with_descriptor(self):
1654 class descriptor(object):
1655 def __get__(self, instance, owner):
1656 return 3
1657 class meta(type):
1658 d = descriptor()
1659 class Thing(object, metaclass=meta):
1660 pass
1661 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1662
1663
Michael Foordcc7ebb82010-11-20 16:20:16 +00001664 def test_class_as_property(self):
1665 class Base(object):
1666 foo = 3
1667
1668 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001669 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001670 @property
1671 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001672 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001673 return object
1674
Michael Foord35184ed2010-11-20 16:58:30 +00001675 instance = Something()
1676 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1677 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001678 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1679
Michael Foorde5162652010-11-20 16:40:44 +00001680 def test_mro_as_property(self):
1681 class Meta(type):
1682 @property
1683 def __mro__(self):
1684 return (object,)
1685
1686 class Base(object):
1687 foo = 3
1688
1689 class Something(Base, metaclass=Meta):
1690 pass
1691
1692 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1693 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1694
Michael Foorddcebe0f2011-03-15 19:20:44 -04001695 def test_dict_as_property(self):
1696 test = self
1697 test.called = False
1698
1699 class Foo(dict):
1700 a = 3
1701 @property
1702 def __dict__(self):
1703 test.called = True
1704 return {}
1705
1706 foo = Foo()
1707 foo.a = 4
1708 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1709 self.assertFalse(test.called)
1710
1711 def test_custom_object_dict(self):
1712 test = self
1713 test.called = False
1714
1715 class Custom(dict):
1716 def get(self, key, default=None):
1717 test.called = True
1718 super().get(key, default)
1719
1720 class Foo(object):
1721 a = 3
1722 foo = Foo()
1723 foo.__dict__ = Custom()
1724 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1725 self.assertFalse(test.called)
1726
1727 def test_metaclass_dict_as_property(self):
1728 class Meta(type):
1729 @property
1730 def __dict__(self):
1731 self.executed = True
1732
1733 class Thing(metaclass=Meta):
1734 executed = False
1735
1736 def __init__(self):
1737 self.spam = 42
1738
1739 instance = Thing()
1740 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1741 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001742
Michael Foorda51623b2011-12-18 22:01:40 +00001743 def test_module(self):
1744 sentinel = object()
1745 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1746 sentinel)
1747
Michael Foord3ba95f82011-12-22 01:13:37 +00001748 def test_metaclass_with_metaclass_with_dict_as_property(self):
1749 class MetaMeta(type):
1750 @property
1751 def __dict__(self):
1752 self.executed = True
1753 return dict(spam=42)
1754
1755 class Meta(type, metaclass=MetaMeta):
1756 executed = False
1757
1758 class Thing(metaclass=Meta):
1759 pass
1760
1761 with self.assertRaises(AttributeError):
1762 inspect.getattr_static(Thing, "spam")
1763 self.assertFalse(Thing.executed)
1764
Nick Coghlane0f04652010-11-21 03:44:04 +00001765class TestGetGeneratorState(unittest.TestCase):
1766
1767 def setUp(self):
1768 def number_generator():
1769 for number in range(5):
1770 yield number
1771 self.generator = number_generator()
1772
1773 def _generatorstate(self):
1774 return inspect.getgeneratorstate(self.generator)
1775
1776 def test_created(self):
1777 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1778
1779 def test_suspended(self):
1780 next(self.generator)
1781 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1782
1783 def test_closed_after_exhaustion(self):
1784 for i in self.generator:
1785 pass
1786 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1787
1788 def test_closed_after_immediate_exception(self):
1789 with self.assertRaises(RuntimeError):
1790 self.generator.throw(RuntimeError)
1791 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1792
1793 def test_running(self):
1794 # As mentioned on issue #10220, checking for the RUNNING state only
1795 # makes sense inside the generator itself.
1796 # The following generator checks for this by using the closure's
1797 # reference to self and the generator state checking helper method
1798 def running_check_generator():
1799 for number in range(5):
1800 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1801 yield number
1802 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1803 self.generator = running_check_generator()
1804 # Running up to the first yield
1805 next(self.generator)
1806 # Running after the first yield
1807 next(self.generator)
1808
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001809 def test_easy_debugging(self):
1810 # repr() and str() of a generator state should contain the state name
1811 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1812 for name in names:
1813 state = getattr(inspect, name)
1814 self.assertIn(name, repr(state))
1815 self.assertIn(name, str(state))
1816
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001817 def test_getgeneratorlocals(self):
1818 def each(lst, a=None):
1819 b=(1, 2, 3)
1820 for v in lst:
1821 if v == 3:
1822 c = 12
1823 yield v
1824
1825 numbers = each([1, 2, 3])
1826 self.assertEqual(inspect.getgeneratorlocals(numbers),
1827 {'a': None, 'lst': [1, 2, 3]})
1828 next(numbers)
1829 self.assertEqual(inspect.getgeneratorlocals(numbers),
1830 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1831 'b': (1, 2, 3)})
1832 next(numbers)
1833 self.assertEqual(inspect.getgeneratorlocals(numbers),
1834 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1835 'b': (1, 2, 3)})
1836 next(numbers)
1837 self.assertEqual(inspect.getgeneratorlocals(numbers),
1838 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1839 'b': (1, 2, 3), 'c': 12})
1840 try:
1841 next(numbers)
1842 except StopIteration:
1843 pass
1844 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1845
1846 def test_getgeneratorlocals_empty(self):
1847 def yield_one():
1848 yield 1
1849 one = yield_one()
1850 self.assertEqual(inspect.getgeneratorlocals(one), {})
1851 try:
1852 next(one)
1853 except StopIteration:
1854 pass
1855 self.assertEqual(inspect.getgeneratorlocals(one), {})
1856
1857 def test_getgeneratorlocals_error(self):
1858 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1859 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1860 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1861 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1862
Nick Coghlane0f04652010-11-21 03:44:04 +00001863
Yury Selivanov5376ba92015-06-22 12:19:30 -04001864class TestGetCoroutineState(unittest.TestCase):
1865
1866 def setUp(self):
1867 @types.coroutine
1868 def number_coroutine():
1869 for number in range(5):
1870 yield number
1871 async def coroutine():
1872 await number_coroutine()
1873 self.coroutine = coroutine()
1874
1875 def tearDown(self):
1876 self.coroutine.close()
1877
1878 def _coroutinestate(self):
1879 return inspect.getcoroutinestate(self.coroutine)
1880
1881 def test_created(self):
1882 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1883
1884 def test_suspended(self):
1885 self.coroutine.send(None)
1886 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1887
1888 def test_closed_after_exhaustion(self):
1889 while True:
1890 try:
1891 self.coroutine.send(None)
1892 except StopIteration:
1893 break
1894
1895 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1896
1897 def test_closed_after_immediate_exception(self):
1898 with self.assertRaises(RuntimeError):
1899 self.coroutine.throw(RuntimeError)
1900 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1901
1902 def test_easy_debugging(self):
1903 # repr() and str() of a coroutine state should contain the state name
1904 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1905 for name in names:
1906 state = getattr(inspect, name)
1907 self.assertIn(name, repr(state))
1908 self.assertIn(name, str(state))
1909
1910 def test_getcoroutinelocals(self):
1911 @types.coroutine
1912 def gencoro():
1913 yield
1914
1915 gencoro = gencoro()
1916 async def func(a=None):
1917 b = 'spam'
1918 await gencoro
1919
1920 coro = func()
1921 self.assertEqual(inspect.getcoroutinelocals(coro),
1922 {'a': None, 'gencoro': gencoro})
1923 coro.send(None)
1924 self.assertEqual(inspect.getcoroutinelocals(coro),
1925 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
1926
1927
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001928class MySignature(inspect.Signature):
1929 # Top-level to make it picklable;
1930 # used in test_signature_object_pickle
1931 pass
1932
1933class MyParameter(inspect.Parameter):
1934 # Top-level to make it picklable;
1935 # used in test_signature_object_pickle
1936 pass
1937
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001938
Yury Selivanova5d63dd2014-03-27 11:31:43 -04001939
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001940class TestSignatureObject(unittest.TestCase):
1941 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04001942 def signature(func, **kw):
1943 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001944 return (tuple((param.name,
1945 (... if param.default is param.empty else param.default),
1946 (... if param.annotation is param.empty
1947 else param.annotation),
1948 str(param.kind).lower())
1949 for param in sig.parameters.values()),
1950 (... if sig.return_annotation is sig.empty
1951 else sig.return_annotation))
1952
1953 def test_signature_object(self):
1954 S = inspect.Signature
1955 P = inspect.Parameter
1956
1957 self.assertEqual(str(S()), '()')
1958
Yury Selivanov07a9e452014-01-29 10:58:16 -05001959 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001960 pass
1961 sig = inspect.signature(test)
1962 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001963 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001964 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001965 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001966 args = sig.parameters['args']
1967 ko = sig.parameters['ko']
1968 kwargs = sig.parameters['kwargs']
1969
1970 S((po, pk, args, ko, kwargs))
1971
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001972 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001973 S((pk, po, args, ko, kwargs))
1974
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001975 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001976 S((po, args, pk, ko, kwargs))
1977
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001978 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001979 S((args, po, pk, ko, kwargs))
1980
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001981 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001982 S((po, pk, args, kwargs, ko))
1983
1984 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001985 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001986 S((po, pk, args, kwargs2, ko))
1987
Yury Selivanov07a9e452014-01-29 10:58:16 -05001988 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1989 S((pod, po))
1990
1991 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1992 S((po, pkd, pk))
1993
1994 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1995 S((pkd, pk))
1996
Yury Selivanov374375d2014-03-27 12:41:53 -04001997 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04001998 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04001999
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002000 def test_signature_object_pickle(self):
2001 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2002 foo_partial = functools.partial(foo, a=1)
2003
2004 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002005
2006 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2007 with self.subTest(pickle_ver=ver, subclass=False):
2008 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2009 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002010
2011 # Test that basic sub-classing works
2012 sig = inspect.signature(foo)
2013 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2014 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2015 mysig = MySignature().replace(parameters=myparams.values(),
2016 return_annotation=sig.return_annotation)
2017 self.assertTrue(isinstance(mysig, MySignature))
2018 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2019
2020 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2021 with self.subTest(pickle_ver=ver, subclass=True):
2022 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2023 self.assertEqual(mysig, sig_pickled)
2024 self.assertTrue(isinstance(sig_pickled, MySignature))
2025 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2026 MyParameter))
2027
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002028 def test_signature_immutability(self):
2029 def test(a):
2030 pass
2031 sig = inspect.signature(test)
2032
2033 with self.assertRaises(AttributeError):
2034 sig.foo = 'bar'
2035
2036 with self.assertRaises(TypeError):
2037 sig.parameters['a'] = None
2038
2039 def test_signature_on_noarg(self):
2040 def test():
2041 pass
2042 self.assertEqual(self.signature(test), ((), ...))
2043
2044 def test_signature_on_wargs(self):
2045 def test(a, b:'foo') -> 123:
2046 pass
2047 self.assertEqual(self.signature(test),
2048 ((('a', ..., ..., "positional_or_keyword"),
2049 ('b', ..., 'foo', "positional_or_keyword")),
2050 123))
2051
2052 def test_signature_on_wkwonly(self):
2053 def test(*, a:float, b:str) -> int:
2054 pass
2055 self.assertEqual(self.signature(test),
2056 ((('a', ..., float, "keyword_only"),
2057 ('b', ..., str, "keyword_only")),
2058 int))
2059
2060 def test_signature_on_complex_args(self):
2061 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2062 pass
2063 self.assertEqual(self.signature(test),
2064 ((('a', ..., ..., "positional_or_keyword"),
2065 ('b', 10, 'foo', "positional_or_keyword"),
2066 ('args', ..., 'bar', "var_positional"),
2067 ('spam', ..., 'baz', "keyword_only"),
2068 ('ham', 123, ..., "keyword_only"),
2069 ('kwargs', ..., int, "var_keyword")),
2070 ...))
2071
Dong-hee Na378d7062017-05-18 04:00:51 +09002072 def test_signature_without_self(self):
2073 def test_args_only(*args): # NOQA
2074 pass
2075
2076 def test_args_kwargs_only(*args, **kwargs): # NOQA
2077 pass
2078
2079 class A:
2080 @classmethod
2081 def test_classmethod(*args): # NOQA
2082 pass
2083
2084 @staticmethod
2085 def test_staticmethod(*args): # NOQA
2086 pass
2087
2088 f1 = functools.partialmethod((test_classmethod), 1)
2089 f2 = functools.partialmethod((test_args_only), 1)
2090 f3 = functools.partialmethod((test_staticmethod), 1)
2091 f4 = functools.partialmethod((test_args_kwargs_only),1)
2092
2093 self.assertEqual(self.signature(test_args_only),
2094 ((('args', ..., ..., 'var_positional'),), ...))
2095 self.assertEqual(self.signature(test_args_kwargs_only),
2096 ((('args', ..., ..., 'var_positional'),
2097 ('kwargs', ..., ..., 'var_keyword')), ...))
2098 self.assertEqual(self.signature(A.f1),
2099 ((('args', ..., ..., 'var_positional'),), ...))
2100 self.assertEqual(self.signature(A.f2),
2101 ((('args', ..., ..., 'var_positional'),), ...))
2102 self.assertEqual(self.signature(A.f3),
2103 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002104 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002105 ((('args', ..., ..., 'var_positional'),
2106 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002107 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002108 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2109 "Signature information for builtins requires docstrings")
2110 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002111 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002112
Larry Hastings5c661892014-01-24 06:17:25 -08002113 def test_unbound_method(o):
2114 """Use this to test unbound methods (things that should have a self)"""
2115 signature = inspect.signature(o)
2116 self.assertTrue(isinstance(signature, inspect.Signature))
2117 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2118 return signature
2119
2120 def test_callable(o):
2121 """Use this to test bound methods or normal callables (things that don't expect self)"""
2122 signature = inspect.signature(o)
2123 self.assertTrue(isinstance(signature, inspect.Signature))
2124 if signature.parameters:
2125 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2126 return signature
2127
2128 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002129 def p(name): return signature.parameters[name].default
2130 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002131 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002132 self.assertEqual(p('d'), 3.14)
2133 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002134 self.assertEqual(p('n'), None)
2135 self.assertEqual(p('t'), True)
2136 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002137 self.assertEqual(p('local'), 3)
2138 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002139 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002140
Larry Hastings5c661892014-01-24 06:17:25 -08002141 test_callable(object)
2142
2143 # normal method
2144 # (PyMethodDescr_Type, "method_descriptor")
2145 test_unbound_method(_pickle.Pickler.dump)
2146 d = _pickle.Pickler(io.StringIO())
2147 test_callable(d.dump)
2148
2149 # static method
2150 test_callable(str.maketrans)
2151 test_callable('abc'.maketrans)
2152
2153 # class method
2154 test_callable(dict.fromkeys)
2155 test_callable({}.fromkeys)
2156
2157 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2158 test_unbound_method(type.__call__)
2159 test_unbound_method(int.__add__)
2160 test_callable((3).__add__)
2161
2162 # _PyMethodWrapper_Type
2163 # support for 'method-wrapper'
2164 test_callable(min.__call__)
2165
Larry Hastings2623c8c2014-02-08 22:15:29 -08002166 # This doesn't work now.
2167 # (We don't have a valid signature for "type" in 3.4)
2168 with self.assertRaisesRegex(ValueError, "no signature found"):
2169 class ThisWorksNow:
2170 __call__ = type
2171 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002172
Yury Selivanov056e2652014-03-02 12:25:27 -05002173 # Regression test for issue #20786
2174 test_unbound_method(dict.__delitem__)
2175 test_unbound_method(property.__delete__)
2176
Zachary Ware8ef887c2015-04-13 18:22:35 -05002177 # Regression test for issue #20586
2178 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2179
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002180 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002181 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2182 "Signature information for builtins requires docstrings")
2183 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002184 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002185 func = _testcapi.docstring_with_signature_with_defaults
2186
2187 def decorator(func):
2188 @functools.wraps(func)
2189 def wrapper(*args, **kwargs) -> int:
2190 return func(*args, **kwargs)
2191 return wrapper
2192
2193 decorated_func = decorator(func)
2194
2195 self.assertEqual(inspect.signature(func),
2196 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002197
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002198 def wrapper_like(*args, **kwargs) -> int: pass
2199 self.assertEqual(inspect.signature(decorated_func,
2200 follow_wrapped=False),
2201 inspect.signature(wrapper_like))
2202
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002203 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002204 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002205 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002206 with self.assertRaisesRegex(ValueError,
2207 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002208 inspect.signature(_testcapi.docstring_no_signature)
2209
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002210 with self.assertRaisesRegex(ValueError,
2211 'no signature found for builtin'):
2212 inspect.signature(str)
2213
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002214 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002215 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002216 inspect.signature(42)
2217
Yury Selivanov63da7c72014-01-31 14:48:37 -05002218 def test_signature_from_functionlike_object(self):
2219 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2220 pass
2221
2222 class funclike:
2223 # Has to be callable, and have correct
2224 # __code__, __annotations__, __defaults__, __name__,
2225 # and __kwdefaults__ attributes
2226
2227 def __init__(self, func):
2228 self.__name__ = func.__name__
2229 self.__code__ = func.__code__
2230 self.__annotations__ = func.__annotations__
2231 self.__defaults__ = func.__defaults__
2232 self.__kwdefaults__ = func.__kwdefaults__
2233 self.func = func
2234
2235 def __call__(self, *args, **kwargs):
2236 return self.func(*args, **kwargs)
2237
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002238 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002239
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002240 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002241 self.assertEqual(sig_funclike, sig_func)
2242
2243 sig_funclike = inspect.signature(funclike(func))
2244 self.assertEqual(sig_funclike, sig_func)
2245
2246 # If object is not a duck type of function, then
2247 # signature will try to get a signature for its '__call__'
2248 # method
2249 fl = funclike(func)
2250 del fl.__defaults__
2251 self.assertEqual(self.signature(fl),
2252 ((('args', ..., ..., "var_positional"),
2253 ('kwargs', ..., ..., "var_keyword")),
2254 ...))
2255
Yury Selivanova773de02014-02-21 18:30:53 -05002256 # Test with cython-like builtins:
2257 _orig_isdesc = inspect.ismethoddescriptor
2258 def _isdesc(obj):
2259 if hasattr(obj, '_builtinmock'):
2260 return True
2261 return _orig_isdesc(obj)
2262
2263 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2264 builtin_func = funclike(func)
2265 # Make sure that our mock setup is working
2266 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2267 builtin_func._builtinmock = True
2268 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2269 self.assertEqual(inspect.signature(builtin_func), sig_func)
2270
Yury Selivanov63da7c72014-01-31 14:48:37 -05002271 def test_signature_functionlike_class(self):
2272 # We only want to duck type function-like objects,
2273 # not classes.
2274
2275 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2276 pass
2277
2278 class funclike:
2279 def __init__(self, marker):
2280 pass
2281
2282 __name__ = func.__name__
2283 __code__ = func.__code__
2284 __annotations__ = func.__annotations__
2285 __defaults__ = func.__defaults__
2286 __kwdefaults__ = func.__kwdefaults__
2287
Yury Selivanov63da7c72014-01-31 14:48:37 -05002288 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2289
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002290 def test_signature_on_method(self):
2291 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002292 def __init__(*args):
2293 pass
2294 def m1(self, arg1, arg2=1) -> int:
2295 pass
2296 def m2(*args):
2297 pass
2298 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002299 pass
2300
Yury Selivanov62560fb2014-01-28 12:26:24 -05002301 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002302 ((('arg1', ..., ..., "positional_or_keyword"),
2303 ('arg2', 1, ..., "positional_or_keyword")),
2304 int))
2305
Yury Selivanov62560fb2014-01-28 12:26:24 -05002306 self.assertEqual(self.signature(Test().m2),
2307 ((('args', ..., ..., "var_positional"),),
2308 ...))
2309
2310 self.assertEqual(self.signature(Test),
2311 ((('args', ..., ..., "var_positional"),),
2312 ...))
2313
2314 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2315 self.signature(Test())
2316
Yury Selivanov46c759d2015-05-27 21:56:53 -04002317 def test_signature_wrapped_bound_method(self):
2318 # Issue 24298
2319 class Test:
2320 def m1(self, arg1, arg2=1) -> int:
2321 pass
2322 @functools.wraps(Test().m1)
2323 def m1d(*args, **kwargs):
2324 pass
2325 self.assertEqual(self.signature(m1d),
2326 ((('arg1', ..., ..., "positional_or_keyword"),
2327 ('arg2', 1, ..., "positional_or_keyword")),
2328 int))
2329
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002330 def test_signature_on_classmethod(self):
2331 class Test:
2332 @classmethod
2333 def foo(cls, arg1, *, arg2=1):
2334 pass
2335
2336 meth = Test().foo
2337 self.assertEqual(self.signature(meth),
2338 ((('arg1', ..., ..., "positional_or_keyword"),
2339 ('arg2', 1, ..., "keyword_only")),
2340 ...))
2341
2342 meth = Test.foo
2343 self.assertEqual(self.signature(meth),
2344 ((('arg1', ..., ..., "positional_or_keyword"),
2345 ('arg2', 1, ..., "keyword_only")),
2346 ...))
2347
2348 def test_signature_on_staticmethod(self):
2349 class Test:
2350 @staticmethod
2351 def foo(cls, *, arg):
2352 pass
2353
2354 meth = Test().foo
2355 self.assertEqual(self.signature(meth),
2356 ((('cls', ..., ..., "positional_or_keyword"),
2357 ('arg', ..., ..., "keyword_only")),
2358 ...))
2359
2360 meth = Test.foo
2361 self.assertEqual(self.signature(meth),
2362 ((('cls', ..., ..., "positional_or_keyword"),
2363 ('arg', ..., ..., "keyword_only")),
2364 ...))
2365
2366 def test_signature_on_partial(self):
2367 from functools import partial
2368
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002369 Parameter = inspect.Parameter
2370
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002371 def test():
2372 pass
2373
2374 self.assertEqual(self.signature(partial(test)), ((), ...))
2375
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002376 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002377 inspect.signature(partial(test, 1))
2378
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002379 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002380 inspect.signature(partial(test, a=1))
2381
2382 def test(a, b, *, c, d):
2383 pass
2384
2385 self.assertEqual(self.signature(partial(test)),
2386 ((('a', ..., ..., "positional_or_keyword"),
2387 ('b', ..., ..., "positional_or_keyword"),
2388 ('c', ..., ..., "keyword_only"),
2389 ('d', ..., ..., "keyword_only")),
2390 ...))
2391
2392 self.assertEqual(self.signature(partial(test, 1)),
2393 ((('b', ..., ..., "positional_or_keyword"),
2394 ('c', ..., ..., "keyword_only"),
2395 ('d', ..., ..., "keyword_only")),
2396 ...))
2397
2398 self.assertEqual(self.signature(partial(test, 1, c=2)),
2399 ((('b', ..., ..., "positional_or_keyword"),
2400 ('c', 2, ..., "keyword_only"),
2401 ('d', ..., ..., "keyword_only")),
2402 ...))
2403
2404 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2405 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002406 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002407 ('c', 2, ..., "keyword_only"),
2408 ('d', ..., ..., "keyword_only")),
2409 ...))
2410
2411 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002412 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002413 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002414 ('d', ..., ..., "keyword_only")),
2415 ...))
2416
2417 self.assertEqual(self.signature(partial(test, a=1)),
2418 ((('a', 1, ..., "keyword_only"),
2419 ('b', ..., ..., "keyword_only"),
2420 ('c', ..., ..., "keyword_only"),
2421 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002422 ...))
2423
2424 def test(a, *args, b, **kwargs):
2425 pass
2426
2427 self.assertEqual(self.signature(partial(test, 1)),
2428 ((('args', ..., ..., "var_positional"),
2429 ('b', ..., ..., "keyword_only"),
2430 ('kwargs', ..., ..., "var_keyword")),
2431 ...))
2432
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002433 self.assertEqual(self.signature(partial(test, a=1)),
2434 ((('a', 1, ..., "keyword_only"),
2435 ('b', ..., ..., "keyword_only"),
2436 ('kwargs', ..., ..., "var_keyword")),
2437 ...))
2438
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002439 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2440 ((('args', ..., ..., "var_positional"),
2441 ('b', ..., ..., "keyword_only"),
2442 ('kwargs', ..., ..., "var_keyword")),
2443 ...))
2444
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002445 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2446 ((('args', ..., ..., "var_positional"),
2447 ('b', ..., ..., "keyword_only"),
2448 ('kwargs', ..., ..., "var_keyword")),
2449 ...))
2450
2451 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2452 ((('args', ..., ..., "var_positional"),
2453 ('b', 0, ..., "keyword_only"),
2454 ('kwargs', ..., ..., "var_keyword")),
2455 ...))
2456
2457 self.assertEqual(self.signature(partial(test, b=0)),
2458 ((('a', ..., ..., "positional_or_keyword"),
2459 ('args', ..., ..., "var_positional"),
2460 ('b', 0, ..., "keyword_only"),
2461 ('kwargs', ..., ..., "var_keyword")),
2462 ...))
2463
2464 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2465 ((('a', ..., ..., "positional_or_keyword"),
2466 ('args', ..., ..., "var_positional"),
2467 ('b', 0, ..., "keyword_only"),
2468 ('kwargs', ..., ..., "var_keyword")),
2469 ...))
2470
2471 def test(a, b, c:int) -> 42:
2472 pass
2473
2474 sig = test.__signature__ = inspect.signature(test)
2475
2476 self.assertEqual(self.signature(partial(partial(test, 1))),
2477 ((('b', ..., ..., "positional_or_keyword"),
2478 ('c', ..., int, "positional_or_keyword")),
2479 42))
2480
2481 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2482 ((('c', ..., int, "positional_or_keyword"),),
2483 42))
2484
2485 psig = inspect.signature(partial(partial(test, 1), 2))
2486
2487 def foo(a):
2488 return a
2489 _foo = partial(partial(foo, a=10), a=20)
2490 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002491 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002492 ...))
2493 # check that we don't have any side-effects in signature(),
2494 # and the partial object is still functioning
2495 self.assertEqual(_foo(), 20)
2496
2497 def foo(a, b, c):
2498 return a, b, c
2499 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002500
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002501 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002502 ((('b', 30, ..., "keyword_only"),
2503 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002504 ...))
2505 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002506
2507 def foo(a, b, c, *, d):
2508 return a, b, c, d
2509 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2510 self.assertEqual(self.signature(_foo),
2511 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002512 ('b', 10, ..., "keyword_only"),
2513 ('c', 20, ..., "keyword_only"),
2514 ('d', 30, ..., "keyword_only"),
2515 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002516 ...))
2517 ba = inspect.signature(_foo).bind(a=200, b=11)
2518 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2519
2520 def foo(a=1, b=2, c=3):
2521 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002522 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2523
2524 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002525 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002526
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002527 ba = inspect.signature(_foo).bind(11, 12)
2528 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002529
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002530 ba = inspect.signature(_foo).bind(11, b=12)
2531 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002532
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002533 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002534 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2535
2536 _foo = partial(_foo, b=10, c=20)
2537 ba = inspect.signature(_foo).bind(12)
2538 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2539
2540
2541 def foo(a, b, c, d, **kwargs):
2542 pass
2543 sig = inspect.signature(foo)
2544 params = sig.parameters.copy()
2545 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2546 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2547 foo.__signature__ = inspect.Signature(params.values())
2548 sig = inspect.signature(foo)
2549 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2550
2551 self.assertEqual(self.signature(partial(foo, 1)),
2552 ((('b', ..., ..., 'positional_only'),
2553 ('c', ..., ..., 'positional_or_keyword'),
2554 ('d', ..., ..., 'positional_or_keyword'),
2555 ('kwargs', ..., ..., 'var_keyword')),
2556 ...))
2557
2558 self.assertEqual(self.signature(partial(foo, 1, 2)),
2559 ((('c', ..., ..., 'positional_or_keyword'),
2560 ('d', ..., ..., 'positional_or_keyword'),
2561 ('kwargs', ..., ..., 'var_keyword')),
2562 ...))
2563
2564 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2565 ((('d', ..., ..., 'positional_or_keyword'),
2566 ('kwargs', ..., ..., 'var_keyword')),
2567 ...))
2568
2569 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2570 ((('c', 3, ..., 'keyword_only'),
2571 ('d', ..., ..., 'keyword_only'),
2572 ('kwargs', ..., ..., 'var_keyword')),
2573 ...))
2574
2575 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2576 ((('b', ..., ..., 'positional_only'),
2577 ('c', 3, ..., 'keyword_only'),
2578 ('d', ..., ..., 'keyword_only'),
2579 ('kwargs', ..., ..., 'var_keyword')),
2580 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002581
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002582 def test_signature_on_partialmethod(self):
2583 from functools import partialmethod
2584
2585 class Spam:
2586 def test():
2587 pass
2588 ham = partialmethod(test)
2589
2590 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2591 inspect.signature(Spam.ham)
2592
2593 class Spam:
2594 def test(it, a, *, c) -> 'spam':
2595 pass
2596 ham = partialmethod(test, c=1)
2597
2598 self.assertEqual(self.signature(Spam.ham),
2599 ((('it', ..., ..., 'positional_or_keyword'),
2600 ('a', ..., ..., 'positional_or_keyword'),
2601 ('c', 1, ..., 'keyword_only')),
2602 'spam'))
2603
2604 self.assertEqual(self.signature(Spam().ham),
2605 ((('a', ..., ..., 'positional_or_keyword'),
2606 ('c', 1, ..., 'keyword_only')),
2607 'spam'))
2608
Miss Islington (bot)112f7992018-03-06 10:23:48 -08002609 class Spam:
2610 def test(self: 'anno', x):
2611 pass
2612
2613 g = partialmethod(test, 1)
2614
2615 self.assertEqual(self.signature(Spam.g),
2616 ((('self', ..., 'anno', 'positional_or_keyword'),),
2617 ...))
2618
Yury Selivanov0486f812014-01-29 12:18:59 -05002619 def test_signature_on_fake_partialmethod(self):
2620 def foo(a): pass
2621 foo._partialmethod = 'spam'
2622 self.assertEqual(str(inspect.signature(foo)), '(a)')
2623
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002624 def test_signature_on_decorated(self):
2625 import functools
2626
2627 def decorator(func):
2628 @functools.wraps(func)
2629 def wrapper(*args, **kwargs) -> int:
2630 return func(*args, **kwargs)
2631 return wrapper
2632
2633 class Foo:
2634 @decorator
2635 def bar(self, a, b):
2636 pass
2637
2638 self.assertEqual(self.signature(Foo.bar),
2639 ((('self', ..., ..., "positional_or_keyword"),
2640 ('a', ..., ..., "positional_or_keyword"),
2641 ('b', ..., ..., "positional_or_keyword")),
2642 ...))
2643
2644 self.assertEqual(self.signature(Foo().bar),
2645 ((('a', ..., ..., "positional_or_keyword"),
2646 ('b', ..., ..., "positional_or_keyword")),
2647 ...))
2648
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002649 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2650 ((('args', ..., ..., "var_positional"),
2651 ('kwargs', ..., ..., "var_keyword")),
2652 ...)) # functools.wraps will copy __annotations__
2653 # from "func" to "wrapper", hence no
2654 # return_annotation
2655
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002656 # Test that we handle method wrappers correctly
2657 def decorator(func):
2658 @functools.wraps(func)
2659 def wrapper(*args, **kwargs) -> int:
2660 return func(42, *args, **kwargs)
2661 sig = inspect.signature(func)
2662 new_params = tuple(sig.parameters.values())[1:]
2663 wrapper.__signature__ = sig.replace(parameters=new_params)
2664 return wrapper
2665
2666 class Foo:
2667 @decorator
2668 def __call__(self, a, b):
2669 pass
2670
2671 self.assertEqual(self.signature(Foo.__call__),
2672 ((('a', ..., ..., "positional_or_keyword"),
2673 ('b', ..., ..., "positional_or_keyword")),
2674 ...))
2675
2676 self.assertEqual(self.signature(Foo().__call__),
2677 ((('b', ..., ..., "positional_or_keyword"),),
2678 ...))
2679
Nick Coghlane8c45d62013-07-28 20:00:01 +10002680 # Test we handle __signature__ partway down the wrapper stack
2681 def wrapped_foo_call():
2682 pass
2683 wrapped_foo_call.__wrapped__ = Foo.__call__
2684
2685 self.assertEqual(self.signature(wrapped_foo_call),
2686 ((('a', ..., ..., "positional_or_keyword"),
2687 ('b', ..., ..., "positional_or_keyword")),
2688 ...))
2689
2690
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002691 def test_signature_on_class(self):
2692 class C:
2693 def __init__(self, a):
2694 pass
2695
2696 self.assertEqual(self.signature(C),
2697 ((('a', ..., ..., "positional_or_keyword"),),
2698 ...))
2699
2700 class CM(type):
2701 def __call__(cls, a):
2702 pass
2703 class C(metaclass=CM):
2704 def __init__(self, b):
2705 pass
2706
2707 self.assertEqual(self.signature(C),
2708 ((('a', ..., ..., "positional_or_keyword"),),
2709 ...))
2710
2711 class CM(type):
2712 def __new__(mcls, name, bases, dct, *, foo=1):
2713 return super().__new__(mcls, name, bases, dct)
2714 class C(metaclass=CM):
2715 def __init__(self, b):
2716 pass
2717
2718 self.assertEqual(self.signature(C),
2719 ((('b', ..., ..., "positional_or_keyword"),),
2720 ...))
2721
2722 self.assertEqual(self.signature(CM),
2723 ((('name', ..., ..., "positional_or_keyword"),
2724 ('bases', ..., ..., "positional_or_keyword"),
2725 ('dct', ..., ..., "positional_or_keyword"),
2726 ('foo', 1, ..., "keyword_only")),
2727 ...))
2728
2729 class CMM(type):
2730 def __new__(mcls, name, bases, dct, *, foo=1):
2731 return super().__new__(mcls, name, bases, dct)
2732 def __call__(cls, nm, bs, dt):
2733 return type(nm, bs, dt)
2734 class CM(type, metaclass=CMM):
2735 def __new__(mcls, name, bases, dct, *, bar=2):
2736 return super().__new__(mcls, name, bases, dct)
2737 class C(metaclass=CM):
2738 def __init__(self, b):
2739 pass
2740
2741 self.assertEqual(self.signature(CMM),
2742 ((('name', ..., ..., "positional_or_keyword"),
2743 ('bases', ..., ..., "positional_or_keyword"),
2744 ('dct', ..., ..., "positional_or_keyword"),
2745 ('foo', 1, ..., "keyword_only")),
2746 ...))
2747
2748 self.assertEqual(self.signature(CM),
2749 ((('nm', ..., ..., "positional_or_keyword"),
2750 ('bs', ..., ..., "positional_or_keyword"),
2751 ('dt', ..., ..., "positional_or_keyword")),
2752 ...))
2753
2754 self.assertEqual(self.signature(C),
2755 ((('b', ..., ..., "positional_or_keyword"),),
2756 ...))
2757
2758 class CM(type):
2759 def __init__(cls, name, bases, dct, *, bar=2):
2760 return super().__init__(name, bases, dct)
2761 class C(metaclass=CM):
2762 def __init__(self, b):
2763 pass
2764
2765 self.assertEqual(self.signature(CM),
2766 ((('name', ..., ..., "positional_or_keyword"),
2767 ('bases', ..., ..., "positional_or_keyword"),
2768 ('dct', ..., ..., "positional_or_keyword"),
2769 ('bar', 2, ..., "keyword_only")),
2770 ...))
2771
Yury Selivanov145dff82014-02-01 13:49:29 -05002772 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2773 "Signature information for builtins requires docstrings")
2774 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002775 # Test classes without user-defined __init__ or __new__
2776 class C: pass
2777 self.assertEqual(str(inspect.signature(C)), '()')
2778 class D(C): pass
2779 self.assertEqual(str(inspect.signature(D)), '()')
2780
2781 # Test meta-classes without user-defined __init__ or __new__
2782 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002783 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002784 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2785 self.assertEqual(inspect.signature(C), None)
2786 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2787 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002788
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002789 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2790 "Signature information for builtins requires docstrings")
2791 def test_signature_on_builtin_class(self):
2792 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2793 '(file, protocol=None, fix_imports=True)')
2794
2795 class P(_pickle.Pickler): pass
2796 class EmptyTrait: pass
2797 class P2(EmptyTrait, P): pass
2798 self.assertEqual(str(inspect.signature(P)),
2799 '(file, protocol=None, fix_imports=True)')
2800 self.assertEqual(str(inspect.signature(P2)),
2801 '(file, protocol=None, fix_imports=True)')
2802
2803 class P3(P2):
2804 def __init__(self, spam):
2805 pass
2806 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2807
2808 class MetaP(type):
2809 def __call__(cls, foo, bar):
2810 pass
2811 class P4(P2, metaclass=MetaP):
2812 pass
2813 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2814
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002815 def test_signature_on_callable_objects(self):
2816 class Foo:
2817 def __call__(self, a):
2818 pass
2819
2820 self.assertEqual(self.signature(Foo()),
2821 ((('a', ..., ..., "positional_or_keyword"),),
2822 ...))
2823
2824 class Spam:
2825 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002826 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002827 inspect.signature(Spam())
2828
2829 class Bar(Spam, Foo):
2830 pass
2831
2832 self.assertEqual(self.signature(Bar()),
2833 ((('a', ..., ..., "positional_or_keyword"),),
2834 ...))
2835
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002836 class Wrapped:
2837 pass
2838 Wrapped.__wrapped__ = lambda a: None
2839 self.assertEqual(self.signature(Wrapped),
2840 ((('a', ..., ..., "positional_or_keyword"),),
2841 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002842 # wrapper loop:
2843 Wrapped.__wrapped__ = Wrapped
2844 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2845 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002846
2847 def test_signature_on_lambdas(self):
2848 self.assertEqual(self.signature((lambda a=10: a)),
2849 ((('a', 10, ..., "positional_or_keyword"),),
2850 ...))
2851
2852 def test_signature_equality(self):
2853 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002854 self.assertFalse(inspect.signature(foo) == 42)
2855 self.assertTrue(inspect.signature(foo) != 42)
2856 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2857 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002858
2859 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002860 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2861 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002862 self.assertEqual(
2863 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002864
2865 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002866 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2867 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002868 self.assertNotEqual(
2869 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002870
2871 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002872 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2873 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002874 self.assertNotEqual(
2875 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002876
2877 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002878 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2879 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002880 self.assertNotEqual(
2881 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002882
2883 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002884 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2885 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002886 self.assertNotEqual(
2887 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002888
2889 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002890 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2891 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002892 self.assertNotEqual(
2893 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002894 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002895 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
2896 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002897 self.assertNotEqual(
2898 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002899
2900 def foo(*, a, b, c): pass
2901 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002902 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2903 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002904 self.assertEqual(
2905 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002906
2907 def foo(*, a=1, b, c): pass
2908 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002909 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2910 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002911 self.assertEqual(
2912 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002913
2914 def foo(pos, *, a=1, b, c): pass
2915 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002916 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2917 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002918 self.assertEqual(
2919 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002920
2921 def foo(pos, *, a, b, c): pass
2922 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002923 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2924 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002925 self.assertNotEqual(
2926 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002927
2928 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2929 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002930 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2931 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002932 self.assertEqual(
2933 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002934
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002935 def test_signature_hashable(self):
2936 S = inspect.Signature
2937 P = inspect.Parameter
2938
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002939 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002940 foo_sig = inspect.signature(foo)
2941
2942 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
2943
2944 self.assertEqual(hash(foo_sig), hash(manual_sig))
2945 self.assertNotEqual(hash(foo_sig),
2946 hash(manual_sig.replace(return_annotation='spam')))
2947
2948 def bar(a) -> 1: pass
2949 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
2950
2951 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002952 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04002953 hash(inspect.signature(foo))
2954
2955 def foo(a) -> {}: pass
2956 with self.assertRaisesRegex(TypeError, 'unhashable type'):
2957 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002958
2959 def test_signature_str(self):
2960 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2961 pass
2962 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09002963 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002964
2965 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2966 pass
2967 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09002968 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002969
2970 def foo():
2971 pass
2972 self.assertEqual(str(inspect.signature(foo)), '()')
2973
2974 def test_signature_str_positional_only(self):
2975 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002976 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002977
2978 def test(a_po, *, b, **kwargs):
2979 return a_po, kwargs
2980
2981 sig = inspect.signature(test)
2982 new_params = list(sig.parameters.values())
2983 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2984 test.__signature__ = sig.replace(parameters=new_params)
2985
2986 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002987 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002988
Yury Selivanov2393dca2014-01-27 15:07:58 -05002989 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2990 '(foo, /)')
2991
2992 self.assertEqual(str(S(parameters=[
2993 P('foo', P.POSITIONAL_ONLY),
2994 P('bar', P.VAR_KEYWORD)])),
2995 '(foo, /, **bar)')
2996
2997 self.assertEqual(str(S(parameters=[
2998 P('foo', P.POSITIONAL_ONLY),
2999 P('bar', P.VAR_POSITIONAL)])),
3000 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003001
3002 def test_signature_replace_anno(self):
3003 def test() -> 42:
3004 pass
3005
3006 sig = inspect.signature(test)
3007 sig = sig.replace(return_annotation=None)
3008 self.assertIs(sig.return_annotation, None)
3009 sig = sig.replace(return_annotation=sig.empty)
3010 self.assertIs(sig.return_annotation, sig.empty)
3011 sig = sig.replace(return_annotation=42)
3012 self.assertEqual(sig.return_annotation, 42)
3013 self.assertEqual(sig, inspect.signature(test))
3014
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003015 def test_signature_on_mangled_parameters(self):
3016 class Spam:
3017 def foo(self, __p1:1=2, *, __p2:2=3):
3018 pass
3019 class Ham(Spam):
3020 pass
3021
3022 self.assertEqual(self.signature(Spam.foo),
3023 ((('self', ..., ..., "positional_or_keyword"),
3024 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3025 ('_Spam__p2', 3, 2, "keyword_only")),
3026 ...))
3027
3028 self.assertEqual(self.signature(Spam.foo),
3029 self.signature(Ham.foo))
3030
Yury Selivanovda396452014-03-27 12:09:24 -04003031 def test_signature_from_callable_python_obj(self):
3032 class MySignature(inspect.Signature): pass
3033 def foo(a, *, b:1): pass
3034 foo_sig = MySignature.from_callable(foo)
3035 self.assertTrue(isinstance(foo_sig, MySignature))
3036
3037 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3038 "Signature information for builtins requires docstrings")
3039 def test_signature_from_callable_builtin_obj(self):
3040 class MySignature(inspect.Signature): pass
3041 sig = MySignature.from_callable(_pickle.Pickler)
3042 self.assertTrue(isinstance(sig, MySignature))
3043
larryhastingsf36ba122018-01-28 11:13:09 -08003044 def test_signature_definition_order_preserved_on_kwonly(self):
3045 for fn in signatures_with_lexicographic_keyword_only_parameters():
3046 signature = inspect.signature(fn)
3047 l = list(signature.parameters)
3048 sorted_l = sorted(l)
3049 self.assertTrue(l)
3050 self.assertEqual(l, sorted_l)
3051 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3052 l = list(signature.parameters)
3053 self.assertEqual(l, unsorted_keyword_only_parameters)
3054
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003055
3056class TestParameterObject(unittest.TestCase):
3057 def test_signature_parameter_kinds(self):
3058 P = inspect.Parameter
3059 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3060 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3061
3062 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3063 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3064
3065 def test_signature_parameter_object(self):
3066 p = inspect.Parameter('foo', default=10,
3067 kind=inspect.Parameter.POSITIONAL_ONLY)
3068 self.assertEqual(p.name, 'foo')
3069 self.assertEqual(p.default, 10)
3070 self.assertIs(p.annotation, p.empty)
3071 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3072
Miss Islington (bot)cb055bc2018-05-29 08:43:54 -07003073 with self.assertRaisesRegex(ValueError, "value '123' is "
3074 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003075 inspect.Parameter('foo', default=10, kind='123')
3076
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003077 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003078 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3079
Yury Selivanov2393dca2014-01-27 15:07:58 -05003080 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003081 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3082
Yury Selivanov2393dca2014-01-27 15:07:58 -05003083 with self.assertRaisesRegex(ValueError,
3084 'is not a valid parameter name'):
3085 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3086
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003087 with self.assertRaisesRegex(ValueError,
3088 'is not a valid parameter name'):
3089 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3090
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003091 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003092 inspect.Parameter('a', default=42,
3093 kind=inspect.Parameter.VAR_KEYWORD)
3094
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003095 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003096 inspect.Parameter('a', default=42,
3097 kind=inspect.Parameter.VAR_POSITIONAL)
3098
3099 p = inspect.Parameter('a', default=42,
3100 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003101 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003102 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3103
3104 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003105 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003106
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003107 def test_signature_parameter_hashable(self):
3108 P = inspect.Parameter
3109 foo = P('foo', kind=P.POSITIONAL_ONLY)
3110 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3111 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3112 default=42)))
3113 self.assertNotEqual(hash(foo),
3114 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3115
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003116 def test_signature_parameter_equality(self):
3117 P = inspect.Parameter
3118 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3119
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003120 self.assertTrue(p == p)
3121 self.assertFalse(p != p)
3122 self.assertFalse(p == 42)
3123 self.assertTrue(p != 42)
3124 self.assertTrue(p == EqualsToAll())
3125 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003126
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003127 self.assertTrue(p == P('foo', default=42,
3128 kind=inspect.Parameter.KEYWORD_ONLY))
3129 self.assertFalse(p != P('foo', default=42,
3130 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003131
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003132 def test_signature_parameter_replace(self):
3133 p = inspect.Parameter('foo', default=42,
3134 kind=inspect.Parameter.KEYWORD_ONLY)
3135
3136 self.assertIsNot(p, p.replace())
3137 self.assertEqual(p, p.replace())
3138
3139 p2 = p.replace(annotation=1)
3140 self.assertEqual(p2.annotation, 1)
3141 p2 = p2.replace(annotation=p2.empty)
3142 self.assertEqual(p, p2)
3143
3144 p2 = p2.replace(name='bar')
3145 self.assertEqual(p2.name, 'bar')
3146 self.assertNotEqual(p2, p)
3147
Yury Selivanov2393dca2014-01-27 15:07:58 -05003148 with self.assertRaisesRegex(ValueError,
3149 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003150 p2 = p2.replace(name=p2.empty)
3151
3152 p2 = p2.replace(name='foo', default=None)
3153 self.assertIs(p2.default, None)
3154 self.assertNotEqual(p2, p)
3155
3156 p2 = p2.replace(name='foo', default=p2.empty)
3157 self.assertIs(p2.default, p2.empty)
3158
3159
3160 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3161 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3162 self.assertNotEqual(p2, p)
3163
Miss Islington (bot)cb055bc2018-05-29 08:43:54 -07003164 with self.assertRaisesRegex(ValueError,
3165 "value <class 'inspect._empty'> "
3166 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003167 p2 = p2.replace(kind=p2.empty)
3168
3169 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3170 self.assertEqual(p2, p)
3171
3172 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003173 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3174 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003175
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003176 @cpython_only
3177 def test_signature_parameter_implicit(self):
3178 with self.assertRaisesRegex(ValueError,
Miss Islington (bot)cb055bc2018-05-29 08:43:54 -07003179 'implicit arguments must be passed as '
3180 'positional or keyword arguments, '
3181 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003182 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3183
3184 param = inspect.Parameter(
3185 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3186 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3187 self.assertEqual(param.name, 'implicit0')
3188
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003189 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003190 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003191
3192 with self.assertRaises(AttributeError):
3193 p.foo = 'bar'
3194
3195 with self.assertRaises(AttributeError):
3196 p.kind = 123
3197
3198
3199class TestSignatureBind(unittest.TestCase):
3200 @staticmethod
3201 def call(func, *args, **kwargs):
3202 sig = inspect.signature(func)
3203 ba = sig.bind(*args, **kwargs)
3204 return func(*ba.args, **ba.kwargs)
3205
3206 def test_signature_bind_empty(self):
3207 def test():
3208 return 42
3209
3210 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003211 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003212 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003213 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003214 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003215 with self.assertRaisesRegex(
3216 TypeError, "got an unexpected keyword argument 'spam'"):
3217
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003218 self.call(test, spam=1)
3219
3220 def test_signature_bind_var(self):
3221 def test(*args, **kwargs):
3222 return args, kwargs
3223
3224 self.assertEqual(self.call(test), ((), {}))
3225 self.assertEqual(self.call(test, 1), ((1,), {}))
3226 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3227 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3228 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3229 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3230 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3231 ((1, 2), {'foo': 'bar'}))
3232
3233 def test_signature_bind_just_args(self):
3234 def test(a, b, c):
3235 return a, b, c
3236
3237 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3238
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003239 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003240 self.call(test, 1, 2, 3, 4)
3241
Yury Selivanov86872752015-05-19 00:27:49 -04003242 with self.assertRaisesRegex(TypeError,
3243 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003244 self.call(test, 1)
3245
Yury Selivanov86872752015-05-19 00:27:49 -04003246 with self.assertRaisesRegex(TypeError,
3247 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003248 self.call(test)
3249
3250 def test(a, b, c=10):
3251 return a, b, c
3252 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3253 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3254
3255 def test(a=1, b=2, c=3):
3256 return a, b, c
3257 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3258 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3259 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3260
3261 def test_signature_bind_varargs_order(self):
3262 def test(*args):
3263 return args
3264
3265 self.assertEqual(self.call(test), ())
3266 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3267
3268 def test_signature_bind_args_and_varargs(self):
3269 def test(a, b, c=3, *args):
3270 return a, b, c, args
3271
3272 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3273 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3274 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3275 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3276
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003277 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003278 "multiple values for argument 'c'"):
3279 self.call(test, 1, 2, 3, c=4)
3280
3281 def test_signature_bind_just_kwargs(self):
3282 def test(**kwargs):
3283 return kwargs
3284
3285 self.assertEqual(self.call(test), {})
3286 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3287 {'foo': 'bar', 'spam': 'ham'})
3288
3289 def test_signature_bind_args_and_kwargs(self):
3290 def test(a, b, c=3, **kwargs):
3291 return a, b, c, kwargs
3292
3293 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3294 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3295 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3296 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3297 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3298 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3299 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3300 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3301 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3302 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3303 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3304 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3305 (1, 2, 4, {'foo': 'bar'}))
3306 self.assertEqual(self.call(test, c=5, a=4, b=3),
3307 (4, 3, 5, {}))
3308
3309 def test_signature_bind_kwonly(self):
3310 def test(*, foo):
3311 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003312 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003313 'too many positional arguments'):
3314 self.call(test, 1)
3315 self.assertEqual(self.call(test, foo=1), 1)
3316
3317 def test(a, *, foo=1, bar):
3318 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003319 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003320 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003321 self.call(test, 1)
3322
3323 def test(foo, *, bar):
3324 return foo, bar
3325 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3326 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3327
Yury Selivanov86872752015-05-19 00:27:49 -04003328 with self.assertRaisesRegex(
3329 TypeError, "got an unexpected keyword argument 'spam'"):
3330
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003331 self.call(test, bar=2, foo=1, spam=10)
3332
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003333 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003334 'too many positional arguments'):
3335 self.call(test, 1, 2)
3336
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003337 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003338 'too many positional arguments'):
3339 self.call(test, 1, 2, bar=2)
3340
Yury Selivanov86872752015-05-19 00:27:49 -04003341 with self.assertRaisesRegex(
3342 TypeError, "got an unexpected keyword argument 'spam'"):
3343
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003344 self.call(test, 1, bar=2, spam='ham')
3345
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003346 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003347 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003348 self.call(test, 1)
3349
3350 def test(foo, *, bar, **bin):
3351 return foo, bar, bin
3352 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3353 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3354 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3355 (1, 2, {'spam': 'ham'}))
3356 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3357 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003358 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003359 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003360 self.call(test, spam='ham', bar=2)
3361 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3362 (1, 2, {'bin': 1, 'spam': 10}))
3363
3364 def test_signature_bind_arguments(self):
3365 def test(a, *args, b, z=100, **kwargs):
3366 pass
3367 sig = inspect.signature(test)
3368 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3369 # we won't have 'z' argument in the bound arguments object, as we didn't
3370 # pass it to the 'bind'
3371 self.assertEqual(tuple(ba.arguments.items()),
3372 (('a', 10), ('args', (20,)), ('b', 30),
3373 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3374 self.assertEqual(ba.kwargs,
3375 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3376 self.assertEqual(ba.args, (10, 20))
3377
3378 def test_signature_bind_positional_only(self):
3379 P = inspect.Parameter
3380
3381 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3382 return a_po, b_po, c_po, foo, bar, kwargs
3383
3384 sig = inspect.signature(test)
3385 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3386 for name in ('a_po', 'b_po', 'c_po'):
3387 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3388 new_sig = sig.replace(parameters=new_params.values())
3389 test.__signature__ = new_sig
3390
3391 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3392 (1, 2, 4, 5, 6, {}))
3393
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003394 self.assertEqual(self.call(test, 1, 2),
3395 (1, 2, 3, 42, 50, {}))
3396
3397 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3398 (1, 2, 3, 4, 5, {}))
3399
3400 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3401 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3402
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003403 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003404 self.call(test, 1, 2, c_po=4)
3405
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003406 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003407 self.call(test, a_po=1, b_po=2)
3408
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003409 def test_signature_bind_with_self_arg(self):
3410 # Issue #17071: one of the parameters is named "self
3411 def test(a, self, b):
3412 pass
3413 sig = inspect.signature(test)
3414 ba = sig.bind(1, 2, 3)
3415 self.assertEqual(ba.args, (1, 2, 3))
3416 ba = sig.bind(1, self=2, b=3)
3417 self.assertEqual(ba.args, (1, 2, 3))
3418
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003419 def test_signature_bind_vararg_name(self):
3420 def test(a, *args):
3421 return a, args
3422 sig = inspect.signature(test)
3423
Yury Selivanov86872752015-05-19 00:27:49 -04003424 with self.assertRaisesRegex(
3425 TypeError, "got an unexpected keyword argument 'args'"):
3426
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003427 sig.bind(a=0, args=1)
3428
3429 def test(*args, **kwargs):
3430 return args, kwargs
3431 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3432
3433 sig = inspect.signature(test)
3434 ba = sig.bind(args=1)
3435 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3436
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003437 @cpython_only
3438 def test_signature_bind_implicit_arg(self):
3439 # Issue #19611: getcallargs should work with set comprehensions
3440 def make_set():
3441 return {z * z for z in range(5)}
3442 setcomp_code = make_set.__code__.co_consts[1]
3443 setcomp_func = types.FunctionType(setcomp_code, {})
3444
3445 iterator = iter(range(5))
3446 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3447
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003448
3449class TestBoundArguments(unittest.TestCase):
3450 def test_signature_bound_arguments_unhashable(self):
3451 def foo(a): pass
3452 ba = inspect.signature(foo).bind(1)
3453
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003454 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003455 hash(ba)
3456
3457 def test_signature_bound_arguments_equality(self):
3458 def foo(a): pass
3459 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003460 self.assertTrue(ba == ba)
3461 self.assertFalse(ba != ba)
3462 self.assertTrue(ba == EqualsToAll())
3463 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003464
3465 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003466 self.assertTrue(ba == ba2)
3467 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003468
3469 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003470 self.assertFalse(ba == ba3)
3471 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003472 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003473 self.assertTrue(ba == ba3)
3474 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003475
3476 def bar(b): pass
3477 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003478 self.assertFalse(ba == ba4)
3479 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003480
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003481 def foo(*, a, b): pass
3482 sig = inspect.signature(foo)
3483 ba1 = sig.bind(a=1, b=2)
3484 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003485 self.assertTrue(ba1 == ba2)
3486 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003487
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003488 def test_signature_bound_arguments_pickle(self):
3489 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3490 sig = inspect.signature(foo)
3491 ba = sig.bind(20, 30, z={})
3492
3493 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3494 with self.subTest(pickle_ver=ver):
3495 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3496 self.assertEqual(ba, ba_pickled)
3497
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003498 def test_signature_bound_arguments_repr(self):
3499 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3500 sig = inspect.signature(foo)
3501 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003502 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003503
Yury Selivanovb907a512015-05-16 13:45:09 -04003504 def test_signature_bound_arguments_apply_defaults(self):
3505 def foo(a, b=1, *args, c:1={}, **kw): pass
3506 sig = inspect.signature(foo)
3507
3508 ba = sig.bind(20)
3509 ba.apply_defaults()
3510 self.assertEqual(
3511 list(ba.arguments.items()),
3512 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3513
3514 # Make sure that we preserve the order:
3515 # i.e. 'c' should be *before* 'kw'.
3516 ba = sig.bind(10, 20, 30, d=1)
3517 ba.apply_defaults()
3518 self.assertEqual(
3519 list(ba.arguments.items()),
3520 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3521
3522 # Make sure that BoundArguments produced by bind_partial()
3523 # are supported.
3524 def foo(a, b): pass
3525 sig = inspect.signature(foo)
3526 ba = sig.bind_partial(20)
3527 ba.apply_defaults()
3528 self.assertEqual(
3529 list(ba.arguments.items()),
3530 [('a', 20)])
3531
3532 # Test no args
3533 def foo(): pass
3534 sig = inspect.signature(foo)
3535 ba = sig.bind()
3536 ba.apply_defaults()
3537 self.assertEqual(list(ba.arguments.items()), [])
3538
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003539 # Make sure a no-args binding still acquires proper defaults.
3540 def foo(a='spam'): pass
3541 sig = inspect.signature(foo)
3542 ba = sig.bind()
3543 ba.apply_defaults()
3544 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3545
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003546
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003547class TestSignaturePrivateHelpers(unittest.TestCase):
3548 def test_signature_get_bound_param(self):
3549 getter = inspect._signature_get_bound_param
3550
3551 self.assertEqual(getter('($self)'), 'self')
3552 self.assertEqual(getter('($self, obj)'), 'self')
3553 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3554
Larry Hastings2623c8c2014-02-08 22:15:29 -08003555 def _strip_non_python_syntax(self, input,
3556 clean_signature, self_parameter, last_positional_only):
3557 computed_clean_signature, \
3558 computed_self_parameter, \
3559 computed_last_positional_only = \
3560 inspect._signature_strip_non_python_syntax(input)
3561 self.assertEqual(computed_clean_signature, clean_signature)
3562 self.assertEqual(computed_self_parameter, self_parameter)
3563 self.assertEqual(computed_last_positional_only, last_positional_only)
3564
3565 def test_signature_strip_non_python_syntax(self):
3566 self._strip_non_python_syntax(
3567 "($module, /, path, mode, *, dir_fd=None, " +
3568 "effective_ids=False,\n follow_symlinks=True)",
3569 "(module, path, mode, *, dir_fd=None, " +
3570 "effective_ids=False, follow_symlinks=True)",
3571 0,
3572 0)
3573
3574 self._strip_non_python_syntax(
3575 "($module, word, salt, /)",
3576 "(module, word, salt)",
3577 0,
3578 2)
3579
3580 self._strip_non_python_syntax(
3581 "(x, y=None, z=None, /)",
3582 "(x, y=None, z=None)",
3583 None,
3584 2)
3585
3586 self._strip_non_python_syntax(
3587 "(x, y=None, z=None)",
3588 "(x, y=None, z=None)",
3589 None,
3590 None)
3591
3592 self._strip_non_python_syntax(
3593 "(x,\n y=None,\n z = None )",
3594 "(x, y=None, z=None)",
3595 None,
3596 None)
3597
3598 self._strip_non_python_syntax(
3599 "",
3600 "",
3601 None,
3602 None)
3603
3604 self._strip_non_python_syntax(
3605 None,
3606 None,
3607 None,
3608 None)
3609
Nick Coghlan9c680b02015-04-13 12:54:54 -04003610class TestSignatureDefinitions(unittest.TestCase):
3611 # This test case provides a home for checking that particular APIs
3612 # have signatures available for introspection
3613
3614 @cpython_only
3615 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3616 "Signature information for builtins requires docstrings")
3617 def test_builtins_have_signatures(self):
3618 # This checks all builtin callables in CPython have signatures
3619 # A few have signatures Signature can't yet handle, so we skip those
3620 # since they will have to wait until PEP 457 adds the required
3621 # introspection support to the inspect module
3622 # Some others also haven't been converted yet for various other
3623 # reasons, so we also skip those for the time being, but design
3624 # the test to fail in order to indicate when it needs to be
3625 # updated.
3626 no_signature = set()
3627 # These need PEP 457 groups
3628 needs_groups = {"range", "slice", "dir", "getattr",
3629 "next", "iter", "vars"}
3630 no_signature |= needs_groups
3631 # These need PEP 457 groups or a signature change to accept None
3632 needs_semantic_update = {"round"}
3633 no_signature |= needs_semantic_update
3634 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003635 needs_varargs = {"breakpoint", "min", "max", "print",
3636 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003637 no_signature |= needs_varargs
3638 # These simply weren't covered in the initial AC conversion
3639 # for builtin callables
3640 not_converted_yet = {"open", "__import__"}
3641 no_signature |= not_converted_yet
3642 # These builtin types are expected to provide introspection info
3643 types_with_signatures = set()
3644 # Check the signatures we expect to be there
3645 ns = vars(builtins)
3646 for name, obj in sorted(ns.items()):
3647 if not callable(obj):
3648 continue
3649 # The builtin types haven't been converted to AC yet
3650 if isinstance(obj, type) and (name not in types_with_signatures):
3651 # Note that this also skips all the exception types
3652 no_signature.add(name)
3653 if (name in no_signature):
3654 # Not yet converted
3655 continue
3656 with self.subTest(builtin=name):
3657 self.assertIsNotNone(inspect.signature(obj))
3658 # Check callables that haven't been converted don't claim a signature
3659 # This ensures this test will start failing as more signatures are
3660 # added, so the affected items can be moved into the scope of the
3661 # regression test above
3662 for name in no_signature:
3663 with self.subTest(builtin=name):
3664 self.assertIsNone(obj.__text_signature__)
3665
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003666
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003667class NTimesUnwrappable:
3668 def __init__(self, n):
3669 self.n = n
3670 self._next = None
3671
3672 @property
3673 def __wrapped__(self):
3674 if self.n <= 0:
3675 raise Exception("Unwrapped too many times")
3676 if self._next is None:
3677 self._next = NTimesUnwrappable(self.n - 1)
3678 return self._next
3679
Nick Coghlane8c45d62013-07-28 20:00:01 +10003680class TestUnwrap(unittest.TestCase):
3681
3682 def test_unwrap_one(self):
3683 def func(a, b):
3684 return a + b
3685 wrapper = functools.lru_cache(maxsize=20)(func)
3686 self.assertIs(inspect.unwrap(wrapper), func)
3687
3688 def test_unwrap_several(self):
3689 def func(a, b):
3690 return a + b
3691 wrapper = func
3692 for __ in range(10):
3693 @functools.wraps(wrapper)
3694 def wrapper():
3695 pass
3696 self.assertIsNot(wrapper.__wrapped__, func)
3697 self.assertIs(inspect.unwrap(wrapper), func)
3698
3699 def test_stop(self):
3700 def func1(a, b):
3701 return a + b
3702 @functools.wraps(func1)
3703 def func2():
3704 pass
3705 @functools.wraps(func2)
3706 def wrapper():
3707 pass
3708 func2.stop_here = 1
3709 unwrapped = inspect.unwrap(wrapper,
3710 stop=(lambda f: hasattr(f, "stop_here")))
3711 self.assertIs(unwrapped, func2)
3712
3713 def test_cycle(self):
3714 def func1(): pass
3715 func1.__wrapped__ = func1
3716 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3717 inspect.unwrap(func1)
3718
3719 def func2(): pass
3720 func2.__wrapped__ = func1
3721 func1.__wrapped__ = func2
3722 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3723 inspect.unwrap(func1)
3724 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3725 inspect.unwrap(func2)
3726
3727 def test_unhashable(self):
3728 def func(): pass
3729 func.__wrapped__ = None
3730 class C:
3731 __hash__ = None
3732 __wrapped__ = func
3733 self.assertIsNone(inspect.unwrap(C()))
3734
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003735 def test_recursion_limit(self):
3736 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3737 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3738 inspect.unwrap(obj)
3739
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003740class TestMain(unittest.TestCase):
3741 def test_only_source(self):
3742 module = importlib.import_module('unittest')
3743 rc, out, err = assert_python_ok('-m', 'inspect',
3744 'unittest')
3745 lines = out.decode().splitlines()
3746 # ignore the final newline
3747 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3748 self.assertEqual(err, b'')
3749
Yury Selivanov42407ab2014-06-23 10:23:50 -07003750 def test_custom_getattr(self):
3751 def foo():
3752 pass
3753 foo.__signature__ = 42
3754 with self.assertRaises(TypeError):
3755 inspect.signature(foo)
3756
Brett Cannon634a8fc2013-10-02 10:25:42 -04003757 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003758 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003759 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003760 rc, out, err = assert_python_ok('-m', 'inspect',
3761 'concurrent.futures:ThreadPoolExecutor')
3762 lines = out.decode().splitlines()
3763 # ignore the final newline
3764 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003765 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003766 self.assertEqual(err, b'')
3767
3768 def test_builtins(self):
3769 module = importlib.import_module('unittest')
3770 _, out, err = assert_python_failure('-m', 'inspect',
3771 'sys')
3772 lines = err.decode().splitlines()
3773 self.assertEqual(lines, ["Can't get info for builtin modules."])
3774
3775 def test_details(self):
3776 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003777 args = support.optim_args_from_interpreter_flags()
3778 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003779 'unittest', '--details')
3780 output = out.decode()
3781 # Just a quick sanity check on the output
3782 self.assertIn(module.__name__, output)
3783 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003784 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003785 self.assertEqual(err, b'')
3786
3787
Yury Selivanovef1e7502014-12-08 16:05:34 -05003788class TestReload(unittest.TestCase):
3789
3790 src_before = textwrap.dedent("""\
3791def foo():
3792 print("Bla")
3793 """)
3794
3795 src_after = textwrap.dedent("""\
3796def foo():
3797 print("Oh no!")
3798 """)
3799
3800 def assertInspectEqual(self, path, source):
3801 inspected_src = inspect.getsource(source)
3802 with open(path) as src:
3803 self.assertEqual(
3804 src.read().splitlines(True),
3805 inspected_src.splitlines(True)
3806 )
3807
3808 def test_getsource_reload(self):
3809 # see issue 1218234
3810 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3811 module = importlib.import_module(name)
3812 self.assertInspectEqual(path, module)
3813 with open(path, 'w') as src:
3814 src.write(self.src_after)
3815 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003816
Nick Coghlane8c45d62013-07-28 20:00:01 +10003817
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003818def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003819 run_unittest(
3820 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3821 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3822 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003823 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003824 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003825 TestBoundArguments, TestSignaturePrivateHelpers,
3826 TestSignatureDefinitions,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003827 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Miss Islington (bot)3e6020c2018-08-24 10:44:47 -04003828 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00003829 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003830
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003831if __name__ == "__main__":
3832 test_main()