blob: 35ad0b93e7dc2e8dd029c061ac53f2c2c7370440 [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
Hai Shic7decc22020-08-04 23:53:12 +080027from test.support import run_unittest, cpython_only
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +030028from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ
Hai Shic7decc22020-08-04 23:53:12 +080029from test.support.import_helper import DirsOnSysPath
30from test.support.os_helper import TESTFN
Berker Peksagce643912015-05-06 06:33:17 +030031from test.support.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000032from test import inspect_fodder as mod
33from test import inspect_fodder2 as mod2
Victor Stinner9def2842016-01-18 12:15:08 +010034from test import support
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000035
Yury Selivanovef1e7502014-12-08 16:05:34 -050036from test.test_import import _ready_to_import
37
R. David Murray74b89242009-05-13 17:33:03 +000038
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000039# Functions tested in this suite:
40# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000041# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
42# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
Berker Peksagfa3922c2015-07-31 04:11:29 +030043# getclasstree, getargvalues, formatargspec, formatargvalues,
Christian Heimes7131fd92008-02-19 14:21:46 +000044# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000045
Nick Coghlanf088e5e2008-12-14 11:50:48 +000046# NOTE: There are some additional tests relating to interaction with
47# zipimport in the test_zipimport_support test module.
48
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000049modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000050if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000051 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000052
Christian Heimesa3538eb2007-11-06 11:44:48 +000053# Normalize file names: on Windows, the case of file names of compiled
54# modules depends on the path used to start the python executable.
55modfile = normcase(modfile)
56
57def revise(filename, *args):
58 return (normcase(filename),) + args
59
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000060git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000061
larryhastingsf36ba122018-01-28 11:13:09 -080062
63def signatures_with_lexicographic_keyword_only_parameters():
64 """
65 Yields a whole bunch of functions with only keyword-only parameters,
66 where those parameters are always in lexicographically sorted order.
67 """
68 parameters = ['a', 'bar', 'c', 'delta', 'ephraim', 'magical', 'yoyo', 'z']
69 for i in range(1, 2**len(parameters)):
70 p = []
71 bit = 1
72 for j in range(len(parameters)):
73 if i & (bit << j):
74 p.append(parameters[j])
75 fn_text = "def foo(*, " + ", ".join(p) + "): pass"
76 symbols = {}
77 exec(fn_text, symbols, symbols)
78 yield symbols['foo']
79
80
81def unsorted_keyword_only_parameters_fn(*, throw, out, the, baby, with_,
82 the_, bathwater):
83 pass
84
85unsorted_keyword_only_parameters = 'throw out the baby with_ the_ bathwater'.split()
86
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000087class IsTestBase(unittest.TestCase):
88 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
89 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000090 inspect.ismodule, inspect.istraceback,
Yury Selivanov75445082015-05-11 22:57:16 -040091 inspect.isgenerator, inspect.isgeneratorfunction,
Yury Selivanoveb636452016-09-08 22:01:51 -070092 inspect.iscoroutine, inspect.iscoroutinefunction,
93 inspect.isasyncgen, inspect.isasyncgenfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000094
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000095 def istest(self, predicate, exp):
96 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000097 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000098
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000099 for other in self.predicates - set([predicate]):
Yury Selivanov75445082015-05-11 22:57:16 -0400100 if (predicate == inspect.isgeneratorfunction or \
Yury Selivanoveb636452016-09-08 22:01:51 -0700101 predicate == inspect.isasyncgenfunction or \
Yury Selivanov75445082015-05-11 22:57:16 -0400102 predicate == inspect.iscoroutinefunction) and \
Christian Heimes7131fd92008-02-19 14:21:46 +0000103 other == inspect.isfunction:
104 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000105 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000106
Christian Heimes7131fd92008-02-19 14:21:46 +0000107def generator_function_example(self):
108 for i in range(2):
109 yield i
110
Yury Selivanoveb636452016-09-08 22:01:51 -0700111async def async_generator_function_example(self):
112 async for i in range(2):
113 yield i
114
Yury Selivanov75445082015-05-11 22:57:16 -0400115async def coroutine_function_example(self):
116 return 'spam'
117
118@types.coroutine
119def gen_coroutine_function_example(self):
120 yield
121 return 'spam'
122
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000123class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +0000124
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000125 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200126 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000127 self.istest(inspect.isbuiltin, 'sys.exit')
128 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +0000129 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200130 try:
131 1/0
132 except:
133 tb = sys.exc_info()[2]
134 self.istest(inspect.isframe, 'tb.tb_frame')
135 self.istest(inspect.istraceback, 'tb')
136 if hasattr(types, 'GetSetDescriptorType'):
137 self.istest(inspect.isgetsetdescriptor,
138 'type(tb.tb_frame).f_locals')
139 else:
140 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
141 finally:
142 # Clear traceback and all the frames and local variables hanging to it.
143 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000144 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000145 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000146 self.istest(inspect.ismethod, 'git.argue')
Jeroen Demeyerfcef60f2019-04-02 16:03:42 +0200147 self.istest(inspect.ismethod, 'mod.custom_method')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000148 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000149 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000150 self.istest(inspect.isgenerator, '(x for x in range(2))')
151 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanoveb636452016-09-08 22:01:51 -0700152 self.istest(inspect.isasyncgen,
153 'async_generator_function_example(1)')
154 self.istest(inspect.isasyncgenfunction,
155 'async_generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400156
157 with warnings.catch_warnings():
158 warnings.simplefilter("ignore")
159 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
160 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
161
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000162 if hasattr(types, 'MemberDescriptorType'):
163 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
164 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000165 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000166
Yury Selivanov75445082015-05-11 22:57:16 -0400167 def test_iscoroutine(self):
Pablo Galindo7cd25432018-10-26 12:19:14 +0100168 async_gen_coro = async_generator_function_example(1)
Yury Selivanov75445082015-05-11 22:57:16 -0400169 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))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100174 self.assertFalse(
175 inspect.iscoroutinefunction(
176 functools.partial(functools.partial(
177 gen_coroutine_function_example))))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400178 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400179
180 self.assertTrue(
181 inspect.isgeneratorfunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100182 self.assertTrue(
183 inspect.isgeneratorfunction(
184 functools.partial(functools.partial(
185 gen_coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400186 self.assertTrue(inspect.isgenerator(gen_coro))
187
188 self.assertTrue(
189 inspect.iscoroutinefunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100190 self.assertTrue(
191 inspect.iscoroutinefunction(
192 functools.partial(functools.partial(
193 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400194 self.assertTrue(inspect.iscoroutine(coro))
195
196 self.assertFalse(
197 inspect.isgeneratorfunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100198 self.assertFalse(
199 inspect.isgeneratorfunction(
200 functools.partial(functools.partial(
201 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400202 self.assertFalse(inspect.isgenerator(coro))
203
Pablo Galindo7cd25432018-10-26 12:19:14 +0100204 self.assertTrue(
205 inspect.isasyncgenfunction(async_generator_function_example))
206 self.assertTrue(
207 inspect.isasyncgenfunction(
208 functools.partial(functools.partial(
209 async_generator_function_example))))
210 self.assertTrue(inspect.isasyncgen(async_gen_coro))
211
212 coro.close(); gen_coro.close(); # silence warnings
Yury Selivanov75445082015-05-11 22:57:16 -0400213
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400214 def test_isawaitable(self):
215 def gen(): yield
216 self.assertFalse(inspect.isawaitable(gen()))
217
218 coro = coroutine_function_example(1)
219 gen_coro = gen_coroutine_function_example(1)
220
221 self.assertTrue(inspect.isawaitable(coro))
222 self.assertTrue(inspect.isawaitable(gen_coro))
223
224 class Future:
225 def __await__():
226 pass
227 self.assertTrue(inspect.isawaitable(Future()))
228 self.assertFalse(inspect.isawaitable(Future))
229
230 class NotFuture: pass
231 not_fut = NotFuture()
232 not_fut.__await__ = lambda: None
233 self.assertFalse(inspect.isawaitable(not_fut))
234
235 coro.close(); gen_coro.close() # silence warnings
236
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000237 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000238 self.assertTrue(inspect.isroutine(mod.spam))
239 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000240
Benjamin Petersonc4656002009-01-17 22:41:18 +0000241 def test_isclass(self):
242 self.istest(inspect.isclass, 'mod.StupidGit')
243 self.assertTrue(inspect.isclass(list))
244
245 class CustomGetattr(object):
246 def __getattr__(self, attr):
247 return None
248 self.assertFalse(inspect.isclass(CustomGetattr()))
249
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000250 def test_get_slot_members(self):
251 class C(object):
252 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000253 x = C()
254 x.a = 42
255 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000256 self.assertIn('a', members)
257 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000258
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000259 def test_isabstract(self):
260 from abc import ABCMeta, abstractmethod
261
262 class AbstractClassExample(metaclass=ABCMeta):
263
264 @abstractmethod
265 def foo(self):
266 pass
267
268 class ClassExample(AbstractClassExample):
269 def foo(self):
270 pass
271
272 a = ClassExample()
273
274 # Test general behaviour.
275 self.assertTrue(inspect.isabstract(AbstractClassExample))
276 self.assertFalse(inspect.isabstract(ClassExample))
277 self.assertFalse(inspect.isabstract(a))
278 self.assertFalse(inspect.isabstract(int))
279 self.assertFalse(inspect.isabstract(5))
280
Natefcfe80e2017-04-24 10:06:15 -0700281 def test_isabstract_during_init_subclass(self):
282 from abc import ABCMeta, abstractmethod
283 isabstract_checks = []
284 class AbstractChecker(metaclass=ABCMeta):
285 def __init_subclass__(cls):
286 isabstract_checks.append(inspect.isabstract(cls))
287 class AbstractClassExample(AbstractChecker):
288 @abstractmethod
289 def foo(self):
290 pass
291 class ClassExample(AbstractClassExample):
292 def foo(self):
293 pass
294 self.assertEqual(isabstract_checks, [True, False])
295
296 isabstract_checks.clear()
297 class AbstractChild(AbstractClassExample):
298 pass
299 class AbstractGrandchild(AbstractChild):
300 pass
301 class ConcreteGrandchild(ClassExample):
302 pass
303 self.assertEqual(isabstract_checks, [True, True, False])
304
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000305
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000306class TestInterpreterStack(IsTestBase):
307 def __init__(self, *args, **kwargs):
308 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000309
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000310 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000311
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000312 def test_abuse_done(self):
313 self.istest(inspect.istraceback, 'git.ex[2]')
314 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000315
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000316 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000317 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000318 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000319 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000320 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000321 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000322 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000323 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000324 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000325 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400326 # Test named tuple fields
327 record = mod.st[0]
328 self.assertIs(record.frame, mod.fr)
329 self.assertEqual(record.lineno, 16)
330 self.assertEqual(record.filename, mod.__file__)
331 self.assertEqual(record.function, 'eggs')
332 self.assertIn('inspect.stack()', record.code_context[0])
333 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000334
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000335 def test_trace(self):
336 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000337 self.assertEqual(revise(*git.tr[0][1:]),
338 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
339 self.assertEqual(revise(*git.tr[1][1:]),
340 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
341 self.assertEqual(revise(*git.tr[2][1:]),
342 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000343
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000344 def test_frame(self):
345 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
346 self.assertEqual(args, ['x', 'y'])
347 self.assertEqual(varargs, None)
348 self.assertEqual(varkw, None)
349 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
350 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
351 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000352
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000353 def test_previous_frame(self):
354 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000355 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000356 self.assertEqual(varargs, 'g')
357 self.assertEqual(varkw, 'h')
358 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000359 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000360
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000361class GetSourceBase(unittest.TestCase):
362 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000363 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000364
Yury Selivanov6738b112015-05-16 10:10:21 -0400365 def setUp(self):
Inada Naokifb786922021-04-06 11:18:41 +0900366 with open(inspect.getsourcefile(self.fodderModule), encoding="utf-8") as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000367 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000368
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000369 def sourcerange(self, top, bottom):
370 lines = self.source.split("\n")
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700371 return "\n".join(lines[top-1:bottom]) + ("\n" if bottom else "")
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000372
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000373 def assertSourceEqual(self, obj, top, bottom):
374 self.assertEqual(inspect.getsource(obj),
375 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000376
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700377class SlotUser:
378 'Docstrings for __slots__'
379 __slots__ = {'power': 'measured in kilowatts',
380 'distance': 'measured in kilometers'}
381
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000382class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000383 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000384
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000385 def test_getclasses(self):
386 classes = inspect.getmembers(mod, inspect.isclass)
387 self.assertEqual(classes,
388 [('FesteringGob', mod.FesteringGob),
389 ('MalodorousPervert', mod.MalodorousPervert),
390 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300391 ('StupidGit', mod.StupidGit),
392 ('Tit', mod.MalodorousPervert),
Irit Katriel6e1eec72020-12-04 16:45:38 +0000393 ('WhichComments', mod.WhichComments),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300394 ])
395 tree = inspect.getclasstree([cls[1] for cls in classes])
396 self.assertEqual(tree,
397 [(object, ()),
398 [(mod.ParrotDroppings, (object,)),
399 [(mod.FesteringGob, (mod.MalodorousPervert,
400 mod.ParrotDroppings))
401 ],
402 (mod.StupidGit, (object,)),
403 [(mod.MalodorousPervert, (mod.StupidGit,)),
404 [(mod.FesteringGob, (mod.MalodorousPervert,
405 mod.ParrotDroppings))
406 ]
Irit Katriel6e1eec72020-12-04 16:45:38 +0000407 ],
408 (mod.WhichComments, (object,),)
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300409 ]
410 ])
411 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000412 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000413 [(object, ()),
414 [(mod.ParrotDroppings, (object,)),
415 (mod.StupidGit, (object,)),
416 [(mod.MalodorousPervert, (mod.StupidGit,)),
417 [(mod.FesteringGob, (mod.MalodorousPervert,
418 mod.ParrotDroppings))
419 ]
Irit Katriel6e1eec72020-12-04 16:45:38 +0000420 ],
421 (mod.WhichComments, (object,),)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000422 ]
423 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000424
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000425 def test_getfunctions(self):
426 functions = inspect.getmembers(mod, inspect.isfunction)
427 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300428 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000429 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000430
R. David Murray378c0cf2010-02-24 01:46:21 +0000431 @unittest.skipIf(sys.flags.optimize >= 2,
432 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000433 def test_getdoc(self):
434 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
435 self.assertEqual(inspect.getdoc(mod.StupidGit),
436 'A longer,\n\nindented\n\ndocstring.')
437 self.assertEqual(inspect.getdoc(git.abuse),
438 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700439 self.assertEqual(inspect.getdoc(SlotUser.power),
440 'measured in kilowatts')
441 self.assertEqual(inspect.getdoc(SlotUser.distance),
442 'measured in kilometers')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000443
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300444 @unittest.skipIf(sys.flags.optimize >= 2,
445 "Docstrings are omitted with -O2 and above")
446 def test_getdoc_inherited(self):
Serhiy Storchaka08b47c32020-05-18 20:25:07 +0300447 self.assertEqual(inspect.getdoc(mod.FesteringGob),
448 'A longer,\n\nindented\n\ndocstring.')
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300449 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
450 'Another\n\ndocstring\n\ncontaining\n\ntabs')
451 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
452 'Another\n\ndocstring\n\ncontaining\n\ntabs')
453 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
454 'The automatic gainsaying.')
455
456 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
457 def test_finddoc(self):
458 finddoc = inspect._finddoc
Serhiy Storchaka08b47c32020-05-18 20:25:07 +0300459 self.assertEqual(finddoc(int), int.__doc__)
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300460 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
461 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
462 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
463 self.assertEqual(finddoc(int.real), int.real.__doc__)
464
Georg Brandl0c77a822008-06-10 16:37:50 +0000465 def test_cleandoc(self):
466 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
467 'An\nindented\ndocstring.')
468
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000469 def test_getcomments(self):
470 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
471 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530472 self.assertEqual(inspect.getcomments(mod2.cls160), '# line 159\n')
Marco Buttu3f2155f2017-03-17 09:50:23 +0100473 # If the object source file is not available, return None.
474 co = compile('x=1', '_non_existing_filename.py', 'exec')
475 self.assertIsNone(inspect.getcomments(co))
476 # If the object has been defined in C, return None.
477 self.assertIsNone(inspect.getcomments(list))
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000478
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000479 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000480 # Check actual module
481 self.assertEqual(inspect.getmodule(mod), mod)
482 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000483 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000484 # Check a method (no __module__ attribute, falls back to filename)
485 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
486 # Do it again (check the caching isn't broken)
487 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
488 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000489 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000490 # Check filename override
491 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000492
Berker Peksagff0e3b72017-01-02 06:57:43 +0300493 def test_getframeinfo_get_first_line(self):
494 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
495 self.assertEqual(frame_info.code_context[0], "# line 1\n")
496 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
497
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000498 def test_getsource(self):
499 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200500 self.assertSourceEqual(mod.StupidGit, 21, 51)
501 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000502
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000503 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000504 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
505 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000506 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100507 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000508 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000509 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200510 try:
511 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
512 finally:
513 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000514
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000515 def test_getfile(self):
516 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000517
Philipp Ad407d2a2019-06-08 14:05:46 +0200518 def test_getfile_builtin_module(self):
519 with self.assertRaises(TypeError) as e:
520 inspect.getfile(sys)
521 self.assertTrue(str(e.exception).startswith('<module'))
522
523 def test_getfile_builtin_class(self):
524 with self.assertRaises(TypeError) as e:
525 inspect.getfile(int)
526 self.assertTrue(str(e.exception).startswith('<class'))
527
528 def test_getfile_builtin_function_or_method(self):
529 with self.assertRaises(TypeError) as e_abs:
530 inspect.getfile(abs)
531 self.assertIn('expected, got', str(e_abs.exception))
532 with self.assertRaises(TypeError) as e_append:
533 inspect.getfile(list.append)
534 self.assertIn('expected, got', str(e_append.exception))
535
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500536 def test_getfile_class_without_module(self):
537 class CM(type):
538 @property
539 def __module__(cls):
540 raise AttributeError
541 class C(metaclass=CM):
542 pass
543 with self.assertRaises(TypeError):
544 inspect.getfile(C)
545
Thomas Kluyvere968bc732017-10-24 13:42:36 +0100546 def test_getfile_broken_repr(self):
547 class ErrorRepr:
548 def __repr__(self):
549 raise Exception('xyz')
550 er = ErrorRepr()
551 with self.assertRaises(TypeError):
552 inspect.getfile(er)
553
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000554 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000555 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000556 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000557 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000558 m.__file__ = "<string>" # hopefully not a real filename...
559 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000560 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000561 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000562 del sys.modules[name]
563 inspect.getmodule(compile('a=10','','single'))
564
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500565 def test_proceed_with_fake_filename(self):
566 '''doctest monkeypatches linecache to enable inspection'''
567 fn, source = '<test>', 'def x(): pass\n'
568 getlines = linecache.getlines
569 def monkey(filename, module_globals=None):
570 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300571 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500572 else:
573 return getlines(filename, module_globals)
574 linecache.getlines = monkey
575 try:
576 ns = {}
577 exec(compile(source, fn, 'single'), ns)
578 inspect.getsource(ns["x"])
579 finally:
580 linecache.getlines = getlines
581
Antoine Pitroua8723a02015-04-15 00:41:29 +0200582 def test_getsource_on_code_object(self):
583 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
584
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700585class TestGettingSourceOfToplevelFrames(GetSourceBase):
586 fodderModule = mod
587
588 def test_range_toplevel_frame(self):
589 self.maxDiff = None
590 self.assertSourceEqual(mod.currentframe, 1, None)
591
592 def test_range_traceback_toplevel_frame(self):
593 self.assertSourceEqual(mod.tb, 1, None)
594
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000595class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000596 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000597
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000598 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000599 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000600
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000601 def test_replacing_decorator(self):
602 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000603
Yury Selivanov081bbf62014-09-26 17:34:54 -0400604 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200605 self.assertSourceEqual(mod2.real, 130, 132)
606
607 def test_decorator_with_lambda(self):
608 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400609
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000610class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000611 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000612 def test_oneline_lambda(self):
613 # Test inspect.getsource with a one-line lambda function.
614 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000615
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000616 def test_threeline_lambda(self):
617 # Test inspect.getsource with a three-line lambda function,
618 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000619 self.assertSourceEqual(mod2.tll, 28, 30)
620
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000621 def test_twoline_indented_lambda(self):
622 # Test inspect.getsource with a two-line lambda function,
623 # where the second line _is_ indented.
624 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000625
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000626 def test_onelinefunc(self):
627 # Test inspect.getsource with a regular one-line function.
628 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000629
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000630 def test_manyargs(self):
631 # Test inspect.getsource with a regular function where
632 # the arguments are on two lines and _not_ indented and
633 # the body on the second line with the last arguments.
634 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000635
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000636 def test_twolinefunc(self):
637 # Test inspect.getsource with a regular function where
638 # the body is on two lines, following the argument list and
639 # continued on the next line by a \\.
640 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000641
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000642 def test_lambda_in_list(self):
643 # Test inspect.getsource with a one-line lambda function
644 # defined in a list, indented.
645 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000646
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000647 def test_anonymous(self):
648 # Test inspect.getsource with a lambda function defined
649 # as argument to another function.
650 self.assertSourceEqual(mod2.anonymous, 55, 55)
651
Irit Katriel6e1eec72020-12-04 16:45:38 +0000652class TestBlockComments(GetSourceBase):
653 fodderModule = mod
654
655 def test_toplevel_class(self):
656 self.assertSourceEqual(mod.WhichComments, 96, 114)
657
658 def test_class_method(self):
659 self.assertSourceEqual(mod.WhichComments.f, 99, 104)
660
661 def test_class_async_method(self):
662 self.assertSourceEqual(mod.WhichComments.asyncf, 109, 112)
663
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000664class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000665 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000666
667 def test_with_comment(self):
668 self.assertSourceEqual(mod2.with_comment, 58, 59)
669
670 def test_multiline_sig(self):
671 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
672
Armin Rigodd5c0232005-09-25 11:45:45 +0000673 def test_nested_class(self):
674 self.assertSourceEqual(mod2.func69().func71, 71, 72)
675
676 def test_one_liner_followed_by_non_name(self):
677 self.assertSourceEqual(mod2.func77, 77, 77)
678
679 def test_one_liner_dedent_non_name(self):
680 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
681
682 def test_with_comment_instead_of_docstring(self):
683 self.assertSourceEqual(mod2.func88, 88, 90)
684
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000685 def test_method_in_dynamic_class(self):
686 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
687
R David Murray32562d72014-10-03 11:15:38 -0400688 # This should not skip for CPython, but might on a repackaged python where
689 # unicodedata is not an external module, or on pypy.
690 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
691 unicodedata.__file__.endswith('.py'),
692 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000693 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200694 self.assertRaises(OSError, inspect.getsource, unicodedata)
695 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000696
R. David Murraya1b37402010-06-17 02:04:29 +0000697 def test_findsource_code_in_linecache(self):
698 lines = ["x=1"]
699 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200700 self.assertRaises(OSError, inspect.findsource, co)
701 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000702 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200703 try:
704 self.assertEqual(inspect.findsource(co), (lines,0))
705 self.assertEqual(inspect.getsource(co), lines[0])
706 finally:
707 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000708
Ezio Melotti1b145922013-03-30 05:17:24 +0200709 def test_findsource_without_filename(self):
710 for fname in ['', '<string>']:
711 co = compile('x=1', fname, "exec")
712 self.assertRaises(IOError, inspect.findsource, co)
713 self.assertRaises(IOError, inspect.getsource, co)
714
Irit Katriel2e0760b2020-12-04 21:22:03 +0000715 def test_findsource_with_out_of_bounds_lineno(self):
716 mod_len = len(inspect.getsource(mod))
717 src = '\n' * 2* mod_len + "def f(): pass"
718 co = compile(src, mod.__file__, "exec")
719 g, l = {}, {}
720 eval(co, g, l)
721 func = l['f']
722 self.assertEqual(func.__code__.co_firstlineno, 1+2*mod_len)
723 with self.assertRaisesRegex(IOError, "lineno is out of bounds"):
724 inspect.findsource(func)
725
Antoine Pitroua8723a02015-04-15 00:41:29 +0200726 def test_getsource_on_method(self):
727 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
728
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300729 def test_nested_func(self):
730 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
731
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530732 def test_class_definition_in_multiline_string_definition(self):
733 self.assertSourceEqual(mod2.cls149, 149, 152)
734
735 def test_class_definition_in_multiline_comment(self):
736 self.assertSourceEqual(mod2.cls160, 160, 163)
737
738 def test_nested_class_definition_indented_string(self):
739 self.assertSourceEqual(mod2.cls173.cls175, 175, 176)
740
741 def test_nested_class_definition(self):
742 self.assertSourceEqual(mod2.cls183, 183, 188)
743 self.assertSourceEqual(mod2.cls183.cls185, 185, 188)
744
745 def test_class_decorator(self):
746 self.assertSourceEqual(mod2.cls196, 194, 201)
747 self.assertSourceEqual(mod2.cls196.cls200, 198, 201)
748
749 def test_class_inside_conditional(self):
750 self.assertSourceEqual(mod2.cls238, 238, 240)
751 self.assertSourceEqual(mod2.cls238.cls239, 239, 240)
752
753 def test_multiple_children_classes(self):
754 self.assertSourceEqual(mod2.cls203, 203, 209)
755 self.assertSourceEqual(mod2.cls203.cls204, 204, 206)
756 self.assertSourceEqual(mod2.cls203.cls204.cls205, 205, 206)
757 self.assertSourceEqual(mod2.cls203.cls207, 207, 209)
758 self.assertSourceEqual(mod2.cls203.cls207.cls205, 208, 209)
759
760 def test_nested_class_definition_inside_function(self):
761 self.assertSourceEqual(mod2.func212(), 213, 214)
762 self.assertSourceEqual(mod2.cls213, 218, 222)
763 self.assertSourceEqual(mod2.cls213().func219(), 220, 221)
764
765 def test_nested_class_definition_inside_async_function(self):
766 import asyncio
767 self.addCleanup(asyncio.set_event_loop_policy, None)
768 self.assertSourceEqual(asyncio.run(mod2.func225()), 226, 227)
769 self.assertSourceEqual(mod2.cls226, 231, 235)
770 self.assertSourceEqual(asyncio.run(mod2.cls226().func232()), 233, 234)
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300771
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000772class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400773 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000774 self.tempdir = TESTFN + '_dir'
775 os.mkdir(self.tempdir)
Inada Naokifb786922021-04-06 11:18:41 +0900776 with open(os.path.join(self.tempdir, 'inspect_fodder3%spy' % os.extsep),
777 'w', encoding='utf-8') as f:
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000778 f.write("class X:\n pass # No EOL")
779 with DirsOnSysPath(self.tempdir):
780 import inspect_fodder3 as mod3
781 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400782 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000783
784 def tearDown(self):
785 shutil.rmtree(self.tempdir)
786
787 def test_class(self):
788 self.assertSourceEqual(self.fodderModule.X, 1, 2)
789
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100790
791class _BrokenDataDescriptor(object):
792 """
793 A broken data descriptor. See bug #1785.
794 """
795 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700796 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100797
798 def __set__(*args):
799 raise RuntimeError
800
801 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700802 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100803
804
805class _BrokenMethodDescriptor(object):
806 """
807 A broken method descriptor. See bug #1785.
808 """
809 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700810 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100811
812 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700813 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100814
815
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000816# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000817def attrs_wo_objs(cls):
818 return [t[:3] for t in inspect.classify_class_attrs(cls)]
819
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100820
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000821class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000822 def test_newstyle_mro(self):
823 # The same w/ new-class MRO.
824 class A(object): pass
825 class B(A): pass
826 class C(A): pass
827 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000828
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000829 expected = (D, B, C, A, object)
830 got = inspect.getmro(D)
831 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000832
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500833 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
834 varkw_e=None, defaults_e=None, formatted=None):
Xtreak6d0b7472019-05-30 17:31:39 +0530835 with self.assertWarns(DeprecationWarning):
836 args, varargs, varkw, defaults = inspect.getargspec(routine)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500837 self.assertEqual(args, args_e)
838 self.assertEqual(varargs, varargs_e)
839 self.assertEqual(varkw, varkw_e)
840 self.assertEqual(defaults, defaults_e)
841 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530842 with self.assertWarns(DeprecationWarning):
843 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
844 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500845
Christian Heimes3795b532007-11-08 13:48:53 +0000846 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
847 varkw_e=None, defaults_e=None,
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100848 posonlyargs_e=[], kwonlyargs_e=[],
849 kwonlydefaults_e=None,
Christian Heimes3795b532007-11-08 13:48:53 +0000850 ann_e={}, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100851 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
852 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000853 self.assertEqual(args, args_e)
854 self.assertEqual(varargs, varargs_e)
855 self.assertEqual(varkw, varkw_e)
856 self.assertEqual(defaults, defaults_e)
857 self.assertEqual(kwonlyargs, kwonlyargs_e)
858 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
859 self.assertEqual(ann, ann_e)
860 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530861 with self.assertWarns(DeprecationWarning):
862 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
863 kwonlyargs, kwonlydefaults, ann),
864 formatted)
Christian Heimes3795b532007-11-08 13:48:53 +0000865
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500866 def test_getargspec(self):
867 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
868
Pablo Galindod5d2b452019-04-30 02:01:14 +0100869 self.assertArgSpecEquals(mod.spam,
870 ['a', 'b', 'c', 'd', 'e', 'f'],
871 'g', 'h', (3, 4, 5),
872 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500873
874 self.assertRaises(ValueError, self.assertArgSpecEquals,
875 mod2.keyworded, [])
876
877 self.assertRaises(ValueError, self.assertArgSpecEquals,
878 mod2.annotated, [])
879 self.assertRaises(ValueError, self.assertArgSpecEquals,
880 mod2.keyword_only_arg, [])
881
882
Christian Heimes3795b532007-11-08 13:48:53 +0000883 def test_getfullargspec(self):
884 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
885 kwonlyargs_e=['arg2'],
886 kwonlydefaults_e={'arg2':1},
887 formatted='(*arg1, arg2=1)')
888
889 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000890 ann_e={'arg1' : list},
Batuhan Taskaya044a1042020-10-06 23:03:02 +0300891 formatted="(arg1: list)")
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000892 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
893 kwonlyargs_e=['arg'],
894 formatted='(*, arg)')
895
Pablo Galindod5d2b452019-04-30 02:01:14 +0100896 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100897 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100898 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100899
900 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100901 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100902 varargs_e='args',
903 varkw_e='kwargs',
904 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100905 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100906
Pablo Galindod5d2b452019-04-30 02:01:14 +0100907 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100908 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100909 kwonlyargs_e=['e', 'f'],
910 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100911 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100912
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500913 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500914 # Issue 20684: low level introspection API must ignore __wrapped__
915 @functools.wraps(mod.spam)
916 def ham(x, y):
917 pass
918 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500919 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500920 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
921 self.assertFullArgSpecEquals(functools.partial(ham),
922 ['x', 'y'], formatted='(x, y)')
923 # Other variants
924 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500925 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
926 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500927 class C:
928 @functools.wraps(mod.spam)
929 def ham(self, x, y):
930 pass
931 pham = functools.partialmethod(ham)
932 @functools.wraps(mod.spam)
933 def __call__(self, x, y):
934 pass
935 check_method(C())
936 check_method(C.ham)
937 check_method(C().ham)
938 check_method(C.pham)
939 check_method(C().pham)
940
941 class C_new:
942 @functools.wraps(mod.spam)
943 def __new__(self, x, y):
944 pass
945 check_method(C_new)
946
947 class C_init:
948 @functools.wraps(mod.spam)
949 def __init__(self, x, y):
950 pass
951 check_method(C_init)
952
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500953 def test_getfullargspec_signature_attr(self):
954 def test():
955 pass
956 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
957 test.__signature__ = inspect.Signature(parameters=(spam_param,))
958
Pablo Galindod5d2b452019-04-30 02:01:14 +0100959 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500960
Yury Selivanov4cb93912014-01-29 11:54:12 -0500961 def test_getfullargspec_signature_annos(self):
962 def test(a:'spam') -> 'ham': pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100963 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500964 self.assertEqual(test.__annotations__, spec.annotations)
965
966 def test(): pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100967 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500968 self.assertEqual(test.__annotations__, spec.annotations)
969
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500970 @unittest.skipIf(MISSING_C_DOCSTRINGS,
971 "Signature information for builtins requires docstrings")
972 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100973 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
974 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500975
Pablo Galindod5d2b452019-04-30 02:01:14 +0100976 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
977 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500978
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500979 self.assertFullArgSpecEquals(
980 os.stat,
981 args_e=['path'],
982 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
983 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
984 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
985
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200986 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500987 @unittest.skipIf(MISSING_C_DOCSTRINGS,
988 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800989 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200990 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500991 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindoaee19f52019-05-16 21:08:15 +0100992 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500993 self.assertEqual(spec.defaults[0], 'avocado')
994
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200995 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500996 @unittest.skipIf(MISSING_C_DOCSTRINGS,
997 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800998 def test_getfullargspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200999 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -05001000 builtin = _testcapi.docstring_no_signature
Pablo Galindoaee19f52019-05-16 21:08:15 +01001001 with self.assertRaises(TypeError):
1002 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +00001003
larryhastingsf36ba122018-01-28 11:13:09 -08001004 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
1005 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindoaee19f52019-05-16 21:08:15 +01001006 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -08001007 l = list(signature.kwonlyargs)
1008 sorted_l = sorted(l)
1009 self.assertTrue(l)
1010 self.assertEqual(l, sorted_l)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001011 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -08001012 l = list(signature.kwonlyargs)
1013 self.assertEqual(l, unsorted_keyword_only_parameters)
1014
Yury Selivanov37dc2b22016-01-11 15:15:01 -05001015 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001016 class A(object):
1017 def m(self):
1018 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -05001019 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +00001020
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001021 def test_classify_newstyle(self):
1022 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +00001023
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001024 def s(): pass
1025 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +00001026
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001027 def c(cls): pass
1028 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +00001029
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001030 def getp(self): pass
1031 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +00001032
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001033 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001034
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001035 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001036
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001037 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +00001038
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001039 dd = _BrokenDataDescriptor()
1040 md = _BrokenMethodDescriptor()
1041
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001042 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001043
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001044 self.assertIn(('__new__', 'static method', object), attrs,
1045 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001046 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
1047
Benjamin Peterson577473f2010-01-19 00:09:57 +00001048 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1049 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1050 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001051 self.assertIn(('m', 'method', A), attrs,
1052 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001053 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1054 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001055 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1056 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001057
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001058 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001059
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001060 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001061
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001062 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001063 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1064 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1065 self.assertIn(('p', 'property', A), attrs, 'missing property')
1066 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1067 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1068 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001069 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1070 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001071
1072
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001073 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001074
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001075 def m(self): pass
1076 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001077
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001078 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001079 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1080 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1081 self.assertIn(('p', 'property', A), attrs, 'missing property')
1082 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
1083 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1084 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001085 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1086 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001087
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001088 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001089
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001090 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001091
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001092 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001093 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1094 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1095 self.assertIn(('p', 'property', A), attrs, 'missing property')
1096 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1097 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1098 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001099 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1100 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1101
1102 def test_classify_builtin_types(self):
1103 # Simple sanity check that all built-in types can have their
1104 # attributes classified.
1105 for name in dir(__builtins__):
1106 builtin = getattr(__builtins__, name)
1107 if isinstance(builtin, type):
1108 inspect.classify_class_attrs(builtin)
1109
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001110 attrs = attrs_wo_objs(bool)
1111 self.assertIn(('__new__', 'static method', bool), attrs,
1112 'missing __new__')
1113 self.assertIn(('from_bytes', 'class method', int), attrs,
1114 'missing class method')
1115 self.assertIn(('to_bytes', 'method', int), attrs,
1116 'missing plain method')
1117 self.assertIn(('__add__', 'method', int), attrs,
1118 'missing plain method')
1119 self.assertIn(('__and__', 'method', bool), attrs,
1120 'missing plain method')
1121
Ethan Furman63c141c2013-10-18 00:27:39 -07001122 def test_classify_DynamicClassAttribute(self):
1123 class Meta(type):
1124 def __getattr__(self, name):
1125 if name == 'ham':
1126 return 'spam'
1127 return super().__getattr__(name)
1128 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001129 @types.DynamicClassAttribute
1130 def ham(self):
1131 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001132 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1133 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001134 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001135 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1136
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001137 def test_classify_overrides_bool(self):
1138 class NoBool(object):
1139 def __eq__(self, other):
1140 return NoBool()
1141
1142 def __bool__(self):
1143 raise NotImplementedError(
1144 "This object does not specify a boolean value")
1145
1146 class HasNB(object):
1147 dd = NoBool()
1148
1149 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1150 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1151
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001152 def test_classify_metaclass_class_attribute(self):
1153 class Meta(type):
1154 fish = 'slap'
1155 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001156 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001157 class Class(metaclass=Meta):
1158 pass
1159 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1160 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1161
Ethan Furman63c141c2013-10-18 00:27:39 -07001162 def test_classify_VirtualAttribute(self):
1163 class Meta(type):
1164 def __dir__(cls):
1165 return ['__class__', '__module__', '__name__', 'BOOM']
1166 def __getattr__(self, name):
1167 if name =='BOOM':
1168 return 42
1169 return super().__getattr(name)
1170 class Class(metaclass=Meta):
1171 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001172 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001173 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1174
1175 def test_classify_VirtualAttribute_multi_classes(self):
1176 class Meta1(type):
1177 def __dir__(cls):
1178 return ['__class__', '__module__', '__name__', 'one']
1179 def __getattr__(self, name):
1180 if name =='one':
1181 return 1
1182 return super().__getattr__(name)
1183 class Meta2(type):
1184 def __dir__(cls):
1185 return ['__class__', '__module__', '__name__', 'two']
1186 def __getattr__(self, name):
1187 if name =='two':
1188 return 2
1189 return super().__getattr__(name)
1190 class Meta3(Meta1, Meta2):
1191 def __dir__(cls):
1192 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1193 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1194 def __getattr__(self, name):
1195 if name =='three':
1196 return 3
1197 return super().__getattr__(name)
1198 class Class1(metaclass=Meta1):
1199 pass
1200 class Class2(Class1, metaclass=Meta3):
1201 pass
1202
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001203 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1204 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1205 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001206 cca = inspect.classify_class_attrs(Class2)
1207 for sf in (should_find1, should_find2, should_find3):
1208 self.assertIn(sf, cca)
1209
1210 def test_classify_class_attrs_with_buggy_dir(self):
1211 class M(type):
1212 def __dir__(cls):
1213 return ['__class__', '__name__', 'missing']
1214 class C(metaclass=M):
1215 pass
1216 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1217 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001218
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001219 def test_getmembers_descriptors(self):
1220 class A(object):
1221 dd = _BrokenDataDescriptor()
1222 md = _BrokenMethodDescriptor()
1223
1224 def pred_wrapper(pred):
1225 # A quick'n'dirty way to discard standard attributes of new-style
1226 # classes.
1227 class Empty(object):
1228 pass
1229 def wrapped(x):
1230 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1231 return False
1232 return pred(x)
1233 return wrapped
1234
1235 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1236 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1237
1238 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1239 [('md', A.__dict__['md'])])
1240 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1241 [('dd', A.__dict__['dd'])])
1242
1243 class B(A):
1244 pass
1245
1246 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1247 [('md', A.__dict__['md'])])
1248 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1249 [('dd', A.__dict__['dd'])])
1250
Antoine Pitrou0c603812012-01-18 17:40:18 +01001251 def test_getmembers_method(self):
1252 class B:
1253 def f(self):
1254 pass
1255
1256 self.assertIn(('f', B.f), inspect.getmembers(B))
1257 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1258 b = B()
1259 self.assertIn(('f', b.f), inspect.getmembers(b))
1260 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1261
Ethan Furmane03ea372013-09-25 07:14:41 -07001262 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001263 class M(type):
1264 def __getattr__(cls, name):
1265 if name == 'eggs':
1266 return 'scrambled'
1267 return super().__getattr__(name)
1268 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001269 @types.DynamicClassAttribute
1270 def eggs(self):
1271 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001272 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1273 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1274
1275 def test_getmembers_with_buggy_dir(self):
1276 class M(type):
1277 def __dir__(cls):
1278 return ['__class__', '__name__', 'missing']
1279 class C(metaclass=M):
1280 pass
1281 attrs = [a[0] for a in inspect.getmembers(C)]
1282 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001283
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001284class TestIsDataDescriptor(unittest.TestCase):
1285
1286 def test_custom_descriptors(self):
1287 class NonDataDescriptor:
1288 def __get__(self, value, type=None): pass
1289 class DataDescriptor0:
1290 def __set__(self, name, value): pass
1291 class DataDescriptor1:
1292 def __delete__(self, name): pass
1293 class DataDescriptor2:
1294 __set__ = None
1295 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1296 'class with only __get__ not a data descriptor')
1297 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1298 'class with __set__ is a data descriptor')
1299 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1300 'class with __delete__ is a data descriptor')
1301 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1302 'class with __set__ = None is a data descriptor')
1303
1304 def test_slot(self):
1305 class Slotted:
1306 __slots__ = 'foo',
1307 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1308 'a slot is a data descriptor')
1309
1310 def test_property(self):
1311 class Propertied:
1312 @property
1313 def a_property(self):
1314 pass
1315 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1316 'a property is a data descriptor')
1317
1318 def test_functions(self):
1319 class Test(object):
1320 def instance_method(self): pass
1321 @classmethod
1322 def class_method(cls): pass
1323 @staticmethod
1324 def static_method(): pass
1325 def function():
1326 pass
1327 a_lambda = lambda: None
1328 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1329 'a instance method is not a data descriptor')
1330 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1331 'a class method is not a data descriptor')
1332 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1333 'a static method is not a data descriptor')
1334 self.assertFalse(inspect.isdatadescriptor(function),
1335 'a function is not a data descriptor')
1336 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1337 'a lambda is not a data descriptor')
1338
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001339
Nick Coghlan2f92e542012-06-23 19:39:55 +10001340_global_ref = object()
1341class TestGetClosureVars(unittest.TestCase):
1342
1343 def test_name_resolution(self):
1344 # Basic test of the 4 different resolution mechanisms
1345 def f(nonlocal_ref):
1346 def g(local_ref):
1347 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1348 return g
1349 _arg = object()
1350 nonlocal_vars = {"nonlocal_ref": _arg}
1351 global_vars = {"_global_ref": _global_ref}
1352 builtin_vars = {"print": print}
1353 unbound_names = {"unbound_ref"}
1354 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1355 builtin_vars, unbound_names)
1356 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1357
1358 def test_generator_closure(self):
1359 def f(nonlocal_ref):
1360 def g(local_ref):
1361 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1362 yield
1363 return g
1364 _arg = object()
1365 nonlocal_vars = {"nonlocal_ref": _arg}
1366 global_vars = {"_global_ref": _global_ref}
1367 builtin_vars = {"print": print}
1368 unbound_names = {"unbound_ref"}
1369 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1370 builtin_vars, unbound_names)
1371 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1372
1373 def test_method_closure(self):
1374 class C:
1375 def f(self, nonlocal_ref):
1376 def g(local_ref):
1377 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1378 return g
1379 _arg = object()
1380 nonlocal_vars = {"nonlocal_ref": _arg}
1381 global_vars = {"_global_ref": _global_ref}
1382 builtin_vars = {"print": print}
1383 unbound_names = {"unbound_ref"}
1384 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1385 builtin_vars, unbound_names)
1386 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1387
1388 def test_nonlocal_vars(self):
1389 # More complex tests of nonlocal resolution
1390 def _nonlocal_vars(f):
1391 return inspect.getclosurevars(f).nonlocals
1392
1393 def make_adder(x):
1394 def add(y):
1395 return x + y
1396 return add
1397
1398 def curry(func, arg1):
1399 return lambda arg2: func(arg1, arg2)
1400
1401 def less_than(a, b):
1402 return a < b
1403
1404 # The infamous Y combinator.
1405 def Y(le):
1406 def g(f):
1407 return le(lambda x: f(f)(x))
1408 Y.g_ref = g
1409 return g(g)
1410
1411 def check_y_combinator(func):
1412 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1413
1414 inc = make_adder(1)
1415 add_two = make_adder(2)
1416 greater_than_five = curry(less_than, 5)
1417
1418 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1419 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1420 self.assertEqual(_nonlocal_vars(greater_than_five),
1421 {'arg1': 5, 'func': less_than})
1422 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1423 {'x': 3})
1424 Y(check_y_combinator)
1425
1426 def test_getclosurevars_empty(self):
1427 def foo(): pass
1428 _empty = inspect.ClosureVars({}, {}, {}, set())
1429 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1430 self.assertEqual(inspect.getclosurevars(foo), _empty)
1431
1432 def test_getclosurevars_error(self):
1433 class T: pass
1434 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1435 self.assertRaises(TypeError, inspect.getclosurevars, list)
1436 self.assertRaises(TypeError, inspect.getclosurevars, {})
1437
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001438 def _private_globals(self):
1439 code = """def f(): print(path)"""
1440 ns = {}
1441 exec(code, ns)
1442 return ns["f"], ns
1443
1444 def test_builtins_fallback(self):
1445 f, ns = self._private_globals()
1446 ns.pop("__builtins__", None)
1447 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1448 self.assertEqual(inspect.getclosurevars(f), expected)
1449
1450 def test_builtins_as_dict(self):
1451 f, ns = self._private_globals()
1452 ns["__builtins__"] = {"path":1}
1453 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1454 self.assertEqual(inspect.getclosurevars(f), expected)
1455
1456 def test_builtins_as_module(self):
1457 f, ns = self._private_globals()
1458 ns["__builtins__"] = os
1459 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1460 self.assertEqual(inspect.getclosurevars(f), expected)
1461
Nick Coghlan2f92e542012-06-23 19:39:55 +10001462
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001463class TestGetcallargsFunctions(unittest.TestCase):
1464
1465 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1466 locs = dict(locs or {}, func=func)
1467 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001468 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1469 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001470 self.assertEqual(r1, r2)
1471
1472 def assertEqualException(self, func, call_param_string, locs=None):
1473 locs = dict(locs or {}, func=func)
1474 try:
1475 eval('func(%s)' % call_param_string, None, locs)
1476 except Exception as e:
1477 ex1 = e
1478 else:
1479 self.fail('Exception not raised')
1480 try:
Pablo Galindoaee19f52019-05-16 21:08:15 +01001481 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1482 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001483 except Exception as e:
1484 ex2 = e
1485 else:
1486 self.fail('Exception not raised')
1487 self.assertIs(type(ex1), type(ex2))
1488 self.assertEqual(str(ex1), str(ex2))
1489 del ex1, ex2
1490
1491 def makeCallable(self, signature):
1492 """Create a function that returns its locals()"""
1493 code = "lambda %s: locals()"
1494 return eval(code % signature)
1495
1496 def test_plain(self):
1497 f = self.makeCallable('a, b=1')
1498 self.assertEqualCallArgs(f, '2')
1499 self.assertEqualCallArgs(f, '2, 3')
1500 self.assertEqualCallArgs(f, 'a=2')
1501 self.assertEqualCallArgs(f, 'b=3, a=2')
1502 self.assertEqualCallArgs(f, '2, b=3')
1503 # expand *iterable / **mapping
1504 self.assertEqualCallArgs(f, '*(2,)')
1505 self.assertEqualCallArgs(f, '*[2]')
1506 self.assertEqualCallArgs(f, '*(2, 3)')
1507 self.assertEqualCallArgs(f, '*[2, 3]')
1508 self.assertEqualCallArgs(f, '**{"a":2}')
1509 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1510 self.assertEqualCallArgs(f, '2, **{"b":3}')
1511 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1512 # expand UserList / UserDict
1513 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1514 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1515 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1516 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1517 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1518
1519 def test_varargs(self):
1520 f = self.makeCallable('a, b=1, *c')
1521 self.assertEqualCallArgs(f, '2')
1522 self.assertEqualCallArgs(f, '2, 3')
1523 self.assertEqualCallArgs(f, '2, 3, 4')
1524 self.assertEqualCallArgs(f, '*(2,3,4)')
1525 self.assertEqualCallArgs(f, '2, *[3,4]')
1526 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1527
1528 def test_varkw(self):
1529 f = self.makeCallable('a, b=1, **c')
1530 self.assertEqualCallArgs(f, 'a=2')
1531 self.assertEqualCallArgs(f, '2, b=3, c=4')
1532 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1533 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1534 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1535 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1536 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1537 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1538 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1539
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001540 def test_varkw_only(self):
1541 # issue11256:
1542 f = self.makeCallable('**c')
1543 self.assertEqualCallArgs(f, '')
1544 self.assertEqualCallArgs(f, 'a=1')
1545 self.assertEqualCallArgs(f, 'a=1, b=2')
1546 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1547 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1548 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1549
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001550 def test_keyword_only(self):
1551 f = self.makeCallable('a=3, *, c, d=2')
1552 self.assertEqualCallArgs(f, 'c=3')
1553 self.assertEqualCallArgs(f, 'c=3, a=3')
1554 self.assertEqualCallArgs(f, 'a=2, c=4')
1555 self.assertEqualCallArgs(f, '4, c=4')
1556 self.assertEqualException(f, '')
1557 self.assertEqualException(f, '3')
1558 self.assertEqualException(f, 'a=3')
1559 self.assertEqualException(f, 'd=4')
1560
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001561 f = self.makeCallable('*, c, d=2')
1562 self.assertEqualCallArgs(f, 'c=3')
1563 self.assertEqualCallArgs(f, 'c=3, d=4')
1564 self.assertEqualCallArgs(f, 'd=4, c=3')
1565
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001566 def test_multiple_features(self):
1567 f = self.makeCallable('a, b=2, *f, **g')
1568 self.assertEqualCallArgs(f, '2, 3, 7')
1569 self.assertEqualCallArgs(f, '2, 3, x=8')
1570 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1571 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1572 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1573 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1574 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1575 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1576 '(4,[5,6])]), **collections.UserDict('
1577 'y=9, z=10)')
1578
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001579 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1580 self.assertEqualCallArgs(f, '2, 3, x=8')
1581 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1582 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1583 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1584 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1585 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1586 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1587 '(4,[5,6])]), q=0, **collections.UserDict('
1588 'y=9, z=10)')
1589
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001590 def test_errors(self):
1591 f0 = self.makeCallable('')
1592 f1 = self.makeCallable('a, b')
1593 f2 = self.makeCallable('a, b=1')
1594 # f0 takes no arguments
1595 self.assertEqualException(f0, '1')
1596 self.assertEqualException(f0, 'x=1')
1597 self.assertEqualException(f0, '1,x=1')
1598 # f1 takes exactly 2 arguments
1599 self.assertEqualException(f1, '')
1600 self.assertEqualException(f1, '1')
1601 self.assertEqualException(f1, 'a=2')
1602 self.assertEqualException(f1, 'b=3')
1603 # f2 takes at least 1 argument
1604 self.assertEqualException(f2, '')
1605 self.assertEqualException(f2, 'b=3')
1606 for f in f1, f2:
1607 # f1/f2 takes exactly/at most 2 arguments
1608 self.assertEqualException(f, '2, 3, 4')
1609 self.assertEqualException(f, '1, 2, 3, a=1')
1610 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001611 # XXX: success of this one depends on dict order
1612 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001613 # f got an unexpected keyword argument
1614 self.assertEqualException(f, 'c=2')
1615 self.assertEqualException(f, '2, c=3')
1616 self.assertEqualException(f, '2, 3, c=4')
1617 self.assertEqualException(f, '2, c=4, b=3')
1618 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1619 # f got multiple values for keyword argument
1620 self.assertEqualException(f, '1, a=2')
1621 self.assertEqualException(f, '1, **{"a":2}')
1622 self.assertEqualException(f, '1, 2, b=3')
1623 # XXX: Python inconsistency
1624 # - for functions and bound methods: unexpected keyword 'c'
1625 # - for unbound methods: multiple values for keyword 'a'
1626 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001627 # issue11256:
1628 f3 = self.makeCallable('**c')
1629 self.assertEqualException(f3, '1, 2')
1630 self.assertEqualException(f3, '1, 2, a=1, b=2')
1631 f4 = self.makeCallable('*, a, b=0')
1632 self.assertEqualException(f3, '1, 2')
1633 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001634
Yury Selivanov875df202014-03-27 18:23:03 -04001635 # issue #20816: getcallargs() fails to iterate over non-existent
1636 # kwonlydefaults and raises a wrong TypeError
1637 def f5(*, a): pass
1638 with self.assertRaisesRegex(TypeError,
1639 'missing 1 required keyword-only'):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001640 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001641
1642
Yury Selivanovdccfa132014-03-27 18:42:52 -04001643 # issue20817:
1644 def f6(a, b, c):
1645 pass
1646 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001647 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001648
Dong-hee Naa9cab432018-05-30 00:04:08 +09001649 # bpo-33197
1650 with self.assertRaisesRegex(ValueError,
1651 'variadic keyword parameters cannot'
1652 ' have default values'):
1653 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1654 default=42)
1655 with self.assertRaisesRegex(ValueError,
1656 "value 5 is not a valid Parameter.kind"):
1657 inspect.Parameter("bar", kind=5, default=42)
1658
1659 with self.assertRaisesRegex(TypeError,
1660 'name must be a str, not a int'):
1661 inspect.Parameter(123, kind=4)
1662
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001663class TestGetcallargsMethods(TestGetcallargsFunctions):
1664
1665 def setUp(self):
1666 class Foo(object):
1667 pass
1668 self.cls = Foo
1669 self.inst = Foo()
1670
1671 def makeCallable(self, signature):
1672 assert 'self' not in signature
1673 mk = super(TestGetcallargsMethods, self).makeCallable
1674 self.cls.method = mk('self, ' + signature)
1675 return self.inst.method
1676
1677class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1678
1679 def makeCallable(self, signature):
1680 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1681 return self.cls.method
1682
1683 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1684 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1685 *self._getAssertEqualParams(func, call_params_string, locs))
1686
1687 def assertEqualException(self, func, call_params_string, locs=None):
1688 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1689 *self._getAssertEqualParams(func, call_params_string, locs))
1690
1691 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1692 assert 'inst' not in call_params_string
1693 locs = dict(locs or {}, inst=self.inst)
1694 return (func, 'inst,' + call_params_string, locs)
1695
Michael Foord95fc51d2010-11-20 15:07:30 +00001696
1697class TestGetattrStatic(unittest.TestCase):
1698
1699 def test_basic(self):
1700 class Thing(object):
1701 x = object()
1702
1703 thing = Thing()
1704 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1705 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1706 with self.assertRaises(AttributeError):
1707 inspect.getattr_static(thing, 'y')
1708
1709 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1710
1711 def test_inherited(self):
1712 class Thing(object):
1713 x = object()
1714 class OtherThing(Thing):
1715 pass
1716
1717 something = OtherThing()
1718 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1719
1720 def test_instance_attr(self):
1721 class Thing(object):
1722 x = 2
1723 def __init__(self, x):
1724 self.x = x
1725 thing = Thing(3)
1726 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1727 del thing.x
1728 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1729
1730 def test_property(self):
1731 class Thing(object):
1732 @property
1733 def x(self):
1734 raise AttributeError("I'm pretending not to exist")
1735 thing = Thing()
1736 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1737
Ezio Melotti75cbd732011-04-28 00:59:29 +03001738 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001739 class descriptor(object):
1740 def __get__(*_):
1741 raise AttributeError("I'm pretending not to exist")
1742 desc = descriptor()
1743 class Thing(object):
1744 x = desc
1745 thing = Thing()
1746 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1747
1748 def test_classAttribute(self):
1749 class Thing(object):
1750 x = object()
1751
1752 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1753
Ethan Furmane03ea372013-09-25 07:14:41 -07001754 def test_classVirtualAttribute(self):
1755 class Thing(object):
1756 @types.DynamicClassAttribute
1757 def x(self):
1758 return self._x
1759 _x = object()
1760
1761 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1762
Michael Foord95fc51d2010-11-20 15:07:30 +00001763 def test_inherited_classattribute(self):
1764 class Thing(object):
1765 x = object()
1766 class OtherThing(Thing):
1767 pass
1768
1769 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1770
1771 def test_slots(self):
1772 class Thing(object):
1773 y = 'bar'
1774 __slots__ = ['x']
1775 def __init__(self):
1776 self.x = 'foo'
1777 thing = Thing()
1778 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1779 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1780
1781 del thing.x
1782 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1783
1784 def test_metaclass(self):
1785 class meta(type):
1786 attr = 'foo'
1787 class Thing(object, metaclass=meta):
1788 pass
1789 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1790
1791 class sub(meta):
1792 pass
1793 class OtherThing(object, metaclass=sub):
1794 x = 3
1795 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1796
1797 class OtherOtherThing(OtherThing):
1798 pass
1799 # this test is odd, but it was added as it exposed a bug
1800 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1801
1802 def test_no_dict_no_slots(self):
1803 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1804 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1805
1806 def test_no_dict_no_slots_instance_member(self):
1807 # returns descriptor
Inada Naokifb786922021-04-06 11:18:41 +09001808 with open(__file__, encoding='utf-8') as handle:
Michael Foord95fc51d2010-11-20 15:07:30 +00001809 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1810
1811 def test_inherited_slots(self):
1812 # returns descriptor
1813 class Thing(object):
1814 __slots__ = ['x']
1815 def __init__(self):
1816 self.x = 'foo'
1817
1818 class OtherThing(Thing):
1819 pass
1820 # it would be nice if this worked...
1821 # we get the descriptor instead of the instance attribute
1822 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1823
1824 def test_descriptor(self):
1825 class descriptor(object):
1826 def __get__(self, instance, owner):
1827 return 3
1828 class Foo(object):
1829 d = descriptor()
1830
1831 foo = Foo()
1832
1833 # for a non data descriptor we return the instance attribute
1834 foo.__dict__['d'] = 1
1835 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1836
Mike53f7a7c2017-12-14 14:04:53 +03001837 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001838 # descriptor
1839 descriptor.__set__ = lambda s, i, v: None
1840 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1841
1842
1843 def test_metaclass_with_descriptor(self):
1844 class descriptor(object):
1845 def __get__(self, instance, owner):
1846 return 3
1847 class meta(type):
1848 d = descriptor()
1849 class Thing(object, metaclass=meta):
1850 pass
1851 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1852
1853
Michael Foordcc7ebb82010-11-20 16:20:16 +00001854 def test_class_as_property(self):
1855 class Base(object):
1856 foo = 3
1857
1858 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001859 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001860 @property
1861 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001862 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001863 return object
1864
Michael Foord35184ed2010-11-20 16:58:30 +00001865 instance = Something()
1866 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1867 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001868 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1869
Michael Foorde5162652010-11-20 16:40:44 +00001870 def test_mro_as_property(self):
1871 class Meta(type):
1872 @property
1873 def __mro__(self):
1874 return (object,)
1875
1876 class Base(object):
1877 foo = 3
1878
1879 class Something(Base, metaclass=Meta):
1880 pass
1881
1882 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1883 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1884
Michael Foorddcebe0f2011-03-15 19:20:44 -04001885 def test_dict_as_property(self):
1886 test = self
1887 test.called = False
1888
1889 class Foo(dict):
1890 a = 3
1891 @property
1892 def __dict__(self):
1893 test.called = True
1894 return {}
1895
1896 foo = Foo()
1897 foo.a = 4
1898 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1899 self.assertFalse(test.called)
1900
1901 def test_custom_object_dict(self):
1902 test = self
1903 test.called = False
1904
1905 class Custom(dict):
1906 def get(self, key, default=None):
1907 test.called = True
1908 super().get(key, default)
1909
1910 class Foo(object):
1911 a = 3
1912 foo = Foo()
1913 foo.__dict__ = Custom()
1914 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1915 self.assertFalse(test.called)
1916
1917 def test_metaclass_dict_as_property(self):
1918 class Meta(type):
1919 @property
1920 def __dict__(self):
1921 self.executed = True
1922
1923 class Thing(metaclass=Meta):
1924 executed = False
1925
1926 def __init__(self):
1927 self.spam = 42
1928
1929 instance = Thing()
1930 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1931 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001932
Michael Foorda51623b2011-12-18 22:01:40 +00001933 def test_module(self):
1934 sentinel = object()
1935 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1936 sentinel)
1937
Michael Foord3ba95f82011-12-22 01:13:37 +00001938 def test_metaclass_with_metaclass_with_dict_as_property(self):
1939 class MetaMeta(type):
1940 @property
1941 def __dict__(self):
1942 self.executed = True
1943 return dict(spam=42)
1944
1945 class Meta(type, metaclass=MetaMeta):
1946 executed = False
1947
1948 class Thing(metaclass=Meta):
1949 pass
1950
1951 with self.assertRaises(AttributeError):
1952 inspect.getattr_static(Thing, "spam")
1953 self.assertFalse(Thing.executed)
1954
Nick Coghlane0f04652010-11-21 03:44:04 +00001955class TestGetGeneratorState(unittest.TestCase):
1956
1957 def setUp(self):
1958 def number_generator():
1959 for number in range(5):
1960 yield number
1961 self.generator = number_generator()
1962
1963 def _generatorstate(self):
1964 return inspect.getgeneratorstate(self.generator)
1965
1966 def test_created(self):
1967 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1968
1969 def test_suspended(self):
1970 next(self.generator)
1971 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1972
1973 def test_closed_after_exhaustion(self):
1974 for i in self.generator:
1975 pass
1976 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1977
1978 def test_closed_after_immediate_exception(self):
1979 with self.assertRaises(RuntimeError):
1980 self.generator.throw(RuntimeError)
1981 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1982
1983 def test_running(self):
1984 # As mentioned on issue #10220, checking for the RUNNING state only
1985 # makes sense inside the generator itself.
1986 # The following generator checks for this by using the closure's
1987 # reference to self and the generator state checking helper method
1988 def running_check_generator():
1989 for number in range(5):
1990 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1991 yield number
1992 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1993 self.generator = running_check_generator()
1994 # Running up to the first yield
1995 next(self.generator)
1996 # Running after the first yield
1997 next(self.generator)
1998
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001999 def test_easy_debugging(self):
2000 # repr() and str() of a generator state should contain the state name
2001 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
2002 for name in names:
2003 state = getattr(inspect, name)
2004 self.assertIn(name, repr(state))
2005 self.assertIn(name, str(state))
2006
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10002007 def test_getgeneratorlocals(self):
2008 def each(lst, a=None):
2009 b=(1, 2, 3)
2010 for v in lst:
2011 if v == 3:
2012 c = 12
2013 yield v
2014
2015 numbers = each([1, 2, 3])
2016 self.assertEqual(inspect.getgeneratorlocals(numbers),
2017 {'a': None, 'lst': [1, 2, 3]})
2018 next(numbers)
2019 self.assertEqual(inspect.getgeneratorlocals(numbers),
2020 {'a': None, 'lst': [1, 2, 3], 'v': 1,
2021 'b': (1, 2, 3)})
2022 next(numbers)
2023 self.assertEqual(inspect.getgeneratorlocals(numbers),
2024 {'a': None, 'lst': [1, 2, 3], 'v': 2,
2025 'b': (1, 2, 3)})
2026 next(numbers)
2027 self.assertEqual(inspect.getgeneratorlocals(numbers),
2028 {'a': None, 'lst': [1, 2, 3], 'v': 3,
2029 'b': (1, 2, 3), 'c': 12})
2030 try:
2031 next(numbers)
2032 except StopIteration:
2033 pass
2034 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
2035
2036 def test_getgeneratorlocals_empty(self):
2037 def yield_one():
2038 yield 1
2039 one = yield_one()
2040 self.assertEqual(inspect.getgeneratorlocals(one), {})
2041 try:
2042 next(one)
2043 except StopIteration:
2044 pass
2045 self.assertEqual(inspect.getgeneratorlocals(one), {})
2046
2047 def test_getgeneratorlocals_error(self):
2048 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
2049 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
2050 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
2051 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
2052
Nick Coghlane0f04652010-11-21 03:44:04 +00002053
Yury Selivanov5376ba92015-06-22 12:19:30 -04002054class TestGetCoroutineState(unittest.TestCase):
2055
2056 def setUp(self):
2057 @types.coroutine
2058 def number_coroutine():
2059 for number in range(5):
2060 yield number
2061 async def coroutine():
2062 await number_coroutine()
2063 self.coroutine = coroutine()
2064
2065 def tearDown(self):
2066 self.coroutine.close()
2067
2068 def _coroutinestate(self):
2069 return inspect.getcoroutinestate(self.coroutine)
2070
2071 def test_created(self):
2072 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
2073
2074 def test_suspended(self):
2075 self.coroutine.send(None)
2076 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
2077
2078 def test_closed_after_exhaustion(self):
2079 while True:
2080 try:
2081 self.coroutine.send(None)
2082 except StopIteration:
2083 break
2084
2085 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2086
2087 def test_closed_after_immediate_exception(self):
2088 with self.assertRaises(RuntimeError):
2089 self.coroutine.throw(RuntimeError)
2090 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2091
2092 def test_easy_debugging(self):
2093 # repr() and str() of a coroutine state should contain the state name
2094 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2095 for name in names:
2096 state = getattr(inspect, name)
2097 self.assertIn(name, repr(state))
2098 self.assertIn(name, str(state))
2099
2100 def test_getcoroutinelocals(self):
2101 @types.coroutine
2102 def gencoro():
2103 yield
2104
2105 gencoro = gencoro()
2106 async def func(a=None):
2107 b = 'spam'
2108 await gencoro
2109
2110 coro = func()
2111 self.assertEqual(inspect.getcoroutinelocals(coro),
2112 {'a': None, 'gencoro': gencoro})
2113 coro.send(None)
2114 self.assertEqual(inspect.getcoroutinelocals(coro),
2115 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2116
2117
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002118class MySignature(inspect.Signature):
2119 # Top-level to make it picklable;
2120 # used in test_signature_object_pickle
2121 pass
2122
2123class MyParameter(inspect.Parameter):
2124 # Top-level to make it picklable;
2125 # used in test_signature_object_pickle
2126 pass
2127
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002128
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002129
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002130class TestSignatureObject(unittest.TestCase):
2131 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002132 def signature(func, **kw):
2133 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002134 return (tuple((param.name,
2135 (... if param.default is param.empty else param.default),
2136 (... if param.annotation is param.empty
2137 else param.annotation),
2138 str(param.kind).lower())
2139 for param in sig.parameters.values()),
2140 (... if sig.return_annotation is sig.empty
2141 else sig.return_annotation))
2142
2143 def test_signature_object(self):
2144 S = inspect.Signature
2145 P = inspect.Parameter
2146
2147 self.assertEqual(str(S()), '()')
Jens Reidel611836a2020-03-18 03:22:46 +01002148 self.assertEqual(repr(S().parameters), 'mappingproxy(OrderedDict())')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002149
Yury Selivanov07a9e452014-01-29 10:58:16 -05002150 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002151 pass
2152 sig = inspect.signature(test)
2153 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002154 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002155 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002156 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002157 args = sig.parameters['args']
2158 ko = sig.parameters['ko']
2159 kwargs = sig.parameters['kwargs']
2160
2161 S((po, pk, args, ko, kwargs))
2162
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002163 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002164 S((pk, po, args, ko, kwargs))
2165
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002166 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002167 S((po, args, pk, ko, kwargs))
2168
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002169 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002170 S((args, po, pk, ko, kwargs))
2171
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002172 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002173 S((po, pk, args, kwargs, ko))
2174
2175 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002176 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002177 S((po, pk, args, kwargs2, ko))
2178
Yury Selivanov07a9e452014-01-29 10:58:16 -05002179 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2180 S((pod, po))
2181
2182 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2183 S((po, pkd, pk))
2184
2185 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2186 S((pkd, pk))
2187
Yury Selivanov374375d2014-03-27 12:41:53 -04002188 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002189 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002190
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002191 def test_signature_object_pickle(self):
2192 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2193 foo_partial = functools.partial(foo, a=1)
2194
2195 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002196
2197 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2198 with self.subTest(pickle_ver=ver, subclass=False):
2199 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2200 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002201
2202 # Test that basic sub-classing works
2203 sig = inspect.signature(foo)
2204 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2205 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2206 mysig = MySignature().replace(parameters=myparams.values(),
2207 return_annotation=sig.return_annotation)
2208 self.assertTrue(isinstance(mysig, MySignature))
2209 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2210
2211 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2212 with self.subTest(pickle_ver=ver, subclass=True):
2213 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2214 self.assertEqual(mysig, sig_pickled)
2215 self.assertTrue(isinstance(sig_pickled, MySignature))
2216 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2217 MyParameter))
2218
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002219 def test_signature_immutability(self):
2220 def test(a):
2221 pass
2222 sig = inspect.signature(test)
2223
2224 with self.assertRaises(AttributeError):
2225 sig.foo = 'bar'
2226
2227 with self.assertRaises(TypeError):
2228 sig.parameters['a'] = None
2229
2230 def test_signature_on_noarg(self):
2231 def test():
2232 pass
2233 self.assertEqual(self.signature(test), ((), ...))
2234
2235 def test_signature_on_wargs(self):
2236 def test(a, b:'foo') -> 123:
2237 pass
2238 self.assertEqual(self.signature(test),
2239 ((('a', ..., ..., "positional_or_keyword"),
Batuhan Taskaya044a1042020-10-06 23:03:02 +03002240 ('b', ..., repr('foo'), "positional_or_keyword")),
2241 '123'))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002242
2243 def test_signature_on_wkwonly(self):
2244 def test(*, a:float, b:str) -> int:
2245 pass
2246 self.assertEqual(self.signature(test),
2247 ((('a', ..., float, "keyword_only"),
2248 ('b', ..., str, "keyword_only")),
2249 int))
2250
2251 def test_signature_on_complex_args(self):
2252 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2253 pass
2254 self.assertEqual(self.signature(test),
2255 ((('a', ..., ..., "positional_or_keyword"),
Batuhan Taskaya044a1042020-10-06 23:03:02 +03002256 ('b', 10, repr('foo'), "positional_or_keyword"),
2257 ('args', ..., repr('bar'), "var_positional"),
2258 ('spam', ..., repr('baz'), "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002259 ('ham', 123, ..., "keyword_only"),
Batuhan Taskaya044a1042020-10-06 23:03:02 +03002260 ('kwargs', ..., 'int', "var_keyword")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002261 ...))
2262
Dong-hee Na378d7062017-05-18 04:00:51 +09002263 def test_signature_without_self(self):
2264 def test_args_only(*args): # NOQA
2265 pass
2266
2267 def test_args_kwargs_only(*args, **kwargs): # NOQA
2268 pass
2269
2270 class A:
2271 @classmethod
2272 def test_classmethod(*args): # NOQA
2273 pass
2274
2275 @staticmethod
2276 def test_staticmethod(*args): # NOQA
2277 pass
2278
2279 f1 = functools.partialmethod((test_classmethod), 1)
2280 f2 = functools.partialmethod((test_args_only), 1)
2281 f3 = functools.partialmethod((test_staticmethod), 1)
2282 f4 = functools.partialmethod((test_args_kwargs_only),1)
2283
2284 self.assertEqual(self.signature(test_args_only),
2285 ((('args', ..., ..., 'var_positional'),), ...))
2286 self.assertEqual(self.signature(test_args_kwargs_only),
2287 ((('args', ..., ..., 'var_positional'),
2288 ('kwargs', ..., ..., 'var_keyword')), ...))
2289 self.assertEqual(self.signature(A.f1),
2290 ((('args', ..., ..., 'var_positional'),), ...))
2291 self.assertEqual(self.signature(A.f2),
2292 ((('args', ..., ..., 'var_positional'),), ...))
2293 self.assertEqual(self.signature(A.f3),
2294 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002295 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002296 ((('args', ..., ..., 'var_positional'),
2297 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002298 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002299 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2300 "Signature information for builtins requires docstrings")
2301 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002302 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002303
Larry Hastings5c661892014-01-24 06:17:25 -08002304 def test_unbound_method(o):
2305 """Use this to test unbound methods (things that should have a self)"""
2306 signature = inspect.signature(o)
2307 self.assertTrue(isinstance(signature, inspect.Signature))
2308 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2309 return signature
2310
2311 def test_callable(o):
2312 """Use this to test bound methods or normal callables (things that don't expect self)"""
2313 signature = inspect.signature(o)
2314 self.assertTrue(isinstance(signature, inspect.Signature))
2315 if signature.parameters:
2316 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2317 return signature
2318
2319 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002320 def p(name): return signature.parameters[name].default
2321 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002322 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002323 self.assertEqual(p('d'), 3.14)
2324 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002325 self.assertEqual(p('n'), None)
2326 self.assertEqual(p('t'), True)
2327 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002328 self.assertEqual(p('local'), 3)
2329 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002330 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002331
Larry Hastings5c661892014-01-24 06:17:25 -08002332 test_callable(object)
2333
2334 # normal method
2335 # (PyMethodDescr_Type, "method_descriptor")
2336 test_unbound_method(_pickle.Pickler.dump)
2337 d = _pickle.Pickler(io.StringIO())
2338 test_callable(d.dump)
2339
2340 # static method
Serhiy Storchaka279f4462019-09-14 12:24:05 +03002341 test_callable(bytes.maketrans)
2342 test_callable(b'abc'.maketrans)
Larry Hastings5c661892014-01-24 06:17:25 -08002343
2344 # class method
2345 test_callable(dict.fromkeys)
2346 test_callable({}.fromkeys)
2347
2348 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2349 test_unbound_method(type.__call__)
2350 test_unbound_method(int.__add__)
2351 test_callable((3).__add__)
2352
2353 # _PyMethodWrapper_Type
2354 # support for 'method-wrapper'
2355 test_callable(min.__call__)
2356
Larry Hastings2623c8c2014-02-08 22:15:29 -08002357 # This doesn't work now.
2358 # (We don't have a valid signature for "type" in 3.4)
2359 with self.assertRaisesRegex(ValueError, "no signature found"):
2360 class ThisWorksNow:
2361 __call__ = type
2362 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002363
Yury Selivanov056e2652014-03-02 12:25:27 -05002364 # Regression test for issue #20786
2365 test_unbound_method(dict.__delitem__)
2366 test_unbound_method(property.__delete__)
2367
Zachary Ware8ef887c2015-04-13 18:22:35 -05002368 # Regression test for issue #20586
2369 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2370
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002371 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002372 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2373 "Signature information for builtins requires docstrings")
2374 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002375 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002376 func = _testcapi.docstring_with_signature_with_defaults
2377
2378 def decorator(func):
2379 @functools.wraps(func)
2380 def wrapper(*args, **kwargs) -> int:
2381 return func(*args, **kwargs)
2382 return wrapper
2383
2384 decorated_func = decorator(func)
2385
2386 self.assertEqual(inspect.signature(func),
2387 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002388
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002389 def wrapper_like(*args, **kwargs) -> int: pass
2390 self.assertEqual(inspect.signature(decorated_func,
2391 follow_wrapped=False),
2392 inspect.signature(wrapper_like))
2393
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002394 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002395 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002396 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002397 with self.assertRaisesRegex(ValueError,
2398 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002399 inspect.signature(_testcapi.docstring_no_signature)
2400
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002401 with self.assertRaisesRegex(ValueError,
2402 'no signature found for builtin'):
2403 inspect.signature(str)
2404
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002405 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002406 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002407 inspect.signature(42)
2408
Yury Selivanov63da7c72014-01-31 14:48:37 -05002409 def test_signature_from_functionlike_object(self):
2410 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2411 pass
2412
2413 class funclike:
2414 # Has to be callable, and have correct
2415 # __code__, __annotations__, __defaults__, __name__,
2416 # and __kwdefaults__ attributes
2417
2418 def __init__(self, func):
2419 self.__name__ = func.__name__
2420 self.__code__ = func.__code__
2421 self.__annotations__ = func.__annotations__
2422 self.__defaults__ = func.__defaults__
2423 self.__kwdefaults__ = func.__kwdefaults__
2424 self.func = func
2425
2426 def __call__(self, *args, **kwargs):
2427 return self.func(*args, **kwargs)
2428
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002429 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002430
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002431 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002432 self.assertEqual(sig_funclike, sig_func)
2433
2434 sig_funclike = inspect.signature(funclike(func))
2435 self.assertEqual(sig_funclike, sig_func)
2436
2437 # If object is not a duck type of function, then
2438 # signature will try to get a signature for its '__call__'
2439 # method
2440 fl = funclike(func)
2441 del fl.__defaults__
2442 self.assertEqual(self.signature(fl),
2443 ((('args', ..., ..., "var_positional"),
2444 ('kwargs', ..., ..., "var_keyword")),
2445 ...))
2446
Yury Selivanova773de02014-02-21 18:30:53 -05002447 # Test with cython-like builtins:
2448 _orig_isdesc = inspect.ismethoddescriptor
2449 def _isdesc(obj):
2450 if hasattr(obj, '_builtinmock'):
2451 return True
2452 return _orig_isdesc(obj)
2453
2454 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2455 builtin_func = funclike(func)
2456 # Make sure that our mock setup is working
2457 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2458 builtin_func._builtinmock = True
2459 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2460 self.assertEqual(inspect.signature(builtin_func), sig_func)
2461
Yury Selivanov63da7c72014-01-31 14:48:37 -05002462 def test_signature_functionlike_class(self):
2463 # We only want to duck type function-like objects,
2464 # not classes.
2465
2466 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2467 pass
2468
2469 class funclike:
2470 def __init__(self, marker):
2471 pass
2472
2473 __name__ = func.__name__
2474 __code__ = func.__code__
2475 __annotations__ = func.__annotations__
2476 __defaults__ = func.__defaults__
2477 __kwdefaults__ = func.__kwdefaults__
2478
Yury Selivanov63da7c72014-01-31 14:48:37 -05002479 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2480
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002481 def test_signature_on_method(self):
2482 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002483 def __init__(*args):
2484 pass
2485 def m1(self, arg1, arg2=1) -> int:
2486 pass
2487 def m2(*args):
2488 pass
2489 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002490 pass
2491
Yury Selivanov62560fb2014-01-28 12:26:24 -05002492 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002493 ((('arg1', ..., ..., "positional_or_keyword"),
2494 ('arg2', 1, ..., "positional_or_keyword")),
2495 int))
2496
Yury Selivanov62560fb2014-01-28 12:26:24 -05002497 self.assertEqual(self.signature(Test().m2),
2498 ((('args', ..., ..., "var_positional"),),
2499 ...))
2500
2501 self.assertEqual(self.signature(Test),
2502 ((('args', ..., ..., "var_positional"),),
2503 ...))
2504
2505 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2506 self.signature(Test())
2507
Yury Selivanov46c759d2015-05-27 21:56:53 -04002508 def test_signature_wrapped_bound_method(self):
2509 # Issue 24298
2510 class Test:
2511 def m1(self, arg1, arg2=1) -> int:
2512 pass
2513 @functools.wraps(Test().m1)
2514 def m1d(*args, **kwargs):
2515 pass
2516 self.assertEqual(self.signature(m1d),
2517 ((('arg1', ..., ..., "positional_or_keyword"),
2518 ('arg2', 1, ..., "positional_or_keyword")),
2519 int))
2520
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002521 def test_signature_on_classmethod(self):
2522 class Test:
2523 @classmethod
2524 def foo(cls, arg1, *, arg2=1):
2525 pass
2526
2527 meth = Test().foo
2528 self.assertEqual(self.signature(meth),
2529 ((('arg1', ..., ..., "positional_or_keyword"),
2530 ('arg2', 1, ..., "keyword_only")),
2531 ...))
2532
2533 meth = Test.foo
2534 self.assertEqual(self.signature(meth),
2535 ((('arg1', ..., ..., "positional_or_keyword"),
2536 ('arg2', 1, ..., "keyword_only")),
2537 ...))
2538
2539 def test_signature_on_staticmethod(self):
2540 class Test:
2541 @staticmethod
2542 def foo(cls, *, arg):
2543 pass
2544
2545 meth = Test().foo
2546 self.assertEqual(self.signature(meth),
2547 ((('cls', ..., ..., "positional_or_keyword"),
2548 ('arg', ..., ..., "keyword_only")),
2549 ...))
2550
2551 meth = Test.foo
2552 self.assertEqual(self.signature(meth),
2553 ((('cls', ..., ..., "positional_or_keyword"),
2554 ('arg', ..., ..., "keyword_only")),
2555 ...))
2556
2557 def test_signature_on_partial(self):
2558 from functools import partial
2559
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002560 Parameter = inspect.Parameter
2561
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002562 def test():
2563 pass
2564
2565 self.assertEqual(self.signature(partial(test)), ((), ...))
2566
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002567 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002568 inspect.signature(partial(test, 1))
2569
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002570 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002571 inspect.signature(partial(test, a=1))
2572
2573 def test(a, b, *, c, d):
2574 pass
2575
2576 self.assertEqual(self.signature(partial(test)),
2577 ((('a', ..., ..., "positional_or_keyword"),
2578 ('b', ..., ..., "positional_or_keyword"),
2579 ('c', ..., ..., "keyword_only"),
2580 ('d', ..., ..., "keyword_only")),
2581 ...))
2582
2583 self.assertEqual(self.signature(partial(test, 1)),
2584 ((('b', ..., ..., "positional_or_keyword"),
2585 ('c', ..., ..., "keyword_only"),
2586 ('d', ..., ..., "keyword_only")),
2587 ...))
2588
2589 self.assertEqual(self.signature(partial(test, 1, c=2)),
2590 ((('b', ..., ..., "positional_or_keyword"),
2591 ('c', 2, ..., "keyword_only"),
2592 ('d', ..., ..., "keyword_only")),
2593 ...))
2594
2595 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2596 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002597 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002598 ('c', 2, ..., "keyword_only"),
2599 ('d', ..., ..., "keyword_only")),
2600 ...))
2601
2602 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002603 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002604 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002605 ('d', ..., ..., "keyword_only")),
2606 ...))
2607
2608 self.assertEqual(self.signature(partial(test, a=1)),
2609 ((('a', 1, ..., "keyword_only"),
2610 ('b', ..., ..., "keyword_only"),
2611 ('c', ..., ..., "keyword_only"),
2612 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002613 ...))
2614
2615 def test(a, *args, b, **kwargs):
2616 pass
2617
2618 self.assertEqual(self.signature(partial(test, 1)),
2619 ((('args', ..., ..., "var_positional"),
2620 ('b', ..., ..., "keyword_only"),
2621 ('kwargs', ..., ..., "var_keyword")),
2622 ...))
2623
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002624 self.assertEqual(self.signature(partial(test, a=1)),
2625 ((('a', 1, ..., "keyword_only"),
2626 ('b', ..., ..., "keyword_only"),
2627 ('kwargs', ..., ..., "var_keyword")),
2628 ...))
2629
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002630 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2631 ((('args', ..., ..., "var_positional"),
2632 ('b', ..., ..., "keyword_only"),
2633 ('kwargs', ..., ..., "var_keyword")),
2634 ...))
2635
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002636 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2637 ((('args', ..., ..., "var_positional"),
2638 ('b', ..., ..., "keyword_only"),
2639 ('kwargs', ..., ..., "var_keyword")),
2640 ...))
2641
2642 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2643 ((('args', ..., ..., "var_positional"),
2644 ('b', 0, ..., "keyword_only"),
2645 ('kwargs', ..., ..., "var_keyword")),
2646 ...))
2647
2648 self.assertEqual(self.signature(partial(test, b=0)),
2649 ((('a', ..., ..., "positional_or_keyword"),
2650 ('args', ..., ..., "var_positional"),
2651 ('b', 0, ..., "keyword_only"),
2652 ('kwargs', ..., ..., "var_keyword")),
2653 ...))
2654
2655 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2656 ((('a', ..., ..., "positional_or_keyword"),
2657 ('args', ..., ..., "var_positional"),
2658 ('b', 0, ..., "keyword_only"),
2659 ('kwargs', ..., ..., "var_keyword")),
2660 ...))
2661
2662 def test(a, b, c:int) -> 42:
2663 pass
2664
2665 sig = test.__signature__ = inspect.signature(test)
2666
2667 self.assertEqual(self.signature(partial(partial(test, 1))),
2668 ((('b', ..., ..., "positional_or_keyword"),
Batuhan Taskaya044a1042020-10-06 23:03:02 +03002669 ('c', ..., 'int', "positional_or_keyword")),
2670 '42'))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002671
2672 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
Batuhan Taskaya044a1042020-10-06 23:03:02 +03002673 ((('c', ..., 'int', "positional_or_keyword"),),
2674 '42'))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002675
2676 psig = inspect.signature(partial(partial(test, 1), 2))
2677
2678 def foo(a):
2679 return a
2680 _foo = partial(partial(foo, a=10), a=20)
2681 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002682 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002683 ...))
2684 # check that we don't have any side-effects in signature(),
2685 # and the partial object is still functioning
2686 self.assertEqual(_foo(), 20)
2687
2688 def foo(a, b, c):
2689 return a, b, c
2690 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002691
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002692 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002693 ((('b', 30, ..., "keyword_only"),
2694 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002695 ...))
2696 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002697
2698 def foo(a, b, c, *, d):
2699 return a, b, c, d
2700 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2701 self.assertEqual(self.signature(_foo),
2702 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002703 ('b', 10, ..., "keyword_only"),
2704 ('c', 20, ..., "keyword_only"),
2705 ('d', 30, ..., "keyword_only"),
2706 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002707 ...))
2708 ba = inspect.signature(_foo).bind(a=200, b=11)
2709 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2710
2711 def foo(a=1, b=2, c=3):
2712 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002713 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2714
2715 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002716 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002717
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002718 ba = inspect.signature(_foo).bind(11, 12)
2719 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002720
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002721 ba = inspect.signature(_foo).bind(11, b=12)
2722 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002723
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002724 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002725 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2726
2727 _foo = partial(_foo, b=10, c=20)
2728 ba = inspect.signature(_foo).bind(12)
2729 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2730
2731
2732 def foo(a, b, c, d, **kwargs):
2733 pass
2734 sig = inspect.signature(foo)
2735 params = sig.parameters.copy()
2736 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2737 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2738 foo.__signature__ = inspect.Signature(params.values())
2739 sig = inspect.signature(foo)
2740 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2741
2742 self.assertEqual(self.signature(partial(foo, 1)),
2743 ((('b', ..., ..., 'positional_only'),
2744 ('c', ..., ..., 'positional_or_keyword'),
2745 ('d', ..., ..., 'positional_or_keyword'),
2746 ('kwargs', ..., ..., 'var_keyword')),
2747 ...))
2748
2749 self.assertEqual(self.signature(partial(foo, 1, 2)),
2750 ((('c', ..., ..., 'positional_or_keyword'),
2751 ('d', ..., ..., 'positional_or_keyword'),
2752 ('kwargs', ..., ..., 'var_keyword')),
2753 ...))
2754
2755 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2756 ((('d', ..., ..., 'positional_or_keyword'),
2757 ('kwargs', ..., ..., 'var_keyword')),
2758 ...))
2759
2760 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2761 ((('c', 3, ..., 'keyword_only'),
2762 ('d', ..., ..., 'keyword_only'),
2763 ('kwargs', ..., ..., 'var_keyword')),
2764 ...))
2765
2766 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2767 ((('b', ..., ..., 'positional_only'),
2768 ('c', 3, ..., 'keyword_only'),
2769 ('d', ..., ..., 'keyword_only'),
2770 ('kwargs', ..., ..., 'var_keyword')),
2771 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002772
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002773 def test_signature_on_partialmethod(self):
2774 from functools import partialmethod
2775
2776 class Spam:
2777 def test():
2778 pass
2779 ham = partialmethod(test)
2780
2781 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2782 inspect.signature(Spam.ham)
2783
2784 class Spam:
2785 def test(it, a, *, c) -> 'spam':
2786 pass
2787 ham = partialmethod(test, c=1)
2788
2789 self.assertEqual(self.signature(Spam.ham),
2790 ((('it', ..., ..., 'positional_or_keyword'),
2791 ('a', ..., ..., 'positional_or_keyword'),
2792 ('c', 1, ..., 'keyword_only')),
Batuhan Taskaya044a1042020-10-06 23:03:02 +03002793 repr('spam')))
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002794
2795 self.assertEqual(self.signature(Spam().ham),
2796 ((('a', ..., ..., 'positional_or_keyword'),
2797 ('c', 1, ..., 'keyword_only')),
Batuhan Taskaya044a1042020-10-06 23:03:02 +03002798 repr('spam')))
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002799
Yury Selivanov8a387212018-03-06 12:59:45 -05002800 class Spam:
2801 def test(self: 'anno', x):
2802 pass
2803
2804 g = partialmethod(test, 1)
2805
2806 self.assertEqual(self.signature(Spam.g),
Batuhan Taskaya044a1042020-10-06 23:03:02 +03002807 ((('self', ..., repr('anno'), 'positional_or_keyword'),),
Yury Selivanov8a387212018-03-06 12:59:45 -05002808 ...))
2809
Yury Selivanov0486f812014-01-29 12:18:59 -05002810 def test_signature_on_fake_partialmethod(self):
2811 def foo(a): pass
2812 foo._partialmethod = 'spam'
2813 self.assertEqual(str(inspect.signature(foo)), '(a)')
2814
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002815 def test_signature_on_decorated(self):
2816 import functools
2817
2818 def decorator(func):
2819 @functools.wraps(func)
2820 def wrapper(*args, **kwargs) -> int:
2821 return func(*args, **kwargs)
2822 return wrapper
2823
2824 class Foo:
2825 @decorator
2826 def bar(self, a, b):
2827 pass
2828
2829 self.assertEqual(self.signature(Foo.bar),
2830 ((('self', ..., ..., "positional_or_keyword"),
2831 ('a', ..., ..., "positional_or_keyword"),
2832 ('b', ..., ..., "positional_or_keyword")),
2833 ...))
2834
2835 self.assertEqual(self.signature(Foo().bar),
2836 ((('a', ..., ..., "positional_or_keyword"),
2837 ('b', ..., ..., "positional_or_keyword")),
2838 ...))
2839
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002840 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2841 ((('args', ..., ..., "var_positional"),
2842 ('kwargs', ..., ..., "var_keyword")),
2843 ...)) # functools.wraps will copy __annotations__
2844 # from "func" to "wrapper", hence no
2845 # return_annotation
2846
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002847 # Test that we handle method wrappers correctly
2848 def decorator(func):
2849 @functools.wraps(func)
2850 def wrapper(*args, **kwargs) -> int:
2851 return func(42, *args, **kwargs)
2852 sig = inspect.signature(func)
2853 new_params = tuple(sig.parameters.values())[1:]
2854 wrapper.__signature__ = sig.replace(parameters=new_params)
2855 return wrapper
2856
2857 class Foo:
2858 @decorator
2859 def __call__(self, a, b):
2860 pass
2861
2862 self.assertEqual(self.signature(Foo.__call__),
2863 ((('a', ..., ..., "positional_or_keyword"),
2864 ('b', ..., ..., "positional_or_keyword")),
2865 ...))
2866
2867 self.assertEqual(self.signature(Foo().__call__),
2868 ((('b', ..., ..., "positional_or_keyword"),),
2869 ...))
2870
Nick Coghlane8c45d62013-07-28 20:00:01 +10002871 # Test we handle __signature__ partway down the wrapper stack
2872 def wrapped_foo_call():
2873 pass
2874 wrapped_foo_call.__wrapped__ = Foo.__call__
2875
2876 self.assertEqual(self.signature(wrapped_foo_call),
2877 ((('a', ..., ..., "positional_or_keyword"),
2878 ('b', ..., ..., "positional_or_keyword")),
2879 ...))
2880
2881
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002882 def test_signature_on_class(self):
2883 class C:
2884 def __init__(self, a):
2885 pass
2886
2887 self.assertEqual(self.signature(C),
2888 ((('a', ..., ..., "positional_or_keyword"),),
2889 ...))
2890
2891 class CM(type):
2892 def __call__(cls, a):
2893 pass
2894 class C(metaclass=CM):
2895 def __init__(self, b):
2896 pass
2897
2898 self.assertEqual(self.signature(C),
2899 ((('a', ..., ..., "positional_or_keyword"),),
2900 ...))
2901
2902 class CM(type):
2903 def __new__(mcls, name, bases, dct, *, foo=1):
2904 return super().__new__(mcls, name, bases, dct)
2905 class C(metaclass=CM):
2906 def __init__(self, b):
2907 pass
2908
2909 self.assertEqual(self.signature(C),
2910 ((('b', ..., ..., "positional_or_keyword"),),
2911 ...))
2912
2913 self.assertEqual(self.signature(CM),
2914 ((('name', ..., ..., "positional_or_keyword"),
2915 ('bases', ..., ..., "positional_or_keyword"),
2916 ('dct', ..., ..., "positional_or_keyword"),
2917 ('foo', 1, ..., "keyword_only")),
2918 ...))
2919
2920 class CMM(type):
2921 def __new__(mcls, name, bases, dct, *, foo=1):
2922 return super().__new__(mcls, name, bases, dct)
2923 def __call__(cls, nm, bs, dt):
2924 return type(nm, bs, dt)
2925 class CM(type, metaclass=CMM):
2926 def __new__(mcls, name, bases, dct, *, bar=2):
2927 return super().__new__(mcls, name, bases, dct)
2928 class C(metaclass=CM):
2929 def __init__(self, b):
2930 pass
2931
2932 self.assertEqual(self.signature(CMM),
2933 ((('name', ..., ..., "positional_or_keyword"),
2934 ('bases', ..., ..., "positional_or_keyword"),
2935 ('dct', ..., ..., "positional_or_keyword"),
2936 ('foo', 1, ..., "keyword_only")),
2937 ...))
2938
2939 self.assertEqual(self.signature(CM),
2940 ((('nm', ..., ..., "positional_or_keyword"),
2941 ('bs', ..., ..., "positional_or_keyword"),
2942 ('dt', ..., ..., "positional_or_keyword")),
2943 ...))
2944
2945 self.assertEqual(self.signature(C),
2946 ((('b', ..., ..., "positional_or_keyword"),),
2947 ...))
2948
2949 class CM(type):
2950 def __init__(cls, name, bases, dct, *, bar=2):
2951 return super().__init__(name, bases, dct)
2952 class C(metaclass=CM):
2953 def __init__(self, b):
2954 pass
2955
2956 self.assertEqual(self.signature(CM),
2957 ((('name', ..., ..., "positional_or_keyword"),
2958 ('bases', ..., ..., "positional_or_keyword"),
2959 ('dct', ..., ..., "positional_or_keyword"),
2960 ('bar', 2, ..., "keyword_only")),
2961 ...))
2962
Yury Selivanov145dff82014-02-01 13:49:29 -05002963 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2964 "Signature information for builtins requires docstrings")
2965 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002966 # Test classes without user-defined __init__ or __new__
2967 class C: pass
2968 self.assertEqual(str(inspect.signature(C)), '()')
2969 class D(C): pass
2970 self.assertEqual(str(inspect.signature(D)), '()')
2971
2972 # Test meta-classes without user-defined __init__ or __new__
2973 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002974 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002975 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2976 self.assertEqual(inspect.signature(C), None)
2977 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2978 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002979
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002980 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2981 "Signature information for builtins requires docstrings")
2982 def test_signature_on_builtin_class(self):
Antoine Pitrou91f43802019-05-26 17:10:09 +02002983 expected = ('(file, protocol=None, fix_imports=True, '
2984 'buffer_callback=None)')
2985 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002986
2987 class P(_pickle.Pickler): pass
2988 class EmptyTrait: pass
2989 class P2(EmptyTrait, P): pass
Antoine Pitrou91f43802019-05-26 17:10:09 +02002990 self.assertEqual(str(inspect.signature(P)), expected)
2991 self.assertEqual(str(inspect.signature(P2)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002992
2993 class P3(P2):
2994 def __init__(self, spam):
2995 pass
2996 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2997
2998 class MetaP(type):
2999 def __call__(cls, foo, bar):
3000 pass
3001 class P4(P2, metaclass=MetaP):
3002 pass
3003 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
3004
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003005 def test_signature_on_callable_objects(self):
3006 class Foo:
3007 def __call__(self, a):
3008 pass
3009
3010 self.assertEqual(self.signature(Foo()),
3011 ((('a', ..., ..., "positional_or_keyword"),),
3012 ...))
3013
3014 class Spam:
3015 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003016 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003017 inspect.signature(Spam())
3018
3019 class Bar(Spam, Foo):
3020 pass
3021
3022 self.assertEqual(self.signature(Bar()),
3023 ((('a', ..., ..., "positional_or_keyword"),),
3024 ...))
3025
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003026 class Wrapped:
3027 pass
3028 Wrapped.__wrapped__ = lambda a: None
3029 self.assertEqual(self.signature(Wrapped),
3030 ((('a', ..., ..., "positional_or_keyword"),),
3031 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10003032 # wrapper loop:
3033 Wrapped.__wrapped__ = Wrapped
3034 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3035 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003036
3037 def test_signature_on_lambdas(self):
3038 self.assertEqual(self.signature((lambda a=10: a)),
3039 ((('a', 10, ..., "positional_or_keyword"),),
3040 ...))
3041
3042 def test_signature_equality(self):
3043 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003044 self.assertFalse(inspect.signature(foo) == 42)
3045 self.assertTrue(inspect.signature(foo) != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003046 self.assertTrue(inspect.signature(foo) == ALWAYS_EQ)
3047 self.assertFalse(inspect.signature(foo) != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003048
3049 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003050 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3051 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003052 self.assertEqual(
3053 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003054
3055 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003056 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3057 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003058 self.assertNotEqual(
3059 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003060
3061 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003062 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3063 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003064 self.assertNotEqual(
3065 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003066
3067 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003068 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3069 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003070 self.assertNotEqual(
3071 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003072
3073 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003074 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3075 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003076 self.assertNotEqual(
3077 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003078
3079 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003080 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3081 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003082 self.assertNotEqual(
3083 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003084 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003085 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3086 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003087 self.assertNotEqual(
3088 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003089
3090 def foo(*, a, b, c): pass
3091 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003092 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3093 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003094 self.assertEqual(
3095 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003096
3097 def foo(*, a=1, b, c): pass
3098 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003099 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3100 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003101 self.assertEqual(
3102 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003103
3104 def foo(pos, *, a=1, b, c): pass
3105 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003106 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3107 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003108 self.assertEqual(
3109 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003110
3111 def foo(pos, *, a, b, c): pass
3112 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003113 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3114 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003115 self.assertNotEqual(
3116 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003117
3118 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3119 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003120 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3121 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003122 self.assertEqual(
3123 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003124
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003125 def test_signature_hashable(self):
3126 S = inspect.Signature
3127 P = inspect.Parameter
3128
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003129 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003130 foo_sig = inspect.signature(foo)
3131
3132 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3133
3134 self.assertEqual(hash(foo_sig), hash(manual_sig))
3135 self.assertNotEqual(hash(foo_sig),
3136 hash(manual_sig.replace(return_annotation='spam')))
3137
3138 def bar(a) -> 1: pass
3139 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3140
3141 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003142 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003143 hash(inspect.signature(foo))
3144
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003145 def test_signature_str(self):
3146 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3147 pass
3148 self.assertEqual(str(inspect.signature(foo)),
Batuhan Taskaya044a1042020-10-06 23:03:02 +03003149 '(a: \'int\' = 1, *, b, c=None, **kwargs) -> \'42\'')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003150
3151 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3152 pass
3153 self.assertEqual(str(inspect.signature(foo)),
Batuhan Taskaya044a1042020-10-06 23:03:02 +03003154 '(a: \'int\' = 1, *args, b, c=None, **kwargs) -> \'42\'')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003155
3156 def foo():
3157 pass
3158 self.assertEqual(str(inspect.signature(foo)), '()')
3159
3160 def test_signature_str_positional_only(self):
3161 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003162 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003163
3164 def test(a_po, *, b, **kwargs):
3165 return a_po, kwargs
3166
3167 sig = inspect.signature(test)
3168 new_params = list(sig.parameters.values())
3169 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3170 test.__signature__ = sig.replace(parameters=new_params)
3171
3172 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003173 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003174
Yury Selivanov2393dca2014-01-27 15:07:58 -05003175 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3176 '(foo, /)')
3177
3178 self.assertEqual(str(S(parameters=[
3179 P('foo', P.POSITIONAL_ONLY),
3180 P('bar', P.VAR_KEYWORD)])),
3181 '(foo, /, **bar)')
3182
3183 self.assertEqual(str(S(parameters=[
3184 P('foo', P.POSITIONAL_ONLY),
3185 P('bar', P.VAR_POSITIONAL)])),
3186 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003187
3188 def test_signature_replace_anno(self):
3189 def test() -> 42:
3190 pass
3191
3192 sig = inspect.signature(test)
3193 sig = sig.replace(return_annotation=None)
3194 self.assertIs(sig.return_annotation, None)
3195 sig = sig.replace(return_annotation=sig.empty)
3196 self.assertIs(sig.return_annotation, sig.empty)
Batuhan Taskaya044a1042020-10-06 23:03:02 +03003197 sig = sig.replace(return_annotation='42')
3198 self.assertEqual(sig.return_annotation, '42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003199 self.assertEqual(sig, inspect.signature(test))
3200
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003201 def test_signature_on_mangled_parameters(self):
3202 class Spam:
3203 def foo(self, __p1:1=2, *, __p2:2=3):
3204 pass
3205 class Ham(Spam):
3206 pass
3207
3208 self.assertEqual(self.signature(Spam.foo),
3209 ((('self', ..., ..., "positional_or_keyword"),
Batuhan Taskaya044a1042020-10-06 23:03:02 +03003210 ('_Spam__p1', 2, '1', "positional_or_keyword"),
3211 ('_Spam__p2', 3, '2', "keyword_only")),
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003212 ...))
3213
3214 self.assertEqual(self.signature(Spam.foo),
3215 self.signature(Ham.foo))
3216
Yury Selivanovda396452014-03-27 12:09:24 -04003217 def test_signature_from_callable_python_obj(self):
3218 class MySignature(inspect.Signature): pass
3219 def foo(a, *, b:1): pass
3220 foo_sig = MySignature.from_callable(foo)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003221 self.assertIsInstance(foo_sig, MySignature)
3222
3223 def test_signature_from_callable_class(self):
3224 # A regression test for a class inheriting its signature from `object`.
3225 class MySignature(inspect.Signature): pass
3226 class foo: pass
3227 foo_sig = MySignature.from_callable(foo)
3228 self.assertIsInstance(foo_sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003229
3230 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3231 "Signature information for builtins requires docstrings")
3232 def test_signature_from_callable_builtin_obj(self):
3233 class MySignature(inspect.Signature): pass
3234 sig = MySignature.from_callable(_pickle.Pickler)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003235 self.assertIsInstance(sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003236
larryhastingsf36ba122018-01-28 11:13:09 -08003237 def test_signature_definition_order_preserved_on_kwonly(self):
3238 for fn in signatures_with_lexicographic_keyword_only_parameters():
3239 signature = inspect.signature(fn)
3240 l = list(signature.parameters)
3241 sorted_l = sorted(l)
3242 self.assertTrue(l)
3243 self.assertEqual(l, sorted_l)
3244 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3245 l = list(signature.parameters)
3246 self.assertEqual(l, unsorted_keyword_only_parameters)
3247
Jens Reidel611836a2020-03-18 03:22:46 +01003248 def test_signater_parameters_is_ordered(self):
3249 p1 = inspect.signature(lambda x, y: None).parameters
3250 p2 = inspect.signature(lambda y, x: None).parameters
3251 self.assertNotEqual(p1, p2)
3252
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003253 def test_signature_annotations_with_local_namespaces(self):
3254 class Foo: ...
3255 def func(foo: Foo) -> int: pass
3256 def func2(foo: Foo, bar: Bar) -> int: pass
3257
3258 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3259 with self.subTest(signature_func = signature_func):
3260 sig1 = signature_func(func)
3261 self.assertEqual(sig1.return_annotation, 'int')
3262 self.assertEqual(sig1.parameters['foo'].annotation, 'Foo')
3263
3264 sig2 = signature_func(func, localns=locals())
3265 self.assertEqual(sig2.return_annotation, int)
3266 self.assertEqual(sig2.parameters['foo'].annotation, Foo)
3267
3268 sig3 = signature_func(func2, globalns={'Bar': int}, localns=locals())
3269 self.assertEqual(sig3.return_annotation, int)
3270 self.assertEqual(sig3.parameters['foo'].annotation, Foo)
3271 self.assertEqual(sig3.parameters['bar'].annotation, int)
3272
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003273
3274class TestParameterObject(unittest.TestCase):
3275 def test_signature_parameter_kinds(self):
3276 P = inspect.Parameter
3277 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3278 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3279
3280 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3281 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3282
3283 def test_signature_parameter_object(self):
3284 p = inspect.Parameter('foo', default=10,
3285 kind=inspect.Parameter.POSITIONAL_ONLY)
3286 self.assertEqual(p.name, 'foo')
3287 self.assertEqual(p.default, 10)
3288 self.assertIs(p.annotation, p.empty)
3289 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3290
Dong-hee Naa9cab432018-05-30 00:04:08 +09003291 with self.assertRaisesRegex(ValueError, "value '123' is "
3292 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003293 inspect.Parameter('foo', default=10, kind='123')
3294
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003295 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003296 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3297
Yury Selivanov2393dca2014-01-27 15:07:58 -05003298 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003299 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3300
Yury Selivanov2393dca2014-01-27 15:07:58 -05003301 with self.assertRaisesRegex(ValueError,
3302 'is not a valid parameter name'):
3303 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3304
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003305 with self.assertRaisesRegex(ValueError,
3306 'is not a valid parameter name'):
3307 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3308
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003309 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003310 inspect.Parameter('a', default=42,
3311 kind=inspect.Parameter.VAR_KEYWORD)
3312
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003313 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003314 inspect.Parameter('a', default=42,
3315 kind=inspect.Parameter.VAR_POSITIONAL)
3316
3317 p = inspect.Parameter('a', default=42,
3318 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003319 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003320 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3321
3322 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003323 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003324
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003325 def test_signature_parameter_hashable(self):
3326 P = inspect.Parameter
3327 foo = P('foo', kind=P.POSITIONAL_ONLY)
3328 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3329 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3330 default=42)))
3331 self.assertNotEqual(hash(foo),
3332 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3333
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003334 def test_signature_parameter_equality(self):
3335 P = inspect.Parameter
3336 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3337
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003338 self.assertTrue(p == p)
3339 self.assertFalse(p != p)
3340 self.assertFalse(p == 42)
3341 self.assertTrue(p != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003342 self.assertTrue(p == ALWAYS_EQ)
3343 self.assertFalse(p != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003344
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003345 self.assertTrue(p == P('foo', default=42,
3346 kind=inspect.Parameter.KEYWORD_ONLY))
3347 self.assertFalse(p != P('foo', default=42,
3348 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003349
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003350 def test_signature_parameter_replace(self):
3351 p = inspect.Parameter('foo', default=42,
3352 kind=inspect.Parameter.KEYWORD_ONLY)
3353
3354 self.assertIsNot(p, p.replace())
3355 self.assertEqual(p, p.replace())
3356
3357 p2 = p.replace(annotation=1)
3358 self.assertEqual(p2.annotation, 1)
3359 p2 = p2.replace(annotation=p2.empty)
3360 self.assertEqual(p, p2)
3361
3362 p2 = p2.replace(name='bar')
3363 self.assertEqual(p2.name, 'bar')
3364 self.assertNotEqual(p2, p)
3365
Yury Selivanov2393dca2014-01-27 15:07:58 -05003366 with self.assertRaisesRegex(ValueError,
3367 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003368 p2 = p2.replace(name=p2.empty)
3369
3370 p2 = p2.replace(name='foo', default=None)
3371 self.assertIs(p2.default, None)
3372 self.assertNotEqual(p2, p)
3373
3374 p2 = p2.replace(name='foo', default=p2.empty)
3375 self.assertIs(p2.default, p2.empty)
3376
3377
3378 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3379 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3380 self.assertNotEqual(p2, p)
3381
Dong-hee Naa9cab432018-05-30 00:04:08 +09003382 with self.assertRaisesRegex(ValueError,
3383 "value <class 'inspect._empty'> "
3384 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003385 p2 = p2.replace(kind=p2.empty)
3386
3387 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3388 self.assertEqual(p2, p)
3389
3390 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003391 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3392 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003393
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003394 @cpython_only
3395 def test_signature_parameter_implicit(self):
3396 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003397 'implicit arguments must be passed as '
3398 'positional or keyword arguments, '
3399 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003400 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3401
3402 param = inspect.Parameter(
3403 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3404 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3405 self.assertEqual(param.name, 'implicit0')
3406
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003407 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003408 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003409
3410 with self.assertRaises(AttributeError):
3411 p.foo = 'bar'
3412
3413 with self.assertRaises(AttributeError):
3414 p.kind = 123
3415
3416
3417class TestSignatureBind(unittest.TestCase):
3418 @staticmethod
3419 def call(func, *args, **kwargs):
3420 sig = inspect.signature(func)
3421 ba = sig.bind(*args, **kwargs)
3422 return func(*ba.args, **ba.kwargs)
3423
3424 def test_signature_bind_empty(self):
3425 def test():
3426 return 42
3427
3428 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003429 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003430 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003431 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003432 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003433 with self.assertRaisesRegex(
3434 TypeError, "got an unexpected keyword argument 'spam'"):
3435
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003436 self.call(test, spam=1)
3437
3438 def test_signature_bind_var(self):
3439 def test(*args, **kwargs):
3440 return args, kwargs
3441
3442 self.assertEqual(self.call(test), ((), {}))
3443 self.assertEqual(self.call(test, 1), ((1,), {}))
3444 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3445 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3446 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3447 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3448 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3449 ((1, 2), {'foo': 'bar'}))
3450
3451 def test_signature_bind_just_args(self):
3452 def test(a, b, c):
3453 return a, b, c
3454
3455 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3456
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003457 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003458 self.call(test, 1, 2, 3, 4)
3459
Yury Selivanov86872752015-05-19 00:27:49 -04003460 with self.assertRaisesRegex(TypeError,
3461 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003462 self.call(test, 1)
3463
Yury Selivanov86872752015-05-19 00:27:49 -04003464 with self.assertRaisesRegex(TypeError,
3465 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003466 self.call(test)
3467
3468 def test(a, b, c=10):
3469 return a, b, c
3470 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3471 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3472
3473 def test(a=1, b=2, c=3):
3474 return a, b, c
3475 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3476 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3477 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3478
3479 def test_signature_bind_varargs_order(self):
3480 def test(*args):
3481 return args
3482
3483 self.assertEqual(self.call(test), ())
3484 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3485
3486 def test_signature_bind_args_and_varargs(self):
3487 def test(a, b, c=3, *args):
3488 return a, b, c, args
3489
3490 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3491 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3492 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3493 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3494
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003495 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003496 "multiple values for argument 'c'"):
3497 self.call(test, 1, 2, 3, c=4)
3498
3499 def test_signature_bind_just_kwargs(self):
3500 def test(**kwargs):
3501 return kwargs
3502
3503 self.assertEqual(self.call(test), {})
3504 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3505 {'foo': 'bar', 'spam': 'ham'})
3506
3507 def test_signature_bind_args_and_kwargs(self):
3508 def test(a, b, c=3, **kwargs):
3509 return a, b, c, kwargs
3510
3511 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3512 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3513 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3514 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3515 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3516 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3517 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3518 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3519 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3520 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3521 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3522 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3523 (1, 2, 4, {'foo': 'bar'}))
3524 self.assertEqual(self.call(test, c=5, a=4, b=3),
3525 (4, 3, 5, {}))
3526
3527 def test_signature_bind_kwonly(self):
3528 def test(*, foo):
3529 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003530 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003531 'too many positional arguments'):
3532 self.call(test, 1)
3533 self.assertEqual(self.call(test, foo=1), 1)
3534
3535 def test(a, *, foo=1, bar):
3536 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003537 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003538 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003539 self.call(test, 1)
3540
3541 def test(foo, *, bar):
3542 return foo, bar
3543 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3544 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3545
Yury Selivanov86872752015-05-19 00:27:49 -04003546 with self.assertRaisesRegex(
3547 TypeError, "got an unexpected keyword argument 'spam'"):
3548
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003549 self.call(test, bar=2, foo=1, spam=10)
3550
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003551 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003552 'too many positional arguments'):
3553 self.call(test, 1, 2)
3554
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003555 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003556 'too many positional arguments'):
3557 self.call(test, 1, 2, bar=2)
3558
Yury Selivanov86872752015-05-19 00:27:49 -04003559 with self.assertRaisesRegex(
3560 TypeError, "got an unexpected keyword argument 'spam'"):
3561
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003562 self.call(test, 1, bar=2, spam='ham')
3563
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003564 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003565 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003566 self.call(test, 1)
3567
3568 def test(foo, *, bar, **bin):
3569 return foo, bar, bin
3570 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3571 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3572 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3573 (1, 2, {'spam': 'ham'}))
3574 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3575 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003576 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003577 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003578 self.call(test, spam='ham', bar=2)
3579 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3580 (1, 2, {'bin': 1, 'spam': 10}))
3581
3582 def test_signature_bind_arguments(self):
3583 def test(a, *args, b, z=100, **kwargs):
3584 pass
3585 sig = inspect.signature(test)
3586 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3587 # we won't have 'z' argument in the bound arguments object, as we didn't
3588 # pass it to the 'bind'
3589 self.assertEqual(tuple(ba.arguments.items()),
3590 (('a', 10), ('args', (20,)), ('b', 30),
3591 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3592 self.assertEqual(ba.kwargs,
3593 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3594 self.assertEqual(ba.args, (10, 20))
3595
3596 def test_signature_bind_positional_only(self):
3597 P = inspect.Parameter
3598
3599 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3600 return a_po, b_po, c_po, foo, bar, kwargs
3601
3602 sig = inspect.signature(test)
3603 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3604 for name in ('a_po', 'b_po', 'c_po'):
3605 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3606 new_sig = sig.replace(parameters=new_params.values())
3607 test.__signature__ = new_sig
3608
3609 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3610 (1, 2, 4, 5, 6, {}))
3611
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003612 self.assertEqual(self.call(test, 1, 2),
3613 (1, 2, 3, 42, 50, {}))
3614
3615 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3616 (1, 2, 3, 4, 5, {}))
3617
3618 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3619 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3620
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003621 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003622 self.call(test, 1, 2, c_po=4)
3623
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003624 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003625 self.call(test, a_po=1, b_po=2)
3626
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003627 def test_signature_bind_with_self_arg(self):
3628 # Issue #17071: one of the parameters is named "self
3629 def test(a, self, b):
3630 pass
3631 sig = inspect.signature(test)
3632 ba = sig.bind(1, 2, 3)
3633 self.assertEqual(ba.args, (1, 2, 3))
3634 ba = sig.bind(1, self=2, b=3)
3635 self.assertEqual(ba.args, (1, 2, 3))
3636
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003637 def test_signature_bind_vararg_name(self):
3638 def test(a, *args):
3639 return a, args
3640 sig = inspect.signature(test)
3641
Yury Selivanov86872752015-05-19 00:27:49 -04003642 with self.assertRaisesRegex(
3643 TypeError, "got an unexpected keyword argument 'args'"):
3644
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003645 sig.bind(a=0, args=1)
3646
3647 def test(*args, **kwargs):
3648 return args, kwargs
3649 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3650
3651 sig = inspect.signature(test)
3652 ba = sig.bind(args=1)
3653 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3654
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003655 @cpython_only
3656 def test_signature_bind_implicit_arg(self):
3657 # Issue #19611: getcallargs should work with set comprehensions
3658 def make_set():
3659 return {z * z for z in range(5)}
3660 setcomp_code = make_set.__code__.co_consts[1]
3661 setcomp_func = types.FunctionType(setcomp_code, {})
3662
3663 iterator = iter(range(5))
3664 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3665
Pablo Galindof3ef06a2019-10-15 12:40:02 +01003666 def test_signature_bind_posonly_kwargs(self):
3667 def foo(bar, /, **kwargs):
3668 return bar, kwargs.get(bar)
3669
3670 sig = inspect.signature(foo)
3671 result = sig.bind("pos-only", bar="keyword")
3672
3673 self.assertEqual(result.kwargs, {"bar": "keyword"})
3674 self.assertIn(("bar", "pos-only"), result.arguments.items())
3675
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003676
3677class TestBoundArguments(unittest.TestCase):
3678 def test_signature_bound_arguments_unhashable(self):
3679 def foo(a): pass
3680 ba = inspect.signature(foo).bind(1)
3681
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003682 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003683 hash(ba)
3684
3685 def test_signature_bound_arguments_equality(self):
3686 def foo(a): pass
3687 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003688 self.assertTrue(ba == ba)
3689 self.assertFalse(ba != ba)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003690 self.assertTrue(ba == ALWAYS_EQ)
3691 self.assertFalse(ba != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003692
3693 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003694 self.assertTrue(ba == ba2)
3695 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003696
3697 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003698 self.assertFalse(ba == ba3)
3699 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003700 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003701 self.assertTrue(ba == ba3)
3702 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003703
3704 def bar(b): pass
3705 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003706 self.assertFalse(ba == ba4)
3707 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003708
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003709 def foo(*, a, b): pass
3710 sig = inspect.signature(foo)
3711 ba1 = sig.bind(a=1, b=2)
3712 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003713 self.assertTrue(ba1 == ba2)
3714 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003715
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003716 def test_signature_bound_arguments_pickle(self):
3717 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3718 sig = inspect.signature(foo)
3719 ba = sig.bind(20, 30, z={})
3720
3721 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3722 with self.subTest(pickle_ver=ver):
3723 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3724 self.assertEqual(ba, ba_pickled)
3725
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003726 def test_signature_bound_arguments_repr(self):
3727 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3728 sig = inspect.signature(foo)
3729 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003730 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003731
Yury Selivanovb907a512015-05-16 13:45:09 -04003732 def test_signature_bound_arguments_apply_defaults(self):
3733 def foo(a, b=1, *args, c:1={}, **kw): pass
3734 sig = inspect.signature(foo)
3735
3736 ba = sig.bind(20)
3737 ba.apply_defaults()
3738 self.assertEqual(
3739 list(ba.arguments.items()),
3740 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3741
3742 # Make sure that we preserve the order:
3743 # i.e. 'c' should be *before* 'kw'.
3744 ba = sig.bind(10, 20, 30, d=1)
3745 ba.apply_defaults()
3746 self.assertEqual(
3747 list(ba.arguments.items()),
3748 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3749
3750 # Make sure that BoundArguments produced by bind_partial()
3751 # are supported.
3752 def foo(a, b): pass
3753 sig = inspect.signature(foo)
3754 ba = sig.bind_partial(20)
3755 ba.apply_defaults()
3756 self.assertEqual(
3757 list(ba.arguments.items()),
3758 [('a', 20)])
3759
3760 # Test no args
3761 def foo(): pass
3762 sig = inspect.signature(foo)
3763 ba = sig.bind()
3764 ba.apply_defaults()
3765 self.assertEqual(list(ba.arguments.items()), [])
3766
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003767 # Make sure a no-args binding still acquires proper defaults.
3768 def foo(a='spam'): pass
3769 sig = inspect.signature(foo)
3770 ba = sig.bind()
3771 ba.apply_defaults()
3772 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3773
Rémi Lapeyre2cca8ef2020-01-28 13:47:03 +01003774 def test_signature_bound_arguments_arguments_type(self):
3775 def foo(a): pass
3776 ba = inspect.signature(foo).bind(1)
3777 self.assertIs(type(ba.arguments), dict)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003778
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003779class TestSignaturePrivateHelpers(unittest.TestCase):
3780 def test_signature_get_bound_param(self):
3781 getter = inspect._signature_get_bound_param
3782
3783 self.assertEqual(getter('($self)'), 'self')
3784 self.assertEqual(getter('($self, obj)'), 'self')
3785 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3786
Larry Hastings2623c8c2014-02-08 22:15:29 -08003787 def _strip_non_python_syntax(self, input,
3788 clean_signature, self_parameter, last_positional_only):
3789 computed_clean_signature, \
3790 computed_self_parameter, \
3791 computed_last_positional_only = \
3792 inspect._signature_strip_non_python_syntax(input)
3793 self.assertEqual(computed_clean_signature, clean_signature)
3794 self.assertEqual(computed_self_parameter, self_parameter)
3795 self.assertEqual(computed_last_positional_only, last_positional_only)
3796
3797 def test_signature_strip_non_python_syntax(self):
3798 self._strip_non_python_syntax(
3799 "($module, /, path, mode, *, dir_fd=None, " +
3800 "effective_ids=False,\n follow_symlinks=True)",
3801 "(module, path, mode, *, dir_fd=None, " +
3802 "effective_ids=False, follow_symlinks=True)",
3803 0,
3804 0)
3805
3806 self._strip_non_python_syntax(
3807 "($module, word, salt, /)",
3808 "(module, word, salt)",
3809 0,
3810 2)
3811
3812 self._strip_non_python_syntax(
3813 "(x, y=None, z=None, /)",
3814 "(x, y=None, z=None)",
3815 None,
3816 2)
3817
3818 self._strip_non_python_syntax(
3819 "(x, y=None, z=None)",
3820 "(x, y=None, z=None)",
3821 None,
3822 None)
3823
3824 self._strip_non_python_syntax(
3825 "(x,\n y=None,\n z = None )",
3826 "(x, y=None, z=None)",
3827 None,
3828 None)
3829
3830 self._strip_non_python_syntax(
3831 "",
3832 "",
3833 None,
3834 None)
3835
3836 self._strip_non_python_syntax(
3837 None,
3838 None,
3839 None,
3840 None)
3841
Nick Coghlan9c680b02015-04-13 12:54:54 -04003842class TestSignatureDefinitions(unittest.TestCase):
3843 # This test case provides a home for checking that particular APIs
3844 # have signatures available for introspection
3845
3846 @cpython_only
3847 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3848 "Signature information for builtins requires docstrings")
3849 def test_builtins_have_signatures(self):
3850 # This checks all builtin callables in CPython have signatures
3851 # A few have signatures Signature can't yet handle, so we skip those
3852 # since they will have to wait until PEP 457 adds the required
3853 # introspection support to the inspect module
3854 # Some others also haven't been converted yet for various other
3855 # reasons, so we also skip those for the time being, but design
3856 # the test to fail in order to indicate when it needs to be
3857 # updated.
3858 no_signature = set()
3859 # These need PEP 457 groups
3860 needs_groups = {"range", "slice", "dir", "getattr",
3861 "next", "iter", "vars"}
3862 no_signature |= needs_groups
Joshua Bronsonf0a6fde2021-03-23 18:47:21 -04003863 # These have unrepresentable parameter default values of NULL
3864 needs_null = {"anext"}
3865 no_signature |= needs_null
Nick Coghlan9c680b02015-04-13 12:54:54 -04003866 # These need PEP 457 groups or a signature change to accept None
3867 needs_semantic_update = {"round"}
3868 no_signature |= needs_semantic_update
3869 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003870 needs_varargs = {"breakpoint", "min", "max", "print",
3871 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003872 no_signature |= needs_varargs
3873 # These simply weren't covered in the initial AC conversion
3874 # for builtin callables
3875 not_converted_yet = {"open", "__import__"}
3876 no_signature |= not_converted_yet
3877 # These builtin types are expected to provide introspection info
3878 types_with_signatures = set()
3879 # Check the signatures we expect to be there
3880 ns = vars(builtins)
3881 for name, obj in sorted(ns.items()):
3882 if not callable(obj):
3883 continue
3884 # The builtin types haven't been converted to AC yet
3885 if isinstance(obj, type) and (name not in types_with_signatures):
3886 # Note that this also skips all the exception types
3887 no_signature.add(name)
3888 if (name in no_signature):
3889 # Not yet converted
3890 continue
3891 with self.subTest(builtin=name):
3892 self.assertIsNotNone(inspect.signature(obj))
3893 # Check callables that haven't been converted don't claim a signature
3894 # This ensures this test will start failing as more signatures are
3895 # added, so the affected items can be moved into the scope of the
3896 # regression test above
3897 for name in no_signature:
3898 with self.subTest(builtin=name):
3899 self.assertIsNone(obj.__text_signature__)
3900
Serhiy Storchakad53cf992019-05-06 22:40:27 +03003901 def test_python_function_override_signature(self):
3902 def func(*args, **kwargs):
3903 pass
3904 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
3905 sig = inspect.signature(func)
3906 self.assertIsNotNone(sig)
3907 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
3908 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
3909 sig = inspect.signature(func)
3910 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
3911
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003912
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003913class NTimesUnwrappable:
3914 def __init__(self, n):
3915 self.n = n
3916 self._next = None
3917
3918 @property
3919 def __wrapped__(self):
3920 if self.n <= 0:
3921 raise Exception("Unwrapped too many times")
3922 if self._next is None:
3923 self._next = NTimesUnwrappable(self.n - 1)
3924 return self._next
3925
Nick Coghlane8c45d62013-07-28 20:00:01 +10003926class TestUnwrap(unittest.TestCase):
3927
3928 def test_unwrap_one(self):
3929 def func(a, b):
3930 return a + b
3931 wrapper = functools.lru_cache(maxsize=20)(func)
3932 self.assertIs(inspect.unwrap(wrapper), func)
3933
3934 def test_unwrap_several(self):
3935 def func(a, b):
3936 return a + b
3937 wrapper = func
3938 for __ in range(10):
3939 @functools.wraps(wrapper)
3940 def wrapper():
3941 pass
3942 self.assertIsNot(wrapper.__wrapped__, func)
3943 self.assertIs(inspect.unwrap(wrapper), func)
3944
3945 def test_stop(self):
3946 def func1(a, b):
3947 return a + b
3948 @functools.wraps(func1)
3949 def func2():
3950 pass
3951 @functools.wraps(func2)
3952 def wrapper():
3953 pass
3954 func2.stop_here = 1
3955 unwrapped = inspect.unwrap(wrapper,
3956 stop=(lambda f: hasattr(f, "stop_here")))
3957 self.assertIs(unwrapped, func2)
3958
3959 def test_cycle(self):
3960 def func1(): pass
3961 func1.__wrapped__ = func1
3962 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3963 inspect.unwrap(func1)
3964
3965 def func2(): pass
3966 func2.__wrapped__ = func1
3967 func1.__wrapped__ = func2
3968 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3969 inspect.unwrap(func1)
3970 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3971 inspect.unwrap(func2)
3972
3973 def test_unhashable(self):
3974 def func(): pass
3975 func.__wrapped__ = None
3976 class C:
3977 __hash__ = None
3978 __wrapped__ = func
3979 self.assertIsNone(inspect.unwrap(C()))
3980
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003981 def test_recursion_limit(self):
3982 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3983 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3984 inspect.unwrap(obj)
3985
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003986class TestMain(unittest.TestCase):
3987 def test_only_source(self):
3988 module = importlib.import_module('unittest')
3989 rc, out, err = assert_python_ok('-m', 'inspect',
3990 'unittest')
3991 lines = out.decode().splitlines()
3992 # ignore the final newline
3993 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3994 self.assertEqual(err, b'')
3995
Yury Selivanov42407ab2014-06-23 10:23:50 -07003996 def test_custom_getattr(self):
3997 def foo():
3998 pass
3999 foo.__signature__ = 42
4000 with self.assertRaises(TypeError):
4001 inspect.signature(foo)
4002
Brett Cannon634a8fc2013-10-02 10:25:42 -04004003 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04004004 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004005 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004006 rc, out, err = assert_python_ok('-m', 'inspect',
4007 'concurrent.futures:ThreadPoolExecutor')
4008 lines = out.decode().splitlines()
4009 # ignore the final newline
4010 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04004011 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004012 self.assertEqual(err, b'')
4013
4014 def test_builtins(self):
4015 module = importlib.import_module('unittest')
4016 _, out, err = assert_python_failure('-m', 'inspect',
4017 'sys')
4018 lines = err.decode().splitlines()
4019 self.assertEqual(lines, ["Can't get info for builtin modules."])
4020
4021 def test_details(self):
4022 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01004023 args = support.optim_args_from_interpreter_flags()
4024 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004025 'unittest', '--details')
4026 output = out.decode()
4027 # Just a quick sanity check on the output
4028 self.assertIn(module.__name__, output)
4029 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01004030 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004031 self.assertEqual(err, b'')
4032
4033
Yury Selivanovef1e7502014-12-08 16:05:34 -05004034class TestReload(unittest.TestCase):
4035
4036 src_before = textwrap.dedent("""\
4037def foo():
4038 print("Bla")
4039 """)
4040
4041 src_after = textwrap.dedent("""\
4042def foo():
4043 print("Oh no!")
4044 """)
4045
4046 def assertInspectEqual(self, path, source):
4047 inspected_src = inspect.getsource(source)
Inada Naokifb786922021-04-06 11:18:41 +09004048 with open(path, encoding='utf-8') as src:
Yury Selivanovef1e7502014-12-08 16:05:34 -05004049 self.assertEqual(
4050 src.read().splitlines(True),
4051 inspected_src.splitlines(True)
4052 )
4053
4054 def test_getsource_reload(self):
4055 # see issue 1218234
4056 with _ready_to_import('reload_bug', self.src_before) as (name, path):
4057 module = importlib.import_module(name)
4058 self.assertInspectEqual(path, module)
Inada Naokifb786922021-04-06 11:18:41 +09004059 with open(path, 'w', encoding='utf-8') as src:
Yury Selivanovef1e7502014-12-08 16:05:34 -05004060 src.write(self.src_after)
4061 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004062
Nick Coghlane8c45d62013-07-28 20:00:01 +10004063
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004064def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00004065 run_unittest(
Irit Katriel6e1eec72020-12-04 16:45:38 +00004066 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBlockComments,
4067 TestBuggyCases, TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00004068 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00004069 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004070 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04004071 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04004072 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04004073 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07004074 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00004075 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00004076
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004077if __name__ == "__main__":
4078 test_main()