blob: b32b3d3757750eed602b6caa42bd4c97cf205b4f [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},
Pablo Galindob0544ba2021-04-21 12:41:19 +0100891 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"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002240 ('b', ..., '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"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002256 ('b', 10, 'foo', "positional_or_keyword"),
2257 ('args', ..., 'bar', "var_positional"),
2258 ('spam', ..., 'baz', "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002259 ('ham', 123, ..., "keyword_only"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002260 ('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"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002669 ('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)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002673 ((('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')),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002793 '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')),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002798 '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),
Pablo Galindob0544ba2021-04-21 12:41:19 +01002807 ((('self', ..., '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
Pablo Galindob0544ba2021-04-21 12:41:19 +01003145 def foo(a) -> {}: pass
3146 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3147 hash(inspect.signature(foo))
3148
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003149 def test_signature_str(self):
3150 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3151 pass
3152 self.assertEqual(str(inspect.signature(foo)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003153 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003154
3155 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3156 pass
3157 self.assertEqual(str(inspect.signature(foo)),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003158 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003159
3160 def foo():
3161 pass
3162 self.assertEqual(str(inspect.signature(foo)), '()')
3163
3164 def test_signature_str_positional_only(self):
3165 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003166 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003167
3168 def test(a_po, *, b, **kwargs):
3169 return a_po, kwargs
3170
3171 sig = inspect.signature(test)
3172 new_params = list(sig.parameters.values())
3173 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3174 test.__signature__ = sig.replace(parameters=new_params)
3175
3176 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003177 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003178
Yury Selivanov2393dca2014-01-27 15:07:58 -05003179 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3180 '(foo, /)')
3181
3182 self.assertEqual(str(S(parameters=[
3183 P('foo', P.POSITIONAL_ONLY),
3184 P('bar', P.VAR_KEYWORD)])),
3185 '(foo, /, **bar)')
3186
3187 self.assertEqual(str(S(parameters=[
3188 P('foo', P.POSITIONAL_ONLY),
3189 P('bar', P.VAR_POSITIONAL)])),
3190 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003191
3192 def test_signature_replace_anno(self):
3193 def test() -> 42:
3194 pass
3195
3196 sig = inspect.signature(test)
3197 sig = sig.replace(return_annotation=None)
3198 self.assertIs(sig.return_annotation, None)
3199 sig = sig.replace(return_annotation=sig.empty)
3200 self.assertIs(sig.return_annotation, sig.empty)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003201 sig = sig.replace(return_annotation=42)
3202 self.assertEqual(sig.return_annotation, 42)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003203 self.assertEqual(sig, inspect.signature(test))
3204
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003205 def test_signature_on_mangled_parameters(self):
3206 class Spam:
3207 def foo(self, __p1:1=2, *, __p2:2=3):
3208 pass
3209 class Ham(Spam):
3210 pass
3211
3212 self.assertEqual(self.signature(Spam.foo),
3213 ((('self', ..., ..., "positional_or_keyword"),
Pablo Galindob0544ba2021-04-21 12:41:19 +01003214 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3215 ('_Spam__p2', 3, 2, "keyword_only")),
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003216 ...))
3217
3218 self.assertEqual(self.signature(Spam.foo),
3219 self.signature(Ham.foo))
3220
Yury Selivanovda396452014-03-27 12:09:24 -04003221 def test_signature_from_callable_python_obj(self):
3222 class MySignature(inspect.Signature): pass
3223 def foo(a, *, b:1): pass
3224 foo_sig = MySignature.from_callable(foo)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003225 self.assertIsInstance(foo_sig, MySignature)
3226
3227 def test_signature_from_callable_class(self):
3228 # A regression test for a class inheriting its signature from `object`.
3229 class MySignature(inspect.Signature): pass
3230 class foo: pass
3231 foo_sig = MySignature.from_callable(foo)
3232 self.assertIsInstance(foo_sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003233
3234 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3235 "Signature information for builtins requires docstrings")
3236 def test_signature_from_callable_builtin_obj(self):
3237 class MySignature(inspect.Signature): pass
3238 sig = MySignature.from_callable(_pickle.Pickler)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003239 self.assertIsInstance(sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003240
larryhastingsf36ba122018-01-28 11:13:09 -08003241 def test_signature_definition_order_preserved_on_kwonly(self):
3242 for fn in signatures_with_lexicographic_keyword_only_parameters():
3243 signature = inspect.signature(fn)
3244 l = list(signature.parameters)
3245 sorted_l = sorted(l)
3246 self.assertTrue(l)
3247 self.assertEqual(l, sorted_l)
3248 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3249 l = list(signature.parameters)
3250 self.assertEqual(l, unsorted_keyword_only_parameters)
3251
Jens Reidel611836a2020-03-18 03:22:46 +01003252 def test_signater_parameters_is_ordered(self):
3253 p1 = inspect.signature(lambda x, y: None).parameters
3254 p2 = inspect.signature(lambda y, x: None).parameters
3255 self.assertNotEqual(p1, p2)
3256
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003257 def test_signature_annotations_with_local_namespaces(self):
3258 class Foo: ...
3259 def func(foo: Foo) -> int: pass
Pablo Galindob0544ba2021-04-21 12:41:19 +01003260 def func2(foo: Foo, bar: 'Bar') -> int: pass
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003261
3262 for signature_func in (inspect.signature, inspect.Signature.from_callable):
3263 with self.subTest(signature_func = signature_func):
3264 sig1 = signature_func(func)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003265 self.assertEqual(sig1.return_annotation, int)
3266 self.assertEqual(sig1.parameters['foo'].annotation, Foo)
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003267
3268 sig2 = signature_func(func, localns=locals())
3269 self.assertEqual(sig2.return_annotation, int)
3270 self.assertEqual(sig2.parameters['foo'].annotation, Foo)
3271
3272 sig3 = signature_func(func2, globalns={'Bar': int}, localns=locals())
3273 self.assertEqual(sig3.return_annotation, int)
3274 self.assertEqual(sig3.parameters['foo'].annotation, Foo)
Pablo Galindob0544ba2021-04-21 12:41:19 +01003275 self.assertEqual(sig3.parameters['bar'].annotation, 'Bar')
Batuhan Taskayaeee1c772020-12-24 01:45:13 +03003276
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003277
3278class TestParameterObject(unittest.TestCase):
3279 def test_signature_parameter_kinds(self):
3280 P = inspect.Parameter
3281 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3282 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3283
3284 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3285 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3286
3287 def test_signature_parameter_object(self):
3288 p = inspect.Parameter('foo', default=10,
3289 kind=inspect.Parameter.POSITIONAL_ONLY)
3290 self.assertEqual(p.name, 'foo')
3291 self.assertEqual(p.default, 10)
3292 self.assertIs(p.annotation, p.empty)
3293 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3294
Dong-hee Naa9cab432018-05-30 00:04:08 +09003295 with self.assertRaisesRegex(ValueError, "value '123' is "
3296 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003297 inspect.Parameter('foo', default=10, kind='123')
3298
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003299 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003300 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3301
Yury Selivanov2393dca2014-01-27 15:07:58 -05003302 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003303 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3304
Yury Selivanov2393dca2014-01-27 15:07:58 -05003305 with self.assertRaisesRegex(ValueError,
3306 'is not a valid parameter name'):
3307 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3308
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003309 with self.assertRaisesRegex(ValueError,
3310 'is not a valid parameter name'):
3311 inspect.Parameter('.a', 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_KEYWORD)
3316
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003317 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003318 inspect.Parameter('a', default=42,
3319 kind=inspect.Parameter.VAR_POSITIONAL)
3320
3321 p = inspect.Parameter('a', default=42,
3322 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003323 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003324 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3325
3326 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003327 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003328
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003329 def test_signature_parameter_hashable(self):
3330 P = inspect.Parameter
3331 foo = P('foo', kind=P.POSITIONAL_ONLY)
3332 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3333 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3334 default=42)))
3335 self.assertNotEqual(hash(foo),
3336 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3337
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003338 def test_signature_parameter_equality(self):
3339 P = inspect.Parameter
3340 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3341
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003342 self.assertTrue(p == p)
3343 self.assertFalse(p != p)
3344 self.assertFalse(p == 42)
3345 self.assertTrue(p != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003346 self.assertTrue(p == ALWAYS_EQ)
3347 self.assertFalse(p != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003348
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003349 self.assertTrue(p == P('foo', default=42,
3350 kind=inspect.Parameter.KEYWORD_ONLY))
3351 self.assertFalse(p != P('foo', default=42,
3352 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003353
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003354 def test_signature_parameter_replace(self):
3355 p = inspect.Parameter('foo', default=42,
3356 kind=inspect.Parameter.KEYWORD_ONLY)
3357
3358 self.assertIsNot(p, p.replace())
3359 self.assertEqual(p, p.replace())
3360
3361 p2 = p.replace(annotation=1)
3362 self.assertEqual(p2.annotation, 1)
3363 p2 = p2.replace(annotation=p2.empty)
3364 self.assertEqual(p, p2)
3365
3366 p2 = p2.replace(name='bar')
3367 self.assertEqual(p2.name, 'bar')
3368 self.assertNotEqual(p2, p)
3369
Yury Selivanov2393dca2014-01-27 15:07:58 -05003370 with self.assertRaisesRegex(ValueError,
3371 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003372 p2 = p2.replace(name=p2.empty)
3373
3374 p2 = p2.replace(name='foo', default=None)
3375 self.assertIs(p2.default, None)
3376 self.assertNotEqual(p2, p)
3377
3378 p2 = p2.replace(name='foo', default=p2.empty)
3379 self.assertIs(p2.default, p2.empty)
3380
3381
3382 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3383 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3384 self.assertNotEqual(p2, p)
3385
Dong-hee Naa9cab432018-05-30 00:04:08 +09003386 with self.assertRaisesRegex(ValueError,
3387 "value <class 'inspect._empty'> "
3388 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003389 p2 = p2.replace(kind=p2.empty)
3390
3391 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3392 self.assertEqual(p2, p)
3393
3394 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003395 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3396 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003397
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003398 @cpython_only
3399 def test_signature_parameter_implicit(self):
3400 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003401 'implicit arguments must be passed as '
3402 'positional or keyword arguments, '
3403 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003404 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3405
3406 param = inspect.Parameter(
3407 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3408 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3409 self.assertEqual(param.name, 'implicit0')
3410
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003411 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003412 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003413
3414 with self.assertRaises(AttributeError):
3415 p.foo = 'bar'
3416
3417 with self.assertRaises(AttributeError):
3418 p.kind = 123
3419
3420
3421class TestSignatureBind(unittest.TestCase):
3422 @staticmethod
3423 def call(func, *args, **kwargs):
3424 sig = inspect.signature(func)
3425 ba = sig.bind(*args, **kwargs)
3426 return func(*ba.args, **ba.kwargs)
3427
3428 def test_signature_bind_empty(self):
3429 def test():
3430 return 42
3431
3432 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003433 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003434 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003435 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003436 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003437 with self.assertRaisesRegex(
3438 TypeError, "got an unexpected keyword argument 'spam'"):
3439
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003440 self.call(test, spam=1)
3441
3442 def test_signature_bind_var(self):
3443 def test(*args, **kwargs):
3444 return args, kwargs
3445
3446 self.assertEqual(self.call(test), ((), {}))
3447 self.assertEqual(self.call(test, 1), ((1,), {}))
3448 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3449 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3450 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3451 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3452 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3453 ((1, 2), {'foo': 'bar'}))
3454
3455 def test_signature_bind_just_args(self):
3456 def test(a, b, c):
3457 return a, b, c
3458
3459 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3460
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003461 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003462 self.call(test, 1, 2, 3, 4)
3463
Yury Selivanov86872752015-05-19 00:27:49 -04003464 with self.assertRaisesRegex(TypeError,
3465 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003466 self.call(test, 1)
3467
Yury Selivanov86872752015-05-19 00:27:49 -04003468 with self.assertRaisesRegex(TypeError,
3469 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003470 self.call(test)
3471
3472 def test(a, b, c=10):
3473 return a, b, c
3474 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3475 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3476
3477 def test(a=1, b=2, c=3):
3478 return a, b, c
3479 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3480 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3481 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3482
3483 def test_signature_bind_varargs_order(self):
3484 def test(*args):
3485 return args
3486
3487 self.assertEqual(self.call(test), ())
3488 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3489
3490 def test_signature_bind_args_and_varargs(self):
3491 def test(a, b, c=3, *args):
3492 return a, b, c, args
3493
3494 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3495 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3496 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3497 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3498
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003499 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003500 "multiple values for argument 'c'"):
3501 self.call(test, 1, 2, 3, c=4)
3502
3503 def test_signature_bind_just_kwargs(self):
3504 def test(**kwargs):
3505 return kwargs
3506
3507 self.assertEqual(self.call(test), {})
3508 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3509 {'foo': 'bar', 'spam': 'ham'})
3510
3511 def test_signature_bind_args_and_kwargs(self):
3512 def test(a, b, c=3, **kwargs):
3513 return a, b, c, kwargs
3514
3515 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3516 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3517 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3518 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3519 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3520 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3521 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3522 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3523 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3524 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3525 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3526 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3527 (1, 2, 4, {'foo': 'bar'}))
3528 self.assertEqual(self.call(test, c=5, a=4, b=3),
3529 (4, 3, 5, {}))
3530
3531 def test_signature_bind_kwonly(self):
3532 def test(*, foo):
3533 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003534 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003535 'too many positional arguments'):
3536 self.call(test, 1)
3537 self.assertEqual(self.call(test, foo=1), 1)
3538
3539 def test(a, *, foo=1, bar):
3540 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003541 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003542 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003543 self.call(test, 1)
3544
3545 def test(foo, *, bar):
3546 return foo, bar
3547 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3548 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3549
Yury Selivanov86872752015-05-19 00:27:49 -04003550 with self.assertRaisesRegex(
3551 TypeError, "got an unexpected keyword argument 'spam'"):
3552
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003553 self.call(test, bar=2, foo=1, spam=10)
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)
3558
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003559 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003560 'too many positional arguments'):
3561 self.call(test, 1, 2, bar=2)
3562
Yury Selivanov86872752015-05-19 00:27:49 -04003563 with self.assertRaisesRegex(
3564 TypeError, "got an unexpected keyword argument 'spam'"):
3565
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003566 self.call(test, 1, bar=2, spam='ham')
3567
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003568 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003569 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003570 self.call(test, 1)
3571
3572 def test(foo, *, bar, **bin):
3573 return foo, bar, bin
3574 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3575 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3576 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3577 (1, 2, {'spam': 'ham'}))
3578 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3579 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003580 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003581 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003582 self.call(test, spam='ham', bar=2)
3583 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3584 (1, 2, {'bin': 1, 'spam': 10}))
3585
3586 def test_signature_bind_arguments(self):
3587 def test(a, *args, b, z=100, **kwargs):
3588 pass
3589 sig = inspect.signature(test)
3590 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3591 # we won't have 'z' argument in the bound arguments object, as we didn't
3592 # pass it to the 'bind'
3593 self.assertEqual(tuple(ba.arguments.items()),
3594 (('a', 10), ('args', (20,)), ('b', 30),
3595 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3596 self.assertEqual(ba.kwargs,
3597 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3598 self.assertEqual(ba.args, (10, 20))
3599
3600 def test_signature_bind_positional_only(self):
3601 P = inspect.Parameter
3602
3603 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3604 return a_po, b_po, c_po, foo, bar, kwargs
3605
3606 sig = inspect.signature(test)
3607 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3608 for name in ('a_po', 'b_po', 'c_po'):
3609 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3610 new_sig = sig.replace(parameters=new_params.values())
3611 test.__signature__ = new_sig
3612
3613 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3614 (1, 2, 4, 5, 6, {}))
3615
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003616 self.assertEqual(self.call(test, 1, 2),
3617 (1, 2, 3, 42, 50, {}))
3618
3619 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3620 (1, 2, 3, 4, 5, {}))
3621
3622 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3623 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3624
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003625 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003626 self.call(test, 1, 2, c_po=4)
3627
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003628 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003629 self.call(test, a_po=1, b_po=2)
3630
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003631 def test_signature_bind_with_self_arg(self):
3632 # Issue #17071: one of the parameters is named "self
3633 def test(a, self, b):
3634 pass
3635 sig = inspect.signature(test)
3636 ba = sig.bind(1, 2, 3)
3637 self.assertEqual(ba.args, (1, 2, 3))
3638 ba = sig.bind(1, self=2, b=3)
3639 self.assertEqual(ba.args, (1, 2, 3))
3640
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003641 def test_signature_bind_vararg_name(self):
3642 def test(a, *args):
3643 return a, args
3644 sig = inspect.signature(test)
3645
Yury Selivanov86872752015-05-19 00:27:49 -04003646 with self.assertRaisesRegex(
3647 TypeError, "got an unexpected keyword argument 'args'"):
3648
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003649 sig.bind(a=0, args=1)
3650
3651 def test(*args, **kwargs):
3652 return args, kwargs
3653 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3654
3655 sig = inspect.signature(test)
3656 ba = sig.bind(args=1)
3657 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3658
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003659 @cpython_only
3660 def test_signature_bind_implicit_arg(self):
3661 # Issue #19611: getcallargs should work with set comprehensions
3662 def make_set():
3663 return {z * z for z in range(5)}
3664 setcomp_code = make_set.__code__.co_consts[1]
3665 setcomp_func = types.FunctionType(setcomp_code, {})
3666
3667 iterator = iter(range(5))
3668 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3669
Pablo Galindof3ef06a2019-10-15 12:40:02 +01003670 def test_signature_bind_posonly_kwargs(self):
3671 def foo(bar, /, **kwargs):
3672 return bar, kwargs.get(bar)
3673
3674 sig = inspect.signature(foo)
3675 result = sig.bind("pos-only", bar="keyword")
3676
3677 self.assertEqual(result.kwargs, {"bar": "keyword"})
3678 self.assertIn(("bar", "pos-only"), result.arguments.items())
3679
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003680
3681class TestBoundArguments(unittest.TestCase):
3682 def test_signature_bound_arguments_unhashable(self):
3683 def foo(a): pass
3684 ba = inspect.signature(foo).bind(1)
3685
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003686 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003687 hash(ba)
3688
3689 def test_signature_bound_arguments_equality(self):
3690 def foo(a): pass
3691 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003692 self.assertTrue(ba == ba)
3693 self.assertFalse(ba != ba)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003694 self.assertTrue(ba == ALWAYS_EQ)
3695 self.assertFalse(ba != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003696
3697 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003698 self.assertTrue(ba == ba2)
3699 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003700
3701 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003702 self.assertFalse(ba == ba3)
3703 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003704 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003705 self.assertTrue(ba == ba3)
3706 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003707
3708 def bar(b): pass
3709 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003710 self.assertFalse(ba == ba4)
3711 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003712
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003713 def foo(*, a, b): pass
3714 sig = inspect.signature(foo)
3715 ba1 = sig.bind(a=1, b=2)
3716 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003717 self.assertTrue(ba1 == ba2)
3718 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003719
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003720 def test_signature_bound_arguments_pickle(self):
3721 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3722 sig = inspect.signature(foo)
3723 ba = sig.bind(20, 30, z={})
3724
3725 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3726 with self.subTest(pickle_ver=ver):
3727 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3728 self.assertEqual(ba, ba_pickled)
3729
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003730 def test_signature_bound_arguments_repr(self):
3731 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3732 sig = inspect.signature(foo)
3733 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003734 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003735
Yury Selivanovb907a512015-05-16 13:45:09 -04003736 def test_signature_bound_arguments_apply_defaults(self):
3737 def foo(a, b=1, *args, c:1={}, **kw): pass
3738 sig = inspect.signature(foo)
3739
3740 ba = sig.bind(20)
3741 ba.apply_defaults()
3742 self.assertEqual(
3743 list(ba.arguments.items()),
3744 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3745
3746 # Make sure that we preserve the order:
3747 # i.e. 'c' should be *before* 'kw'.
3748 ba = sig.bind(10, 20, 30, d=1)
3749 ba.apply_defaults()
3750 self.assertEqual(
3751 list(ba.arguments.items()),
3752 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3753
3754 # Make sure that BoundArguments produced by bind_partial()
3755 # are supported.
3756 def foo(a, b): pass
3757 sig = inspect.signature(foo)
3758 ba = sig.bind_partial(20)
3759 ba.apply_defaults()
3760 self.assertEqual(
3761 list(ba.arguments.items()),
3762 [('a', 20)])
3763
3764 # Test no args
3765 def foo(): pass
3766 sig = inspect.signature(foo)
3767 ba = sig.bind()
3768 ba.apply_defaults()
3769 self.assertEqual(list(ba.arguments.items()), [])
3770
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003771 # Make sure a no-args binding still acquires proper defaults.
3772 def foo(a='spam'): pass
3773 sig = inspect.signature(foo)
3774 ba = sig.bind()
3775 ba.apply_defaults()
3776 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3777
Rémi Lapeyre2cca8ef2020-01-28 13:47:03 +01003778 def test_signature_bound_arguments_arguments_type(self):
3779 def foo(a): pass
3780 ba = inspect.signature(foo).bind(1)
3781 self.assertIs(type(ba.arguments), dict)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003782
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003783class TestSignaturePrivateHelpers(unittest.TestCase):
3784 def test_signature_get_bound_param(self):
3785 getter = inspect._signature_get_bound_param
3786
3787 self.assertEqual(getter('($self)'), 'self')
3788 self.assertEqual(getter('($self, obj)'), 'self')
3789 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3790
Larry Hastings2623c8c2014-02-08 22:15:29 -08003791 def _strip_non_python_syntax(self, input,
3792 clean_signature, self_parameter, last_positional_only):
3793 computed_clean_signature, \
3794 computed_self_parameter, \
3795 computed_last_positional_only = \
3796 inspect._signature_strip_non_python_syntax(input)
3797 self.assertEqual(computed_clean_signature, clean_signature)
3798 self.assertEqual(computed_self_parameter, self_parameter)
3799 self.assertEqual(computed_last_positional_only, last_positional_only)
3800
3801 def test_signature_strip_non_python_syntax(self):
3802 self._strip_non_python_syntax(
3803 "($module, /, path, mode, *, dir_fd=None, " +
3804 "effective_ids=False,\n follow_symlinks=True)",
3805 "(module, path, mode, *, dir_fd=None, " +
3806 "effective_ids=False, follow_symlinks=True)",
3807 0,
3808 0)
3809
3810 self._strip_non_python_syntax(
3811 "($module, word, salt, /)",
3812 "(module, word, salt)",
3813 0,
3814 2)
3815
3816 self._strip_non_python_syntax(
3817 "(x, y=None, z=None, /)",
3818 "(x, y=None, z=None)",
3819 None,
3820 2)
3821
3822 self._strip_non_python_syntax(
3823 "(x, y=None, z=None)",
3824 "(x, y=None, z=None)",
3825 None,
3826 None)
3827
3828 self._strip_non_python_syntax(
3829 "(x,\n y=None,\n z = None )",
3830 "(x, y=None, z=None)",
3831 None,
3832 None)
3833
3834 self._strip_non_python_syntax(
3835 "",
3836 "",
3837 None,
3838 None)
3839
3840 self._strip_non_python_syntax(
3841 None,
3842 None,
3843 None,
3844 None)
3845
Nick Coghlan9c680b02015-04-13 12:54:54 -04003846class TestSignatureDefinitions(unittest.TestCase):
3847 # This test case provides a home for checking that particular APIs
3848 # have signatures available for introspection
3849
3850 @cpython_only
3851 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3852 "Signature information for builtins requires docstrings")
3853 def test_builtins_have_signatures(self):
3854 # This checks all builtin callables in CPython have signatures
3855 # A few have signatures Signature can't yet handle, so we skip those
3856 # since they will have to wait until PEP 457 adds the required
3857 # introspection support to the inspect module
3858 # Some others also haven't been converted yet for various other
3859 # reasons, so we also skip those for the time being, but design
3860 # the test to fail in order to indicate when it needs to be
3861 # updated.
3862 no_signature = set()
3863 # These need PEP 457 groups
3864 needs_groups = {"range", "slice", "dir", "getattr",
3865 "next", "iter", "vars"}
3866 no_signature |= needs_groups
Joshua Bronsonf0a6fde2021-03-23 18:47:21 -04003867 # These have unrepresentable parameter default values of NULL
3868 needs_null = {"anext"}
3869 no_signature |= needs_null
Nick Coghlan9c680b02015-04-13 12:54:54 -04003870 # These need PEP 457 groups or a signature change to accept None
3871 needs_semantic_update = {"round"}
3872 no_signature |= needs_semantic_update
3873 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003874 needs_varargs = {"breakpoint", "min", "max", "print",
3875 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003876 no_signature |= needs_varargs
3877 # These simply weren't covered in the initial AC conversion
3878 # for builtin callables
3879 not_converted_yet = {"open", "__import__"}
3880 no_signature |= not_converted_yet
3881 # These builtin types are expected to provide introspection info
3882 types_with_signatures = set()
3883 # Check the signatures we expect to be there
3884 ns = vars(builtins)
3885 for name, obj in sorted(ns.items()):
3886 if not callable(obj):
3887 continue
3888 # The builtin types haven't been converted to AC yet
3889 if isinstance(obj, type) and (name not in types_with_signatures):
3890 # Note that this also skips all the exception types
3891 no_signature.add(name)
3892 if (name in no_signature):
3893 # Not yet converted
3894 continue
3895 with self.subTest(builtin=name):
3896 self.assertIsNotNone(inspect.signature(obj))
3897 # Check callables that haven't been converted don't claim a signature
3898 # This ensures this test will start failing as more signatures are
3899 # added, so the affected items can be moved into the scope of the
3900 # regression test above
3901 for name in no_signature:
3902 with self.subTest(builtin=name):
3903 self.assertIsNone(obj.__text_signature__)
3904
Serhiy Storchakad53cf992019-05-06 22:40:27 +03003905 def test_python_function_override_signature(self):
3906 def func(*args, **kwargs):
3907 pass
3908 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
3909 sig = inspect.signature(func)
3910 self.assertIsNotNone(sig)
3911 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
3912 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
3913 sig = inspect.signature(func)
3914 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
3915
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003916
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003917class NTimesUnwrappable:
3918 def __init__(self, n):
3919 self.n = n
3920 self._next = None
3921
3922 @property
3923 def __wrapped__(self):
3924 if self.n <= 0:
3925 raise Exception("Unwrapped too many times")
3926 if self._next is None:
3927 self._next = NTimesUnwrappable(self.n - 1)
3928 return self._next
3929
Nick Coghlane8c45d62013-07-28 20:00:01 +10003930class TestUnwrap(unittest.TestCase):
3931
3932 def test_unwrap_one(self):
3933 def func(a, b):
3934 return a + b
3935 wrapper = functools.lru_cache(maxsize=20)(func)
3936 self.assertIs(inspect.unwrap(wrapper), func)
3937
3938 def test_unwrap_several(self):
3939 def func(a, b):
3940 return a + b
3941 wrapper = func
3942 for __ in range(10):
3943 @functools.wraps(wrapper)
3944 def wrapper():
3945 pass
3946 self.assertIsNot(wrapper.__wrapped__, func)
3947 self.assertIs(inspect.unwrap(wrapper), func)
3948
3949 def test_stop(self):
3950 def func1(a, b):
3951 return a + b
3952 @functools.wraps(func1)
3953 def func2():
3954 pass
3955 @functools.wraps(func2)
3956 def wrapper():
3957 pass
3958 func2.stop_here = 1
3959 unwrapped = inspect.unwrap(wrapper,
3960 stop=(lambda f: hasattr(f, "stop_here")))
3961 self.assertIs(unwrapped, func2)
3962
3963 def test_cycle(self):
3964 def func1(): pass
3965 func1.__wrapped__ = func1
3966 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3967 inspect.unwrap(func1)
3968
3969 def func2(): pass
3970 func2.__wrapped__ = func1
3971 func1.__wrapped__ = func2
3972 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3973 inspect.unwrap(func1)
3974 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3975 inspect.unwrap(func2)
3976
3977 def test_unhashable(self):
3978 def func(): pass
3979 func.__wrapped__ = None
3980 class C:
3981 __hash__ = None
3982 __wrapped__ = func
3983 self.assertIsNone(inspect.unwrap(C()))
3984
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003985 def test_recursion_limit(self):
3986 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3987 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3988 inspect.unwrap(obj)
3989
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003990class TestMain(unittest.TestCase):
3991 def test_only_source(self):
3992 module = importlib.import_module('unittest')
3993 rc, out, err = assert_python_ok('-m', 'inspect',
3994 'unittest')
3995 lines = out.decode().splitlines()
3996 # ignore the final newline
3997 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3998 self.assertEqual(err, b'')
3999
Yury Selivanov42407ab2014-06-23 10:23:50 -07004000 def test_custom_getattr(self):
4001 def foo():
4002 pass
4003 foo.__signature__ = 42
4004 with self.assertRaises(TypeError):
4005 inspect.signature(foo)
4006
Brett Cannon634a8fc2013-10-02 10:25:42 -04004007 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04004008 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004009 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004010 rc, out, err = assert_python_ok('-m', 'inspect',
4011 'concurrent.futures:ThreadPoolExecutor')
4012 lines = out.decode().splitlines()
4013 # ignore the final newline
4014 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04004015 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004016 self.assertEqual(err, b'')
4017
4018 def test_builtins(self):
4019 module = importlib.import_module('unittest')
4020 _, out, err = assert_python_failure('-m', 'inspect',
4021 'sys')
4022 lines = err.decode().splitlines()
4023 self.assertEqual(lines, ["Can't get info for builtin modules."])
4024
4025 def test_details(self):
4026 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01004027 args = support.optim_args_from_interpreter_flags()
4028 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004029 'unittest', '--details')
4030 output = out.decode()
4031 # Just a quick sanity check on the output
4032 self.assertIn(module.__name__, output)
4033 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01004034 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004035 self.assertEqual(err, b'')
4036
4037
Yury Selivanovef1e7502014-12-08 16:05:34 -05004038class TestReload(unittest.TestCase):
4039
4040 src_before = textwrap.dedent("""\
4041def foo():
4042 print("Bla")
4043 """)
4044
4045 src_after = textwrap.dedent("""\
4046def foo():
4047 print("Oh no!")
4048 """)
4049
4050 def assertInspectEqual(self, path, source):
4051 inspected_src = inspect.getsource(source)
Inada Naokifb786922021-04-06 11:18:41 +09004052 with open(path, encoding='utf-8') as src:
Yury Selivanovef1e7502014-12-08 16:05:34 -05004053 self.assertEqual(
4054 src.read().splitlines(True),
4055 inspected_src.splitlines(True)
4056 )
4057
4058 def test_getsource_reload(self):
4059 # see issue 1218234
4060 with _ready_to_import('reload_bug', self.src_before) as (name, path):
4061 module = importlib.import_module(name)
4062 self.assertInspectEqual(path, module)
Inada Naokifb786922021-04-06 11:18:41 +09004063 with open(path, 'w', encoding='utf-8') as src:
Yury Selivanovef1e7502014-12-08 16:05:34 -05004064 src.write(self.src_after)
4065 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004066
Nick Coghlane8c45d62013-07-28 20:00:01 +10004067
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004068def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00004069 run_unittest(
Irit Katriel6e1eec72020-12-04 16:45:38 +00004070 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBlockComments,
4071 TestBuggyCases, TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00004072 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00004073 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004074 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04004075 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04004076 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04004077 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07004078 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00004079 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00004080
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004081if __name__ == "__main__":
4082 test_main()