blob: 98a9c0a662a0939aa74e58b6a8a3f872d6cc490b [file] [log] [blame]
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001import builtins
Guido van Rossum813b0e52007-05-21 18:11:34 +00002import collections
Larry Hastings5c661892014-01-24 06:17:25 -08003import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10004import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10005import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08006import inspect
7import io
8import linecache
9import os
Christian Heimesa3538eb2007-11-06 11:44:48 +000010from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080011import _pickle
Yury Selivanova5d63dd2014-03-27 11:31:43 -040012import pickle
Larry Hastings5c661892014-01-24 06:17:25 -080013import shutil
14import sys
15import types
Yury Selivanovef1e7502014-12-08 16:05:34 -050016import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080017import unicodedata
18import unittest
Yury Selivanova773de02014-02-21 18:30:53 -050019import unittest.mock
Yury Selivanov75445082015-05-11 22:57:16 -040020import warnings
Larry Hastings5c661892014-01-24 06:17:25 -080021
Brett Cannon634a8fc2013-10-02 10:25:42 -040022try:
23 from concurrent.futures import ThreadPoolExecutor
24except ImportError:
25 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000026
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020027from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +030028from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ
Berker Peksagce643912015-05-06 06:33:17 +030029from test.support.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000030from test import inspect_fodder as mod
31from test import inspect_fodder2 as mod2
Victor Stinner9def2842016-01-18 12:15:08 +010032from test import support
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000033
Yury Selivanovef1e7502014-12-08 16:05:34 -050034from test.test_import import _ready_to_import
35
R. David Murray74b89242009-05-13 17:33:03 +000036
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000037# Functions tested in this suite:
38# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000039# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
40# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
Berker Peksagfa3922c2015-07-31 04:11:29 +030041# getclasstree, getargvalues, formatargspec, formatargvalues,
Christian Heimes7131fd92008-02-19 14:21:46 +000042# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000043
Nick Coghlanf088e5e2008-12-14 11:50:48 +000044# NOTE: There are some additional tests relating to interaction with
45# zipimport in the test_zipimport_support test module.
46
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000047modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000048if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000049 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000050
Christian Heimesa3538eb2007-11-06 11:44:48 +000051# Normalize file names: on Windows, the case of file names of compiled
52# modules depends on the path used to start the python executable.
53modfile = normcase(modfile)
54
55def revise(filename, *args):
56 return (normcase(filename),) + args
57
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000058git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000059
larryhastingsf36ba122018-01-28 11:13:09 -080060
61def signatures_with_lexicographic_keyword_only_parameters():
62 """
63 Yields a whole bunch of functions with only keyword-only parameters,
64 where those parameters are always in lexicographically sorted order.
65 """
66 parameters = ['a', 'bar', 'c', 'delta', 'ephraim', 'magical', 'yoyo', 'z']
67 for i in range(1, 2**len(parameters)):
68 p = []
69 bit = 1
70 for j in range(len(parameters)):
71 if i & (bit << j):
72 p.append(parameters[j])
73 fn_text = "def foo(*, " + ", ".join(p) + "): pass"
74 symbols = {}
75 exec(fn_text, symbols, symbols)
76 yield symbols['foo']
77
78
79def unsorted_keyword_only_parameters_fn(*, throw, out, the, baby, with_,
80 the_, bathwater):
81 pass
82
83unsorted_keyword_only_parameters = 'throw out the baby with_ the_ bathwater'.split()
84
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000085class IsTestBase(unittest.TestCase):
86 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
87 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000088 inspect.ismodule, inspect.istraceback,
Yury Selivanov75445082015-05-11 22:57:16 -040089 inspect.isgenerator, inspect.isgeneratorfunction,
Yury Selivanoveb636452016-09-08 22:01:51 -070090 inspect.iscoroutine, inspect.iscoroutinefunction,
91 inspect.isasyncgen, inspect.isasyncgenfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000092
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000093 def istest(self, predicate, exp):
94 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000095 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000096
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000097 for other in self.predicates - set([predicate]):
Yury Selivanov75445082015-05-11 22:57:16 -040098 if (predicate == inspect.isgeneratorfunction or \
Yury Selivanoveb636452016-09-08 22:01:51 -070099 predicate == inspect.isasyncgenfunction or \
Yury Selivanov75445082015-05-11 22:57:16 -0400100 predicate == inspect.iscoroutinefunction) and \
Christian Heimes7131fd92008-02-19 14:21:46 +0000101 other == inspect.isfunction:
102 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000103 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000104
Christian Heimes7131fd92008-02-19 14:21:46 +0000105def generator_function_example(self):
106 for i in range(2):
107 yield i
108
Yury Selivanoveb636452016-09-08 22:01:51 -0700109async def async_generator_function_example(self):
110 async for i in range(2):
111 yield i
112
Yury Selivanov75445082015-05-11 22:57:16 -0400113async def coroutine_function_example(self):
114 return 'spam'
115
116@types.coroutine
117def gen_coroutine_function_example(self):
118 yield
119 return 'spam'
120
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000121class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +0000122
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000123 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200124 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000125 self.istest(inspect.isbuiltin, 'sys.exit')
126 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +0000127 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200128 try:
129 1/0
130 except:
131 tb = sys.exc_info()[2]
132 self.istest(inspect.isframe, 'tb.tb_frame')
133 self.istest(inspect.istraceback, 'tb')
134 if hasattr(types, 'GetSetDescriptorType'):
135 self.istest(inspect.isgetsetdescriptor,
136 'type(tb.tb_frame).f_locals')
137 else:
138 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
139 finally:
140 # Clear traceback and all the frames and local variables hanging to it.
141 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000142 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000143 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000144 self.istest(inspect.ismethod, 'git.argue')
Jeroen Demeyerfcef60f2019-04-02 16:03:42 +0200145 self.istest(inspect.ismethod, 'mod.custom_method')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000146 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000147 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000148 self.istest(inspect.isgenerator, '(x for x in range(2))')
149 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanoveb636452016-09-08 22:01:51 -0700150 self.istest(inspect.isasyncgen,
151 'async_generator_function_example(1)')
152 self.istest(inspect.isasyncgenfunction,
153 'async_generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400154
155 with warnings.catch_warnings():
156 warnings.simplefilter("ignore")
157 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
158 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
159
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000160 if hasattr(types, 'MemberDescriptorType'):
161 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
162 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000163 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000164
Yury Selivanov75445082015-05-11 22:57:16 -0400165 def test_iscoroutine(self):
Pablo Galindo7cd25432018-10-26 12:19:14 +0100166 async_gen_coro = async_generator_function_example(1)
Yury Selivanov75445082015-05-11 22:57:16 -0400167 gen_coro = gen_coroutine_function_example(1)
168 coro = coroutine_function_example(1)
169
Yury Selivanov5376ba92015-06-22 12:19:30 -0400170 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400171 inspect.iscoroutinefunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100172 self.assertFalse(
173 inspect.iscoroutinefunction(
174 functools.partial(functools.partial(
175 gen_coroutine_function_example))))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400176 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400177
178 self.assertTrue(
179 inspect.isgeneratorfunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100180 self.assertTrue(
181 inspect.isgeneratorfunction(
182 functools.partial(functools.partial(
183 gen_coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400184 self.assertTrue(inspect.isgenerator(gen_coro))
185
186 self.assertTrue(
187 inspect.iscoroutinefunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100188 self.assertTrue(
189 inspect.iscoroutinefunction(
190 functools.partial(functools.partial(
191 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400192 self.assertTrue(inspect.iscoroutine(coro))
193
194 self.assertFalse(
195 inspect.isgeneratorfunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100196 self.assertFalse(
197 inspect.isgeneratorfunction(
198 functools.partial(functools.partial(
199 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400200 self.assertFalse(inspect.isgenerator(coro))
201
Pablo Galindo7cd25432018-10-26 12:19:14 +0100202 self.assertTrue(
203 inspect.isasyncgenfunction(async_generator_function_example))
204 self.assertTrue(
205 inspect.isasyncgenfunction(
206 functools.partial(functools.partial(
207 async_generator_function_example))))
208 self.assertTrue(inspect.isasyncgen(async_gen_coro))
209
210 coro.close(); gen_coro.close(); # silence warnings
Yury Selivanov75445082015-05-11 22:57:16 -0400211
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400212 def test_isawaitable(self):
213 def gen(): yield
214 self.assertFalse(inspect.isawaitable(gen()))
215
216 coro = coroutine_function_example(1)
217 gen_coro = gen_coroutine_function_example(1)
218
219 self.assertTrue(inspect.isawaitable(coro))
220 self.assertTrue(inspect.isawaitable(gen_coro))
221
222 class Future:
223 def __await__():
224 pass
225 self.assertTrue(inspect.isawaitable(Future()))
226 self.assertFalse(inspect.isawaitable(Future))
227
228 class NotFuture: pass
229 not_fut = NotFuture()
230 not_fut.__await__ = lambda: None
231 self.assertFalse(inspect.isawaitable(not_fut))
232
233 coro.close(); gen_coro.close() # silence warnings
234
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000235 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000236 self.assertTrue(inspect.isroutine(mod.spam))
237 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000238
Benjamin Petersonc4656002009-01-17 22:41:18 +0000239 def test_isclass(self):
240 self.istest(inspect.isclass, 'mod.StupidGit')
241 self.assertTrue(inspect.isclass(list))
242
243 class CustomGetattr(object):
244 def __getattr__(self, attr):
245 return None
246 self.assertFalse(inspect.isclass(CustomGetattr()))
247
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000248 def test_get_slot_members(self):
249 class C(object):
250 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000251 x = C()
252 x.a = 42
253 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000254 self.assertIn('a', members)
255 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000256
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000257 def test_isabstract(self):
258 from abc import ABCMeta, abstractmethod
259
260 class AbstractClassExample(metaclass=ABCMeta):
261
262 @abstractmethod
263 def foo(self):
264 pass
265
266 class ClassExample(AbstractClassExample):
267 def foo(self):
268 pass
269
270 a = ClassExample()
271
272 # Test general behaviour.
273 self.assertTrue(inspect.isabstract(AbstractClassExample))
274 self.assertFalse(inspect.isabstract(ClassExample))
275 self.assertFalse(inspect.isabstract(a))
276 self.assertFalse(inspect.isabstract(int))
277 self.assertFalse(inspect.isabstract(5))
278
Natefcfe80e2017-04-24 10:06:15 -0700279 def test_isabstract_during_init_subclass(self):
280 from abc import ABCMeta, abstractmethod
281 isabstract_checks = []
282 class AbstractChecker(metaclass=ABCMeta):
283 def __init_subclass__(cls):
284 isabstract_checks.append(inspect.isabstract(cls))
285 class AbstractClassExample(AbstractChecker):
286 @abstractmethod
287 def foo(self):
288 pass
289 class ClassExample(AbstractClassExample):
290 def foo(self):
291 pass
292 self.assertEqual(isabstract_checks, [True, False])
293
294 isabstract_checks.clear()
295 class AbstractChild(AbstractClassExample):
296 pass
297 class AbstractGrandchild(AbstractChild):
298 pass
299 class ConcreteGrandchild(ClassExample):
300 pass
301 self.assertEqual(isabstract_checks, [True, True, False])
302
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000303
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000304class TestInterpreterStack(IsTestBase):
305 def __init__(self, *args, **kwargs):
306 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000307
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000308 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000309
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000310 def test_abuse_done(self):
311 self.istest(inspect.istraceback, 'git.ex[2]')
312 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000313
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000314 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000315 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000316 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000317 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000318 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000319 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000320 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000321 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000322 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000323 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400324 # Test named tuple fields
325 record = mod.st[0]
326 self.assertIs(record.frame, mod.fr)
327 self.assertEqual(record.lineno, 16)
328 self.assertEqual(record.filename, mod.__file__)
329 self.assertEqual(record.function, 'eggs')
330 self.assertIn('inspect.stack()', record.code_context[0])
331 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000332
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000333 def test_trace(self):
334 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000335 self.assertEqual(revise(*git.tr[0][1:]),
336 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
337 self.assertEqual(revise(*git.tr[1][1:]),
338 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
339 self.assertEqual(revise(*git.tr[2][1:]),
340 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000341
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000342 def test_frame(self):
343 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
344 self.assertEqual(args, ['x', 'y'])
345 self.assertEqual(varargs, None)
346 self.assertEqual(varkw, None)
347 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
348 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
349 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000350
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000351 def test_previous_frame(self):
352 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000353 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000354 self.assertEqual(varargs, 'g')
355 self.assertEqual(varkw, 'h')
356 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000357 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000358
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000359class GetSourceBase(unittest.TestCase):
360 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000361 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000362
Yury Selivanov6738b112015-05-16 10:10:21 -0400363 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000364 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000365 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000366
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000367 def sourcerange(self, top, bottom):
368 lines = self.source.split("\n")
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700369 return "\n".join(lines[top-1:bottom]) + ("\n" if bottom else "")
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000370
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000371 def assertSourceEqual(self, obj, top, bottom):
372 self.assertEqual(inspect.getsource(obj),
373 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000374
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700375class SlotUser:
376 'Docstrings for __slots__'
377 __slots__ = {'power': 'measured in kilowatts',
378 'distance': 'measured in kilometers'}
379
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000380class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000381 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000382
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000383 def test_getclasses(self):
384 classes = inspect.getmembers(mod, inspect.isclass)
385 self.assertEqual(classes,
386 [('FesteringGob', mod.FesteringGob),
387 ('MalodorousPervert', mod.MalodorousPervert),
388 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300389 ('StupidGit', mod.StupidGit),
390 ('Tit', mod.MalodorousPervert),
391 ])
392 tree = inspect.getclasstree([cls[1] for cls in classes])
393 self.assertEqual(tree,
394 [(object, ()),
395 [(mod.ParrotDroppings, (object,)),
396 [(mod.FesteringGob, (mod.MalodorousPervert,
397 mod.ParrotDroppings))
398 ],
399 (mod.StupidGit, (object,)),
400 [(mod.MalodorousPervert, (mod.StupidGit,)),
401 [(mod.FesteringGob, (mod.MalodorousPervert,
402 mod.ParrotDroppings))
403 ]
404 ]
405 ]
406 ])
407 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000408 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000409 [(object, ()),
410 [(mod.ParrotDroppings, (object,)),
411 (mod.StupidGit, (object,)),
412 [(mod.MalodorousPervert, (mod.StupidGit,)),
413 [(mod.FesteringGob, (mod.MalodorousPervert,
414 mod.ParrotDroppings))
415 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000416 ]
417 ]
418 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000419
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000420 def test_getfunctions(self):
421 functions = inspect.getmembers(mod, inspect.isfunction)
422 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300423 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000424 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000425
R. David Murray378c0cf2010-02-24 01:46:21 +0000426 @unittest.skipIf(sys.flags.optimize >= 2,
427 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000428 def test_getdoc(self):
429 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
430 self.assertEqual(inspect.getdoc(mod.StupidGit),
431 'A longer,\n\nindented\n\ndocstring.')
432 self.assertEqual(inspect.getdoc(git.abuse),
433 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700434 self.assertEqual(inspect.getdoc(SlotUser.power),
435 'measured in kilowatts')
436 self.assertEqual(inspect.getdoc(SlotUser.distance),
437 'measured in kilometers')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000438
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300439 @unittest.skipIf(sys.flags.optimize >= 2,
440 "Docstrings are omitted with -O2 and above")
441 def test_getdoc_inherited(self):
Serhiy Storchakafbf27862020-04-15 23:00:20 +0300442 self.assertIsNone(inspect.getdoc(mod.FesteringGob))
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300443 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
444 'Another\n\ndocstring\n\ncontaining\n\ntabs')
445 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
446 'Another\n\ndocstring\n\ncontaining\n\ntabs')
447 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
448 'The automatic gainsaying.')
449
450 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
Serhiy Storchakafbf27862020-04-15 23:00:20 +0300451 def test_getowndoc(self):
452 getowndoc = inspect._getowndoc
453 self.assertEqual(getowndoc(type), type.__doc__)
454 self.assertEqual(getowndoc(int), int.__doc__)
455 self.assertEqual(getowndoc(int.to_bytes), int.to_bytes.__doc__)
456 self.assertEqual(getowndoc(int().to_bytes), int.to_bytes.__doc__)
457 self.assertEqual(getowndoc(int.from_bytes), int.from_bytes.__doc__)
458 self.assertEqual(getowndoc(int.real), int.real.__doc__)
459
460 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300461 def test_finddoc(self):
462 finddoc = inspect._finddoc
Serhiy Storchakafbf27862020-04-15 23:00:20 +0300463 self.assertIsNone(finddoc(int))
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300464 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
465 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
466 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
467 self.assertEqual(finddoc(int.real), int.real.__doc__)
468
Georg Brandl0c77a822008-06-10 16:37:50 +0000469 def test_cleandoc(self):
470 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
471 'An\nindented\ndocstring.')
472
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000473 def test_getcomments(self):
474 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
475 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530476 self.assertEqual(inspect.getcomments(mod2.cls160), '# line 159\n')
Marco Buttu3f2155f2017-03-17 09:50:23 +0100477 # If the object source file is not available, return None.
478 co = compile('x=1', '_non_existing_filename.py', 'exec')
479 self.assertIsNone(inspect.getcomments(co))
480 # If the object has been defined in C, return None.
481 self.assertIsNone(inspect.getcomments(list))
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000482
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000483 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000484 # Check actual module
485 self.assertEqual(inspect.getmodule(mod), mod)
486 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000487 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000488 # Check a method (no __module__ attribute, falls back to filename)
489 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
490 # Do it again (check the caching isn't broken)
491 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
492 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000493 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000494 # Check filename override
495 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000496
Berker Peksagff0e3b72017-01-02 06:57:43 +0300497 def test_getframeinfo_get_first_line(self):
498 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
499 self.assertEqual(frame_info.code_context[0], "# line 1\n")
500 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
501
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000502 def test_getsource(self):
503 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200504 self.assertSourceEqual(mod.StupidGit, 21, 51)
505 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000506
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000507 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000508 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
509 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000510 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100511 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000512 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000513 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200514 try:
515 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
516 finally:
517 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000518
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000519 def test_getfile(self):
520 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000521
Philipp Ad407d2a2019-06-08 14:05:46 +0200522 def test_getfile_builtin_module(self):
523 with self.assertRaises(TypeError) as e:
524 inspect.getfile(sys)
525 self.assertTrue(str(e.exception).startswith('<module'))
526
527 def test_getfile_builtin_class(self):
528 with self.assertRaises(TypeError) as e:
529 inspect.getfile(int)
530 self.assertTrue(str(e.exception).startswith('<class'))
531
532 def test_getfile_builtin_function_or_method(self):
533 with self.assertRaises(TypeError) as e_abs:
534 inspect.getfile(abs)
535 self.assertIn('expected, got', str(e_abs.exception))
536 with self.assertRaises(TypeError) as e_append:
537 inspect.getfile(list.append)
538 self.assertIn('expected, got', str(e_append.exception))
539
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500540 def test_getfile_class_without_module(self):
541 class CM(type):
542 @property
543 def __module__(cls):
544 raise AttributeError
545 class C(metaclass=CM):
546 pass
547 with self.assertRaises(TypeError):
548 inspect.getfile(C)
549
Thomas Kluyvere968bc732017-10-24 13:42:36 +0100550 def test_getfile_broken_repr(self):
551 class ErrorRepr:
552 def __repr__(self):
553 raise Exception('xyz')
554 er = ErrorRepr()
555 with self.assertRaises(TypeError):
556 inspect.getfile(er)
557
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000558 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000559 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000560 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000561 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000562 m.__file__ = "<string>" # hopefully not a real filename...
563 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000564 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000565 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000566 del sys.modules[name]
567 inspect.getmodule(compile('a=10','','single'))
568
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500569 def test_proceed_with_fake_filename(self):
570 '''doctest monkeypatches linecache to enable inspection'''
571 fn, source = '<test>', 'def x(): pass\n'
572 getlines = linecache.getlines
573 def monkey(filename, module_globals=None):
574 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300575 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500576 else:
577 return getlines(filename, module_globals)
578 linecache.getlines = monkey
579 try:
580 ns = {}
581 exec(compile(source, fn, 'single'), ns)
582 inspect.getsource(ns["x"])
583 finally:
584 linecache.getlines = getlines
585
Antoine Pitroua8723a02015-04-15 00:41:29 +0200586 def test_getsource_on_code_object(self):
587 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
588
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700589class TestGettingSourceOfToplevelFrames(GetSourceBase):
590 fodderModule = mod
591
592 def test_range_toplevel_frame(self):
593 self.maxDiff = None
594 self.assertSourceEqual(mod.currentframe, 1, None)
595
596 def test_range_traceback_toplevel_frame(self):
597 self.assertSourceEqual(mod.tb, 1, None)
598
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000599class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000600 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000601
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000602 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000603 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000604
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000605 def test_replacing_decorator(self):
606 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000607
Yury Selivanov081bbf62014-09-26 17:34:54 -0400608 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200609 self.assertSourceEqual(mod2.real, 130, 132)
610
611 def test_decorator_with_lambda(self):
612 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400613
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000614class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000615 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000616 def test_oneline_lambda(self):
617 # Test inspect.getsource with a one-line lambda function.
618 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000619
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000620 def test_threeline_lambda(self):
621 # Test inspect.getsource with a three-line lambda function,
622 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000623 self.assertSourceEqual(mod2.tll, 28, 30)
624
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000625 def test_twoline_indented_lambda(self):
626 # Test inspect.getsource with a two-line lambda function,
627 # where the second line _is_ indented.
628 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000629
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000630 def test_onelinefunc(self):
631 # Test inspect.getsource with a regular one-line function.
632 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000633
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000634 def test_manyargs(self):
635 # Test inspect.getsource with a regular function where
636 # the arguments are on two lines and _not_ indented and
637 # the body on the second line with the last arguments.
638 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000639
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000640 def test_twolinefunc(self):
641 # Test inspect.getsource with a regular function where
642 # the body is on two lines, following the argument list and
643 # continued on the next line by a \\.
644 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000645
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000646 def test_lambda_in_list(self):
647 # Test inspect.getsource with a one-line lambda function
648 # defined in a list, indented.
649 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000650
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000651 def test_anonymous(self):
652 # Test inspect.getsource with a lambda function defined
653 # as argument to another function.
654 self.assertSourceEqual(mod2.anonymous, 55, 55)
655
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000656class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000657 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000658
659 def test_with_comment(self):
660 self.assertSourceEqual(mod2.with_comment, 58, 59)
661
662 def test_multiline_sig(self):
663 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
664
Armin Rigodd5c0232005-09-25 11:45:45 +0000665 def test_nested_class(self):
666 self.assertSourceEqual(mod2.func69().func71, 71, 72)
667
668 def test_one_liner_followed_by_non_name(self):
669 self.assertSourceEqual(mod2.func77, 77, 77)
670
671 def test_one_liner_dedent_non_name(self):
672 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
673
674 def test_with_comment_instead_of_docstring(self):
675 self.assertSourceEqual(mod2.func88, 88, 90)
676
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000677 def test_method_in_dynamic_class(self):
678 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
679
R David Murray32562d72014-10-03 11:15:38 -0400680 # This should not skip for CPython, but might on a repackaged python where
681 # unicodedata is not an external module, or on pypy.
682 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
683 unicodedata.__file__.endswith('.py'),
684 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000685 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200686 self.assertRaises(OSError, inspect.getsource, unicodedata)
687 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000688
R. David Murraya1b37402010-06-17 02:04:29 +0000689 def test_findsource_code_in_linecache(self):
690 lines = ["x=1"]
691 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200692 self.assertRaises(OSError, inspect.findsource, co)
693 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000694 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200695 try:
696 self.assertEqual(inspect.findsource(co), (lines,0))
697 self.assertEqual(inspect.getsource(co), lines[0])
698 finally:
699 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000700
Ezio Melotti1b145922013-03-30 05:17:24 +0200701 def test_findsource_without_filename(self):
702 for fname in ['', '<string>']:
703 co = compile('x=1', fname, "exec")
704 self.assertRaises(IOError, inspect.findsource, co)
705 self.assertRaises(IOError, inspect.getsource, co)
706
Antoine Pitroua8723a02015-04-15 00:41:29 +0200707 def test_getsource_on_method(self):
708 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
709
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300710 def test_nested_func(self):
711 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
712
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530713 def test_class_definition_in_multiline_string_definition(self):
714 self.assertSourceEqual(mod2.cls149, 149, 152)
715
716 def test_class_definition_in_multiline_comment(self):
717 self.assertSourceEqual(mod2.cls160, 160, 163)
718
719 def test_nested_class_definition_indented_string(self):
720 self.assertSourceEqual(mod2.cls173.cls175, 175, 176)
721
722 def test_nested_class_definition(self):
723 self.assertSourceEqual(mod2.cls183, 183, 188)
724 self.assertSourceEqual(mod2.cls183.cls185, 185, 188)
725
726 def test_class_decorator(self):
727 self.assertSourceEqual(mod2.cls196, 194, 201)
728 self.assertSourceEqual(mod2.cls196.cls200, 198, 201)
729
730 def test_class_inside_conditional(self):
731 self.assertSourceEqual(mod2.cls238, 238, 240)
732 self.assertSourceEqual(mod2.cls238.cls239, 239, 240)
733
734 def test_multiple_children_classes(self):
735 self.assertSourceEqual(mod2.cls203, 203, 209)
736 self.assertSourceEqual(mod2.cls203.cls204, 204, 206)
737 self.assertSourceEqual(mod2.cls203.cls204.cls205, 205, 206)
738 self.assertSourceEqual(mod2.cls203.cls207, 207, 209)
739 self.assertSourceEqual(mod2.cls203.cls207.cls205, 208, 209)
740
741 def test_nested_class_definition_inside_function(self):
742 self.assertSourceEqual(mod2.func212(), 213, 214)
743 self.assertSourceEqual(mod2.cls213, 218, 222)
744 self.assertSourceEqual(mod2.cls213().func219(), 220, 221)
745
746 def test_nested_class_definition_inside_async_function(self):
747 import asyncio
748 self.addCleanup(asyncio.set_event_loop_policy, None)
749 self.assertSourceEqual(asyncio.run(mod2.func225()), 226, 227)
750 self.assertSourceEqual(mod2.cls226, 231, 235)
751 self.assertSourceEqual(asyncio.run(mod2.cls226().func232()), 233, 234)
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300752
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000753class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400754 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000755 self.tempdir = TESTFN + '_dir'
756 os.mkdir(self.tempdir)
757 with open(os.path.join(self.tempdir,
758 'inspect_fodder3%spy' % os.extsep), 'w') as f:
759 f.write("class X:\n pass # No EOL")
760 with DirsOnSysPath(self.tempdir):
761 import inspect_fodder3 as mod3
762 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400763 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000764
765 def tearDown(self):
766 shutil.rmtree(self.tempdir)
767
768 def test_class(self):
769 self.assertSourceEqual(self.fodderModule.X, 1, 2)
770
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100771
772class _BrokenDataDescriptor(object):
773 """
774 A broken data descriptor. See bug #1785.
775 """
776 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700777 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100778
779 def __set__(*args):
780 raise RuntimeError
781
782 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700783 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100784
785
786class _BrokenMethodDescriptor(object):
787 """
788 A broken method descriptor. See bug #1785.
789 """
790 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700791 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100792
793 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700794 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100795
796
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000797# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000798def attrs_wo_objs(cls):
799 return [t[:3] for t in inspect.classify_class_attrs(cls)]
800
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100801
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000802class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000803 def test_newstyle_mro(self):
804 # The same w/ new-class MRO.
805 class A(object): pass
806 class B(A): pass
807 class C(A): pass
808 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000809
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000810 expected = (D, B, C, A, object)
811 got = inspect.getmro(D)
812 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000813
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500814 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
815 varkw_e=None, defaults_e=None, formatted=None):
Xtreak6d0b7472019-05-30 17:31:39 +0530816 with self.assertWarns(DeprecationWarning):
817 args, varargs, varkw, defaults = inspect.getargspec(routine)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500818 self.assertEqual(args, args_e)
819 self.assertEqual(varargs, varargs_e)
820 self.assertEqual(varkw, varkw_e)
821 self.assertEqual(defaults, defaults_e)
822 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530823 with self.assertWarns(DeprecationWarning):
824 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
825 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500826
Christian Heimes3795b532007-11-08 13:48:53 +0000827 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
828 varkw_e=None, defaults_e=None,
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100829 posonlyargs_e=[], kwonlyargs_e=[],
830 kwonlydefaults_e=None,
Christian Heimes3795b532007-11-08 13:48:53 +0000831 ann_e={}, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100832 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
833 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000834 self.assertEqual(args, args_e)
835 self.assertEqual(varargs, varargs_e)
836 self.assertEqual(varkw, varkw_e)
837 self.assertEqual(defaults, defaults_e)
838 self.assertEqual(kwonlyargs, kwonlyargs_e)
839 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
840 self.assertEqual(ann, ann_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 kwonlyargs, kwonlydefaults, ann),
845 formatted)
Christian Heimes3795b532007-11-08 13:48:53 +0000846
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500847 def test_getargspec(self):
848 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
849
Pablo Galindod5d2b452019-04-30 02:01:14 +0100850 self.assertArgSpecEquals(mod.spam,
851 ['a', 'b', 'c', 'd', 'e', 'f'],
852 'g', 'h', (3, 4, 5),
853 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500854
855 self.assertRaises(ValueError, self.assertArgSpecEquals,
856 mod2.keyworded, [])
857
858 self.assertRaises(ValueError, self.assertArgSpecEquals,
859 mod2.annotated, [])
860 self.assertRaises(ValueError, self.assertArgSpecEquals,
861 mod2.keyword_only_arg, [])
862
863
Christian Heimes3795b532007-11-08 13:48:53 +0000864 def test_getfullargspec(self):
865 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
866 kwonlyargs_e=['arg2'],
867 kwonlydefaults_e={'arg2':1},
868 formatted='(*arg1, arg2=1)')
869
870 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000871 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000872 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000873 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
874 kwonlyargs_e=['arg'],
875 formatted='(*, arg)')
876
Pablo Galindod5d2b452019-04-30 02:01:14 +0100877 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100878 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100879 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100880
881 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100882 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100883 varargs_e='args',
884 varkw_e='kwargs',
885 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100886 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100887
Pablo Galindod5d2b452019-04-30 02:01:14 +0100888 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100889 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100890 kwonlyargs_e=['e', 'f'],
891 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100892 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100893
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500894 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500895 # Issue 20684: low level introspection API must ignore __wrapped__
896 @functools.wraps(mod.spam)
897 def ham(x, y):
898 pass
899 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500900 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500901 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
902 self.assertFullArgSpecEquals(functools.partial(ham),
903 ['x', 'y'], formatted='(x, y)')
904 # Other variants
905 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500906 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
907 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500908 class C:
909 @functools.wraps(mod.spam)
910 def ham(self, x, y):
911 pass
912 pham = functools.partialmethod(ham)
913 @functools.wraps(mod.spam)
914 def __call__(self, x, y):
915 pass
916 check_method(C())
917 check_method(C.ham)
918 check_method(C().ham)
919 check_method(C.pham)
920 check_method(C().pham)
921
922 class C_new:
923 @functools.wraps(mod.spam)
924 def __new__(self, x, y):
925 pass
926 check_method(C_new)
927
928 class C_init:
929 @functools.wraps(mod.spam)
930 def __init__(self, x, y):
931 pass
932 check_method(C_init)
933
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500934 def test_getfullargspec_signature_attr(self):
935 def test():
936 pass
937 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
938 test.__signature__ = inspect.Signature(parameters=(spam_param,))
939
Pablo Galindod5d2b452019-04-30 02:01:14 +0100940 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500941
Yury Selivanov4cb93912014-01-29 11:54:12 -0500942 def test_getfullargspec_signature_annos(self):
943 def test(a:'spam') -> 'ham': pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100944 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500945 self.assertEqual(test.__annotations__, spec.annotations)
946
947 def test(): pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100948 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500949 self.assertEqual(test.__annotations__, spec.annotations)
950
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500951 @unittest.skipIf(MISSING_C_DOCSTRINGS,
952 "Signature information for builtins requires docstrings")
953 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100954 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
955 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500956
Pablo Galindod5d2b452019-04-30 02:01:14 +0100957 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
958 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500959
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500960 self.assertFullArgSpecEquals(
961 os.stat,
962 args_e=['path'],
963 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
964 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
965 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
966
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200967 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500968 @unittest.skipIf(MISSING_C_DOCSTRINGS,
969 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800970 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200971 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500972 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindoaee19f52019-05-16 21:08:15 +0100973 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500974 self.assertEqual(spec.defaults[0], 'avocado')
975
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200976 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500977 @unittest.skipIf(MISSING_C_DOCSTRINGS,
978 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800979 def test_getfullargspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200980 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500981 builtin = _testcapi.docstring_no_signature
Pablo Galindoaee19f52019-05-16 21:08:15 +0100982 with self.assertRaises(TypeError):
983 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000984
larryhastingsf36ba122018-01-28 11:13:09 -0800985 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
986 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindoaee19f52019-05-16 21:08:15 +0100987 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800988 l = list(signature.kwonlyargs)
989 sorted_l = sorted(l)
990 self.assertTrue(l)
991 self.assertEqual(l, sorted_l)
Pablo Galindoaee19f52019-05-16 21:08:15 +0100992 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800993 l = list(signature.kwonlyargs)
994 self.assertEqual(l, unsorted_keyword_only_parameters)
995
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500996 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000997 class A(object):
998 def m(self):
999 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -05001000 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +00001001
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001002 def test_classify_newstyle(self):
1003 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +00001004
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001005 def s(): pass
1006 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +00001007
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001008 def c(cls): pass
1009 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +00001010
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001011 def getp(self): pass
1012 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +00001013
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001014 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001015
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001016 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001017
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001018 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +00001019
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001020 dd = _BrokenDataDescriptor()
1021 md = _BrokenMethodDescriptor()
1022
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001023 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001024
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001025 self.assertIn(('__new__', 'static method', object), attrs,
1026 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001027 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
1028
Benjamin Peterson577473f2010-01-19 00:09:57 +00001029 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1030 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1031 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001032 self.assertIn(('m', 'method', A), attrs,
1033 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001034 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1035 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001036 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1037 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001038
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001039 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001040
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001041 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001042
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001043 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001044 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1045 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1046 self.assertIn(('p', 'property', A), attrs, 'missing property')
1047 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1048 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1049 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001050 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1051 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001052
1053
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001054 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001055
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001056 def m(self): pass
1057 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001058
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001059 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001060 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1061 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1062 self.assertIn(('p', 'property', A), attrs, 'missing property')
1063 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
1064 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1065 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001066 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1067 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001068
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001069 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001070
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001071 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001072
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001073 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001074 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1075 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1076 self.assertIn(('p', 'property', A), attrs, 'missing property')
1077 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1078 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1079 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001080 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1081 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1082
1083 def test_classify_builtin_types(self):
1084 # Simple sanity check that all built-in types can have their
1085 # attributes classified.
1086 for name in dir(__builtins__):
1087 builtin = getattr(__builtins__, name)
1088 if isinstance(builtin, type):
1089 inspect.classify_class_attrs(builtin)
1090
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001091 attrs = attrs_wo_objs(bool)
1092 self.assertIn(('__new__', 'static method', bool), attrs,
1093 'missing __new__')
1094 self.assertIn(('from_bytes', 'class method', int), attrs,
1095 'missing class method')
1096 self.assertIn(('to_bytes', 'method', int), attrs,
1097 'missing plain method')
1098 self.assertIn(('__add__', 'method', int), attrs,
1099 'missing plain method')
1100 self.assertIn(('__and__', 'method', bool), attrs,
1101 'missing plain method')
1102
Ethan Furman63c141c2013-10-18 00:27:39 -07001103 def test_classify_DynamicClassAttribute(self):
1104 class Meta(type):
1105 def __getattr__(self, name):
1106 if name == 'ham':
1107 return 'spam'
1108 return super().__getattr__(name)
1109 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001110 @types.DynamicClassAttribute
1111 def ham(self):
1112 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001113 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1114 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001115 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001116 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1117
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001118 def test_classify_overrides_bool(self):
1119 class NoBool(object):
1120 def __eq__(self, other):
1121 return NoBool()
1122
1123 def __bool__(self):
1124 raise NotImplementedError(
1125 "This object does not specify a boolean value")
1126
1127 class HasNB(object):
1128 dd = NoBool()
1129
1130 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1131 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1132
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001133 def test_classify_metaclass_class_attribute(self):
1134 class Meta(type):
1135 fish = 'slap'
1136 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001137 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001138 class Class(metaclass=Meta):
1139 pass
1140 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1141 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1142
Ethan Furman63c141c2013-10-18 00:27:39 -07001143 def test_classify_VirtualAttribute(self):
1144 class Meta(type):
1145 def __dir__(cls):
1146 return ['__class__', '__module__', '__name__', 'BOOM']
1147 def __getattr__(self, name):
1148 if name =='BOOM':
1149 return 42
1150 return super().__getattr(name)
1151 class Class(metaclass=Meta):
1152 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001153 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001154 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1155
1156 def test_classify_VirtualAttribute_multi_classes(self):
1157 class Meta1(type):
1158 def __dir__(cls):
1159 return ['__class__', '__module__', '__name__', 'one']
1160 def __getattr__(self, name):
1161 if name =='one':
1162 return 1
1163 return super().__getattr__(name)
1164 class Meta2(type):
1165 def __dir__(cls):
1166 return ['__class__', '__module__', '__name__', 'two']
1167 def __getattr__(self, name):
1168 if name =='two':
1169 return 2
1170 return super().__getattr__(name)
1171 class Meta3(Meta1, Meta2):
1172 def __dir__(cls):
1173 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1174 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1175 def __getattr__(self, name):
1176 if name =='three':
1177 return 3
1178 return super().__getattr__(name)
1179 class Class1(metaclass=Meta1):
1180 pass
1181 class Class2(Class1, metaclass=Meta3):
1182 pass
1183
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001184 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1185 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1186 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001187 cca = inspect.classify_class_attrs(Class2)
1188 for sf in (should_find1, should_find2, should_find3):
1189 self.assertIn(sf, cca)
1190
1191 def test_classify_class_attrs_with_buggy_dir(self):
1192 class M(type):
1193 def __dir__(cls):
1194 return ['__class__', '__name__', 'missing']
1195 class C(metaclass=M):
1196 pass
1197 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1198 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001199
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001200 def test_getmembers_descriptors(self):
1201 class A(object):
1202 dd = _BrokenDataDescriptor()
1203 md = _BrokenMethodDescriptor()
1204
1205 def pred_wrapper(pred):
1206 # A quick'n'dirty way to discard standard attributes of new-style
1207 # classes.
1208 class Empty(object):
1209 pass
1210 def wrapped(x):
1211 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1212 return False
1213 return pred(x)
1214 return wrapped
1215
1216 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1217 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1218
1219 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1220 [('md', A.__dict__['md'])])
1221 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1222 [('dd', A.__dict__['dd'])])
1223
1224 class B(A):
1225 pass
1226
1227 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1228 [('md', A.__dict__['md'])])
1229 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1230 [('dd', A.__dict__['dd'])])
1231
Antoine Pitrou0c603812012-01-18 17:40:18 +01001232 def test_getmembers_method(self):
1233 class B:
1234 def f(self):
1235 pass
1236
1237 self.assertIn(('f', B.f), inspect.getmembers(B))
1238 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1239 b = B()
1240 self.assertIn(('f', b.f), inspect.getmembers(b))
1241 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1242
Ethan Furmane03ea372013-09-25 07:14:41 -07001243 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001244 class M(type):
1245 def __getattr__(cls, name):
1246 if name == 'eggs':
1247 return 'scrambled'
1248 return super().__getattr__(name)
1249 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001250 @types.DynamicClassAttribute
1251 def eggs(self):
1252 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001253 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1254 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1255
1256 def test_getmembers_with_buggy_dir(self):
1257 class M(type):
1258 def __dir__(cls):
1259 return ['__class__', '__name__', 'missing']
1260 class C(metaclass=M):
1261 pass
1262 attrs = [a[0] for a in inspect.getmembers(C)]
1263 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001264
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001265class TestIsDataDescriptor(unittest.TestCase):
1266
1267 def test_custom_descriptors(self):
1268 class NonDataDescriptor:
1269 def __get__(self, value, type=None): pass
1270 class DataDescriptor0:
1271 def __set__(self, name, value): pass
1272 class DataDescriptor1:
1273 def __delete__(self, name): pass
1274 class DataDescriptor2:
1275 __set__ = None
1276 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1277 'class with only __get__ not a data descriptor')
1278 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1279 'class with __set__ is a data descriptor')
1280 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1281 'class with __delete__ is a data descriptor')
1282 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1283 'class with __set__ = None is a data descriptor')
1284
1285 def test_slot(self):
1286 class Slotted:
1287 __slots__ = 'foo',
1288 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1289 'a slot is a data descriptor')
1290
1291 def test_property(self):
1292 class Propertied:
1293 @property
1294 def a_property(self):
1295 pass
1296 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1297 'a property is a data descriptor')
1298
1299 def test_functions(self):
1300 class Test(object):
1301 def instance_method(self): pass
1302 @classmethod
1303 def class_method(cls): pass
1304 @staticmethod
1305 def static_method(): pass
1306 def function():
1307 pass
1308 a_lambda = lambda: None
1309 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1310 'a instance method is not a data descriptor')
1311 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1312 'a class method is not a data descriptor')
1313 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1314 'a static method is not a data descriptor')
1315 self.assertFalse(inspect.isdatadescriptor(function),
1316 'a function is not a data descriptor')
1317 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1318 'a lambda is not a data descriptor')
1319
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001320
Nick Coghlan2f92e542012-06-23 19:39:55 +10001321_global_ref = object()
1322class TestGetClosureVars(unittest.TestCase):
1323
1324 def test_name_resolution(self):
1325 # Basic test of the 4 different resolution mechanisms
1326 def f(nonlocal_ref):
1327 def g(local_ref):
1328 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1329 return g
1330 _arg = object()
1331 nonlocal_vars = {"nonlocal_ref": _arg}
1332 global_vars = {"_global_ref": _global_ref}
1333 builtin_vars = {"print": print}
1334 unbound_names = {"unbound_ref"}
1335 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1336 builtin_vars, unbound_names)
1337 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1338
1339 def test_generator_closure(self):
1340 def f(nonlocal_ref):
1341 def g(local_ref):
1342 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1343 yield
1344 return g
1345 _arg = object()
1346 nonlocal_vars = {"nonlocal_ref": _arg}
1347 global_vars = {"_global_ref": _global_ref}
1348 builtin_vars = {"print": print}
1349 unbound_names = {"unbound_ref"}
1350 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1351 builtin_vars, unbound_names)
1352 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1353
1354 def test_method_closure(self):
1355 class C:
1356 def f(self, nonlocal_ref):
1357 def g(local_ref):
1358 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1359 return g
1360 _arg = object()
1361 nonlocal_vars = {"nonlocal_ref": _arg}
1362 global_vars = {"_global_ref": _global_ref}
1363 builtin_vars = {"print": print}
1364 unbound_names = {"unbound_ref"}
1365 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1366 builtin_vars, unbound_names)
1367 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1368
1369 def test_nonlocal_vars(self):
1370 # More complex tests of nonlocal resolution
1371 def _nonlocal_vars(f):
1372 return inspect.getclosurevars(f).nonlocals
1373
1374 def make_adder(x):
1375 def add(y):
1376 return x + y
1377 return add
1378
1379 def curry(func, arg1):
1380 return lambda arg2: func(arg1, arg2)
1381
1382 def less_than(a, b):
1383 return a < b
1384
1385 # The infamous Y combinator.
1386 def Y(le):
1387 def g(f):
1388 return le(lambda x: f(f)(x))
1389 Y.g_ref = g
1390 return g(g)
1391
1392 def check_y_combinator(func):
1393 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1394
1395 inc = make_adder(1)
1396 add_two = make_adder(2)
1397 greater_than_five = curry(less_than, 5)
1398
1399 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1400 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1401 self.assertEqual(_nonlocal_vars(greater_than_five),
1402 {'arg1': 5, 'func': less_than})
1403 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1404 {'x': 3})
1405 Y(check_y_combinator)
1406
1407 def test_getclosurevars_empty(self):
1408 def foo(): pass
1409 _empty = inspect.ClosureVars({}, {}, {}, set())
1410 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1411 self.assertEqual(inspect.getclosurevars(foo), _empty)
1412
1413 def test_getclosurevars_error(self):
1414 class T: pass
1415 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1416 self.assertRaises(TypeError, inspect.getclosurevars, list)
1417 self.assertRaises(TypeError, inspect.getclosurevars, {})
1418
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001419 def _private_globals(self):
1420 code = """def f(): print(path)"""
1421 ns = {}
1422 exec(code, ns)
1423 return ns["f"], ns
1424
1425 def test_builtins_fallback(self):
1426 f, ns = self._private_globals()
1427 ns.pop("__builtins__", None)
1428 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1429 self.assertEqual(inspect.getclosurevars(f), expected)
1430
1431 def test_builtins_as_dict(self):
1432 f, ns = self._private_globals()
1433 ns["__builtins__"] = {"path":1}
1434 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1435 self.assertEqual(inspect.getclosurevars(f), expected)
1436
1437 def test_builtins_as_module(self):
1438 f, ns = self._private_globals()
1439 ns["__builtins__"] = os
1440 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1441 self.assertEqual(inspect.getclosurevars(f), expected)
1442
Nick Coghlan2f92e542012-06-23 19:39:55 +10001443
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001444class TestGetcallargsFunctions(unittest.TestCase):
1445
1446 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1447 locs = dict(locs or {}, func=func)
1448 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001449 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1450 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001451 self.assertEqual(r1, r2)
1452
1453 def assertEqualException(self, func, call_param_string, locs=None):
1454 locs = dict(locs or {}, func=func)
1455 try:
1456 eval('func(%s)' % call_param_string, None, locs)
1457 except Exception as e:
1458 ex1 = e
1459 else:
1460 self.fail('Exception not raised')
1461 try:
Pablo Galindoaee19f52019-05-16 21:08:15 +01001462 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1463 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001464 except Exception as e:
1465 ex2 = e
1466 else:
1467 self.fail('Exception not raised')
1468 self.assertIs(type(ex1), type(ex2))
1469 self.assertEqual(str(ex1), str(ex2))
1470 del ex1, ex2
1471
1472 def makeCallable(self, signature):
1473 """Create a function that returns its locals()"""
1474 code = "lambda %s: locals()"
1475 return eval(code % signature)
1476
1477 def test_plain(self):
1478 f = self.makeCallable('a, b=1')
1479 self.assertEqualCallArgs(f, '2')
1480 self.assertEqualCallArgs(f, '2, 3')
1481 self.assertEqualCallArgs(f, 'a=2')
1482 self.assertEqualCallArgs(f, 'b=3, a=2')
1483 self.assertEqualCallArgs(f, '2, b=3')
1484 # expand *iterable / **mapping
1485 self.assertEqualCallArgs(f, '*(2,)')
1486 self.assertEqualCallArgs(f, '*[2]')
1487 self.assertEqualCallArgs(f, '*(2, 3)')
1488 self.assertEqualCallArgs(f, '*[2, 3]')
1489 self.assertEqualCallArgs(f, '**{"a":2}')
1490 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1491 self.assertEqualCallArgs(f, '2, **{"b":3}')
1492 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1493 # expand UserList / UserDict
1494 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1495 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1496 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1497 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1498 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1499
1500 def test_varargs(self):
1501 f = self.makeCallable('a, b=1, *c')
1502 self.assertEqualCallArgs(f, '2')
1503 self.assertEqualCallArgs(f, '2, 3')
1504 self.assertEqualCallArgs(f, '2, 3, 4')
1505 self.assertEqualCallArgs(f, '*(2,3,4)')
1506 self.assertEqualCallArgs(f, '2, *[3,4]')
1507 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1508
1509 def test_varkw(self):
1510 f = self.makeCallable('a, b=1, **c')
1511 self.assertEqualCallArgs(f, 'a=2')
1512 self.assertEqualCallArgs(f, '2, b=3, c=4')
1513 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1514 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1515 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1516 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1517 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1518 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1519 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1520
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001521 def test_varkw_only(self):
1522 # issue11256:
1523 f = self.makeCallable('**c')
1524 self.assertEqualCallArgs(f, '')
1525 self.assertEqualCallArgs(f, 'a=1')
1526 self.assertEqualCallArgs(f, 'a=1, b=2')
1527 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1528 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1529 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1530
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001531 def test_keyword_only(self):
1532 f = self.makeCallable('a=3, *, c, d=2')
1533 self.assertEqualCallArgs(f, 'c=3')
1534 self.assertEqualCallArgs(f, 'c=3, a=3')
1535 self.assertEqualCallArgs(f, 'a=2, c=4')
1536 self.assertEqualCallArgs(f, '4, c=4')
1537 self.assertEqualException(f, '')
1538 self.assertEqualException(f, '3')
1539 self.assertEqualException(f, 'a=3')
1540 self.assertEqualException(f, 'd=4')
1541
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001542 f = self.makeCallable('*, c, d=2')
1543 self.assertEqualCallArgs(f, 'c=3')
1544 self.assertEqualCallArgs(f, 'c=3, d=4')
1545 self.assertEqualCallArgs(f, 'd=4, c=3')
1546
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001547 def test_multiple_features(self):
1548 f = self.makeCallable('a, b=2, *f, **g')
1549 self.assertEqualCallArgs(f, '2, 3, 7')
1550 self.assertEqualCallArgs(f, '2, 3, x=8')
1551 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1552 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1553 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1554 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1555 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1556 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1557 '(4,[5,6])]), **collections.UserDict('
1558 'y=9, z=10)')
1559
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001560 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1561 self.assertEqualCallArgs(f, '2, 3, x=8')
1562 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1563 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1564 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1565 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1566 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1567 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1568 '(4,[5,6])]), q=0, **collections.UserDict('
1569 'y=9, z=10)')
1570
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001571 def test_errors(self):
1572 f0 = self.makeCallable('')
1573 f1 = self.makeCallable('a, b')
1574 f2 = self.makeCallable('a, b=1')
1575 # f0 takes no arguments
1576 self.assertEqualException(f0, '1')
1577 self.assertEqualException(f0, 'x=1')
1578 self.assertEqualException(f0, '1,x=1')
1579 # f1 takes exactly 2 arguments
1580 self.assertEqualException(f1, '')
1581 self.assertEqualException(f1, '1')
1582 self.assertEqualException(f1, 'a=2')
1583 self.assertEqualException(f1, 'b=3')
1584 # f2 takes at least 1 argument
1585 self.assertEqualException(f2, '')
1586 self.assertEqualException(f2, 'b=3')
1587 for f in f1, f2:
1588 # f1/f2 takes exactly/at most 2 arguments
1589 self.assertEqualException(f, '2, 3, 4')
1590 self.assertEqualException(f, '1, 2, 3, a=1')
1591 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001592 # XXX: success of this one depends on dict order
1593 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001594 # f got an unexpected keyword argument
1595 self.assertEqualException(f, 'c=2')
1596 self.assertEqualException(f, '2, c=3')
1597 self.assertEqualException(f, '2, 3, c=4')
1598 self.assertEqualException(f, '2, c=4, b=3')
1599 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1600 # f got multiple values for keyword argument
1601 self.assertEqualException(f, '1, a=2')
1602 self.assertEqualException(f, '1, **{"a":2}')
1603 self.assertEqualException(f, '1, 2, b=3')
1604 # XXX: Python inconsistency
1605 # - for functions and bound methods: unexpected keyword 'c'
1606 # - for unbound methods: multiple values for keyword 'a'
1607 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001608 # issue11256:
1609 f3 = self.makeCallable('**c')
1610 self.assertEqualException(f3, '1, 2')
1611 self.assertEqualException(f3, '1, 2, a=1, b=2')
1612 f4 = self.makeCallable('*, a, b=0')
1613 self.assertEqualException(f3, '1, 2')
1614 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001615
Yury Selivanov875df202014-03-27 18:23:03 -04001616 # issue #20816: getcallargs() fails to iterate over non-existent
1617 # kwonlydefaults and raises a wrong TypeError
1618 def f5(*, a): pass
1619 with self.assertRaisesRegex(TypeError,
1620 'missing 1 required keyword-only'):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001621 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001622
1623
Yury Selivanovdccfa132014-03-27 18:42:52 -04001624 # issue20817:
1625 def f6(a, b, c):
1626 pass
1627 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001628 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001629
Dong-hee Naa9cab432018-05-30 00:04:08 +09001630 # bpo-33197
1631 with self.assertRaisesRegex(ValueError,
1632 'variadic keyword parameters cannot'
1633 ' have default values'):
1634 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1635 default=42)
1636 with self.assertRaisesRegex(ValueError,
1637 "value 5 is not a valid Parameter.kind"):
1638 inspect.Parameter("bar", kind=5, default=42)
1639
1640 with self.assertRaisesRegex(TypeError,
1641 'name must be a str, not a int'):
1642 inspect.Parameter(123, kind=4)
1643
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001644class TestGetcallargsMethods(TestGetcallargsFunctions):
1645
1646 def setUp(self):
1647 class Foo(object):
1648 pass
1649 self.cls = Foo
1650 self.inst = Foo()
1651
1652 def makeCallable(self, signature):
1653 assert 'self' not in signature
1654 mk = super(TestGetcallargsMethods, self).makeCallable
1655 self.cls.method = mk('self, ' + signature)
1656 return self.inst.method
1657
1658class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1659
1660 def makeCallable(self, signature):
1661 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1662 return self.cls.method
1663
1664 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1665 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1666 *self._getAssertEqualParams(func, call_params_string, locs))
1667
1668 def assertEqualException(self, func, call_params_string, locs=None):
1669 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1670 *self._getAssertEqualParams(func, call_params_string, locs))
1671
1672 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1673 assert 'inst' not in call_params_string
1674 locs = dict(locs or {}, inst=self.inst)
1675 return (func, 'inst,' + call_params_string, locs)
1676
Michael Foord95fc51d2010-11-20 15:07:30 +00001677
1678class TestGetattrStatic(unittest.TestCase):
1679
1680 def test_basic(self):
1681 class Thing(object):
1682 x = object()
1683
1684 thing = Thing()
1685 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1686 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1687 with self.assertRaises(AttributeError):
1688 inspect.getattr_static(thing, 'y')
1689
1690 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1691
1692 def test_inherited(self):
1693 class Thing(object):
1694 x = object()
1695 class OtherThing(Thing):
1696 pass
1697
1698 something = OtherThing()
1699 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1700
1701 def test_instance_attr(self):
1702 class Thing(object):
1703 x = 2
1704 def __init__(self, x):
1705 self.x = x
1706 thing = Thing(3)
1707 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1708 del thing.x
1709 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1710
1711 def test_property(self):
1712 class Thing(object):
1713 @property
1714 def x(self):
1715 raise AttributeError("I'm pretending not to exist")
1716 thing = Thing()
1717 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1718
Ezio Melotti75cbd732011-04-28 00:59:29 +03001719 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001720 class descriptor(object):
1721 def __get__(*_):
1722 raise AttributeError("I'm pretending not to exist")
1723 desc = descriptor()
1724 class Thing(object):
1725 x = desc
1726 thing = Thing()
1727 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1728
1729 def test_classAttribute(self):
1730 class Thing(object):
1731 x = object()
1732
1733 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1734
Ethan Furmane03ea372013-09-25 07:14:41 -07001735 def test_classVirtualAttribute(self):
1736 class Thing(object):
1737 @types.DynamicClassAttribute
1738 def x(self):
1739 return self._x
1740 _x = object()
1741
1742 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1743
Michael Foord95fc51d2010-11-20 15:07:30 +00001744 def test_inherited_classattribute(self):
1745 class Thing(object):
1746 x = object()
1747 class OtherThing(Thing):
1748 pass
1749
1750 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1751
1752 def test_slots(self):
1753 class Thing(object):
1754 y = 'bar'
1755 __slots__ = ['x']
1756 def __init__(self):
1757 self.x = 'foo'
1758 thing = Thing()
1759 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1760 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1761
1762 del thing.x
1763 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1764
1765 def test_metaclass(self):
1766 class meta(type):
1767 attr = 'foo'
1768 class Thing(object, metaclass=meta):
1769 pass
1770 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1771
1772 class sub(meta):
1773 pass
1774 class OtherThing(object, metaclass=sub):
1775 x = 3
1776 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1777
1778 class OtherOtherThing(OtherThing):
1779 pass
1780 # this test is odd, but it was added as it exposed a bug
1781 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1782
1783 def test_no_dict_no_slots(self):
1784 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1785 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1786
1787 def test_no_dict_no_slots_instance_member(self):
1788 # returns descriptor
1789 with open(__file__) as handle:
1790 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1791
1792 def test_inherited_slots(self):
1793 # returns descriptor
1794 class Thing(object):
1795 __slots__ = ['x']
1796 def __init__(self):
1797 self.x = 'foo'
1798
1799 class OtherThing(Thing):
1800 pass
1801 # it would be nice if this worked...
1802 # we get the descriptor instead of the instance attribute
1803 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1804
1805 def test_descriptor(self):
1806 class descriptor(object):
1807 def __get__(self, instance, owner):
1808 return 3
1809 class Foo(object):
1810 d = descriptor()
1811
1812 foo = Foo()
1813
1814 # for a non data descriptor we return the instance attribute
1815 foo.__dict__['d'] = 1
1816 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1817
Mike53f7a7c2017-12-14 14:04:53 +03001818 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001819 # descriptor
1820 descriptor.__set__ = lambda s, i, v: None
1821 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1822
1823
1824 def test_metaclass_with_descriptor(self):
1825 class descriptor(object):
1826 def __get__(self, instance, owner):
1827 return 3
1828 class meta(type):
1829 d = descriptor()
1830 class Thing(object, metaclass=meta):
1831 pass
1832 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1833
1834
Michael Foordcc7ebb82010-11-20 16:20:16 +00001835 def test_class_as_property(self):
1836 class Base(object):
1837 foo = 3
1838
1839 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001840 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001841 @property
1842 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001843 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001844 return object
1845
Michael Foord35184ed2010-11-20 16:58:30 +00001846 instance = Something()
1847 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1848 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001849 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1850
Michael Foorde5162652010-11-20 16:40:44 +00001851 def test_mro_as_property(self):
1852 class Meta(type):
1853 @property
1854 def __mro__(self):
1855 return (object,)
1856
1857 class Base(object):
1858 foo = 3
1859
1860 class Something(Base, metaclass=Meta):
1861 pass
1862
1863 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1864 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1865
Michael Foorddcebe0f2011-03-15 19:20:44 -04001866 def test_dict_as_property(self):
1867 test = self
1868 test.called = False
1869
1870 class Foo(dict):
1871 a = 3
1872 @property
1873 def __dict__(self):
1874 test.called = True
1875 return {}
1876
1877 foo = Foo()
1878 foo.a = 4
1879 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1880 self.assertFalse(test.called)
1881
1882 def test_custom_object_dict(self):
1883 test = self
1884 test.called = False
1885
1886 class Custom(dict):
1887 def get(self, key, default=None):
1888 test.called = True
1889 super().get(key, default)
1890
1891 class Foo(object):
1892 a = 3
1893 foo = Foo()
1894 foo.__dict__ = Custom()
1895 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1896 self.assertFalse(test.called)
1897
1898 def test_metaclass_dict_as_property(self):
1899 class Meta(type):
1900 @property
1901 def __dict__(self):
1902 self.executed = True
1903
1904 class Thing(metaclass=Meta):
1905 executed = False
1906
1907 def __init__(self):
1908 self.spam = 42
1909
1910 instance = Thing()
1911 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1912 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001913
Michael Foorda51623b2011-12-18 22:01:40 +00001914 def test_module(self):
1915 sentinel = object()
1916 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1917 sentinel)
1918
Michael Foord3ba95f82011-12-22 01:13:37 +00001919 def test_metaclass_with_metaclass_with_dict_as_property(self):
1920 class MetaMeta(type):
1921 @property
1922 def __dict__(self):
1923 self.executed = True
1924 return dict(spam=42)
1925
1926 class Meta(type, metaclass=MetaMeta):
1927 executed = False
1928
1929 class Thing(metaclass=Meta):
1930 pass
1931
1932 with self.assertRaises(AttributeError):
1933 inspect.getattr_static(Thing, "spam")
1934 self.assertFalse(Thing.executed)
1935
Nick Coghlane0f04652010-11-21 03:44:04 +00001936class TestGetGeneratorState(unittest.TestCase):
1937
1938 def setUp(self):
1939 def number_generator():
1940 for number in range(5):
1941 yield number
1942 self.generator = number_generator()
1943
1944 def _generatorstate(self):
1945 return inspect.getgeneratorstate(self.generator)
1946
1947 def test_created(self):
1948 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1949
1950 def test_suspended(self):
1951 next(self.generator)
1952 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1953
1954 def test_closed_after_exhaustion(self):
1955 for i in self.generator:
1956 pass
1957 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1958
1959 def test_closed_after_immediate_exception(self):
1960 with self.assertRaises(RuntimeError):
1961 self.generator.throw(RuntimeError)
1962 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1963
1964 def test_running(self):
1965 # As mentioned on issue #10220, checking for the RUNNING state only
1966 # makes sense inside the generator itself.
1967 # The following generator checks for this by using the closure's
1968 # reference to self and the generator state checking helper method
1969 def running_check_generator():
1970 for number in range(5):
1971 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1972 yield number
1973 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1974 self.generator = running_check_generator()
1975 # Running up to the first yield
1976 next(self.generator)
1977 # Running after the first yield
1978 next(self.generator)
1979
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001980 def test_easy_debugging(self):
1981 # repr() and str() of a generator state should contain the state name
1982 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1983 for name in names:
1984 state = getattr(inspect, name)
1985 self.assertIn(name, repr(state))
1986 self.assertIn(name, str(state))
1987
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001988 def test_getgeneratorlocals(self):
1989 def each(lst, a=None):
1990 b=(1, 2, 3)
1991 for v in lst:
1992 if v == 3:
1993 c = 12
1994 yield v
1995
1996 numbers = each([1, 2, 3])
1997 self.assertEqual(inspect.getgeneratorlocals(numbers),
1998 {'a': None, 'lst': [1, 2, 3]})
1999 next(numbers)
2000 self.assertEqual(inspect.getgeneratorlocals(numbers),
2001 {'a': None, 'lst': [1, 2, 3], 'v': 1,
2002 'b': (1, 2, 3)})
2003 next(numbers)
2004 self.assertEqual(inspect.getgeneratorlocals(numbers),
2005 {'a': None, 'lst': [1, 2, 3], 'v': 2,
2006 'b': (1, 2, 3)})
2007 next(numbers)
2008 self.assertEqual(inspect.getgeneratorlocals(numbers),
2009 {'a': None, 'lst': [1, 2, 3], 'v': 3,
2010 'b': (1, 2, 3), 'c': 12})
2011 try:
2012 next(numbers)
2013 except StopIteration:
2014 pass
2015 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
2016
2017 def test_getgeneratorlocals_empty(self):
2018 def yield_one():
2019 yield 1
2020 one = yield_one()
2021 self.assertEqual(inspect.getgeneratorlocals(one), {})
2022 try:
2023 next(one)
2024 except StopIteration:
2025 pass
2026 self.assertEqual(inspect.getgeneratorlocals(one), {})
2027
2028 def test_getgeneratorlocals_error(self):
2029 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
2030 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
2031 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
2032 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
2033
Nick Coghlane0f04652010-11-21 03:44:04 +00002034
Yury Selivanov5376ba92015-06-22 12:19:30 -04002035class TestGetCoroutineState(unittest.TestCase):
2036
2037 def setUp(self):
2038 @types.coroutine
2039 def number_coroutine():
2040 for number in range(5):
2041 yield number
2042 async def coroutine():
2043 await number_coroutine()
2044 self.coroutine = coroutine()
2045
2046 def tearDown(self):
2047 self.coroutine.close()
2048
2049 def _coroutinestate(self):
2050 return inspect.getcoroutinestate(self.coroutine)
2051
2052 def test_created(self):
2053 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
2054
2055 def test_suspended(self):
2056 self.coroutine.send(None)
2057 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
2058
2059 def test_closed_after_exhaustion(self):
2060 while True:
2061 try:
2062 self.coroutine.send(None)
2063 except StopIteration:
2064 break
2065
2066 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2067
2068 def test_closed_after_immediate_exception(self):
2069 with self.assertRaises(RuntimeError):
2070 self.coroutine.throw(RuntimeError)
2071 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2072
2073 def test_easy_debugging(self):
2074 # repr() and str() of a coroutine state should contain the state name
2075 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2076 for name in names:
2077 state = getattr(inspect, name)
2078 self.assertIn(name, repr(state))
2079 self.assertIn(name, str(state))
2080
2081 def test_getcoroutinelocals(self):
2082 @types.coroutine
2083 def gencoro():
2084 yield
2085
2086 gencoro = gencoro()
2087 async def func(a=None):
2088 b = 'spam'
2089 await gencoro
2090
2091 coro = func()
2092 self.assertEqual(inspect.getcoroutinelocals(coro),
2093 {'a': None, 'gencoro': gencoro})
2094 coro.send(None)
2095 self.assertEqual(inspect.getcoroutinelocals(coro),
2096 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2097
2098
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002099class MySignature(inspect.Signature):
2100 # Top-level to make it picklable;
2101 # used in test_signature_object_pickle
2102 pass
2103
2104class MyParameter(inspect.Parameter):
2105 # Top-level to make it picklable;
2106 # used in test_signature_object_pickle
2107 pass
2108
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002109
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002110
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002111class TestSignatureObject(unittest.TestCase):
2112 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002113 def signature(func, **kw):
2114 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002115 return (tuple((param.name,
2116 (... if param.default is param.empty else param.default),
2117 (... if param.annotation is param.empty
2118 else param.annotation),
2119 str(param.kind).lower())
2120 for param in sig.parameters.values()),
2121 (... if sig.return_annotation is sig.empty
2122 else sig.return_annotation))
2123
2124 def test_signature_object(self):
2125 S = inspect.Signature
2126 P = inspect.Parameter
2127
2128 self.assertEqual(str(S()), '()')
Jens Reidel611836a2020-03-18 03:22:46 +01002129 self.assertEqual(repr(S().parameters), 'mappingproxy(OrderedDict())')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002130
Yury Selivanov07a9e452014-01-29 10:58:16 -05002131 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002132 pass
2133 sig = inspect.signature(test)
2134 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002135 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002136 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002137 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002138 args = sig.parameters['args']
2139 ko = sig.parameters['ko']
2140 kwargs = sig.parameters['kwargs']
2141
2142 S((po, pk, args, ko, kwargs))
2143
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002144 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002145 S((pk, po, args, ko, kwargs))
2146
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002147 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002148 S((po, args, pk, ko, kwargs))
2149
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002150 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002151 S((args, po, pk, ko, kwargs))
2152
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002153 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002154 S((po, pk, args, kwargs, ko))
2155
2156 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002157 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002158 S((po, pk, args, kwargs2, ko))
2159
Yury Selivanov07a9e452014-01-29 10:58:16 -05002160 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2161 S((pod, po))
2162
2163 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2164 S((po, pkd, pk))
2165
2166 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2167 S((pkd, pk))
2168
Yury Selivanov374375d2014-03-27 12:41:53 -04002169 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002170 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002171
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002172 def test_signature_object_pickle(self):
2173 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2174 foo_partial = functools.partial(foo, a=1)
2175
2176 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002177
2178 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2179 with self.subTest(pickle_ver=ver, subclass=False):
2180 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2181 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002182
2183 # Test that basic sub-classing works
2184 sig = inspect.signature(foo)
2185 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2186 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2187 mysig = MySignature().replace(parameters=myparams.values(),
2188 return_annotation=sig.return_annotation)
2189 self.assertTrue(isinstance(mysig, MySignature))
2190 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2191
2192 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2193 with self.subTest(pickle_ver=ver, subclass=True):
2194 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2195 self.assertEqual(mysig, sig_pickled)
2196 self.assertTrue(isinstance(sig_pickled, MySignature))
2197 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2198 MyParameter))
2199
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002200 def test_signature_immutability(self):
2201 def test(a):
2202 pass
2203 sig = inspect.signature(test)
2204
2205 with self.assertRaises(AttributeError):
2206 sig.foo = 'bar'
2207
2208 with self.assertRaises(TypeError):
2209 sig.parameters['a'] = None
2210
2211 def test_signature_on_noarg(self):
2212 def test():
2213 pass
2214 self.assertEqual(self.signature(test), ((), ...))
2215
2216 def test_signature_on_wargs(self):
2217 def test(a, b:'foo') -> 123:
2218 pass
2219 self.assertEqual(self.signature(test),
2220 ((('a', ..., ..., "positional_or_keyword"),
2221 ('b', ..., 'foo', "positional_or_keyword")),
2222 123))
2223
2224 def test_signature_on_wkwonly(self):
2225 def test(*, a:float, b:str) -> int:
2226 pass
2227 self.assertEqual(self.signature(test),
2228 ((('a', ..., float, "keyword_only"),
2229 ('b', ..., str, "keyword_only")),
2230 int))
2231
2232 def test_signature_on_complex_args(self):
2233 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2234 pass
2235 self.assertEqual(self.signature(test),
2236 ((('a', ..., ..., "positional_or_keyword"),
2237 ('b', 10, 'foo', "positional_or_keyword"),
2238 ('args', ..., 'bar', "var_positional"),
2239 ('spam', ..., 'baz', "keyword_only"),
2240 ('ham', 123, ..., "keyword_only"),
2241 ('kwargs', ..., int, "var_keyword")),
2242 ...))
2243
Dong-hee Na378d7062017-05-18 04:00:51 +09002244 def test_signature_without_self(self):
2245 def test_args_only(*args): # NOQA
2246 pass
2247
2248 def test_args_kwargs_only(*args, **kwargs): # NOQA
2249 pass
2250
2251 class A:
2252 @classmethod
2253 def test_classmethod(*args): # NOQA
2254 pass
2255
2256 @staticmethod
2257 def test_staticmethod(*args): # NOQA
2258 pass
2259
2260 f1 = functools.partialmethod((test_classmethod), 1)
2261 f2 = functools.partialmethod((test_args_only), 1)
2262 f3 = functools.partialmethod((test_staticmethod), 1)
2263 f4 = functools.partialmethod((test_args_kwargs_only),1)
2264
2265 self.assertEqual(self.signature(test_args_only),
2266 ((('args', ..., ..., 'var_positional'),), ...))
2267 self.assertEqual(self.signature(test_args_kwargs_only),
2268 ((('args', ..., ..., 'var_positional'),
2269 ('kwargs', ..., ..., 'var_keyword')), ...))
2270 self.assertEqual(self.signature(A.f1),
2271 ((('args', ..., ..., 'var_positional'),), ...))
2272 self.assertEqual(self.signature(A.f2),
2273 ((('args', ..., ..., 'var_positional'),), ...))
2274 self.assertEqual(self.signature(A.f3),
2275 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002276 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002277 ((('args', ..., ..., 'var_positional'),
2278 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002279 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002280 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2281 "Signature information for builtins requires docstrings")
2282 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002283 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002284
Larry Hastings5c661892014-01-24 06:17:25 -08002285 def test_unbound_method(o):
2286 """Use this to test unbound methods (things that should have a self)"""
2287 signature = inspect.signature(o)
2288 self.assertTrue(isinstance(signature, inspect.Signature))
2289 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2290 return signature
2291
2292 def test_callable(o):
2293 """Use this to test bound methods or normal callables (things that don't expect self)"""
2294 signature = inspect.signature(o)
2295 self.assertTrue(isinstance(signature, inspect.Signature))
2296 if signature.parameters:
2297 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2298 return signature
2299
2300 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002301 def p(name): return signature.parameters[name].default
2302 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002303 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002304 self.assertEqual(p('d'), 3.14)
2305 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002306 self.assertEqual(p('n'), None)
2307 self.assertEqual(p('t'), True)
2308 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002309 self.assertEqual(p('local'), 3)
2310 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002311 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002312
Larry Hastings5c661892014-01-24 06:17:25 -08002313 test_callable(object)
2314
2315 # normal method
2316 # (PyMethodDescr_Type, "method_descriptor")
2317 test_unbound_method(_pickle.Pickler.dump)
2318 d = _pickle.Pickler(io.StringIO())
2319 test_callable(d.dump)
2320
2321 # static method
Serhiy Storchaka279f4462019-09-14 12:24:05 +03002322 test_callable(bytes.maketrans)
2323 test_callable(b'abc'.maketrans)
Larry Hastings5c661892014-01-24 06:17:25 -08002324
2325 # class method
2326 test_callable(dict.fromkeys)
2327 test_callable({}.fromkeys)
2328
2329 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2330 test_unbound_method(type.__call__)
2331 test_unbound_method(int.__add__)
2332 test_callable((3).__add__)
2333
2334 # _PyMethodWrapper_Type
2335 # support for 'method-wrapper'
2336 test_callable(min.__call__)
2337
Larry Hastings2623c8c2014-02-08 22:15:29 -08002338 # This doesn't work now.
2339 # (We don't have a valid signature for "type" in 3.4)
2340 with self.assertRaisesRegex(ValueError, "no signature found"):
2341 class ThisWorksNow:
2342 __call__ = type
2343 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002344
Yury Selivanov056e2652014-03-02 12:25:27 -05002345 # Regression test for issue #20786
2346 test_unbound_method(dict.__delitem__)
2347 test_unbound_method(property.__delete__)
2348
Zachary Ware8ef887c2015-04-13 18:22:35 -05002349 # Regression test for issue #20586
2350 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2351
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002352 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002353 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2354 "Signature information for builtins requires docstrings")
2355 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002356 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002357 func = _testcapi.docstring_with_signature_with_defaults
2358
2359 def decorator(func):
2360 @functools.wraps(func)
2361 def wrapper(*args, **kwargs) -> int:
2362 return func(*args, **kwargs)
2363 return wrapper
2364
2365 decorated_func = decorator(func)
2366
2367 self.assertEqual(inspect.signature(func),
2368 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002369
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002370 def wrapper_like(*args, **kwargs) -> int: pass
2371 self.assertEqual(inspect.signature(decorated_func,
2372 follow_wrapped=False),
2373 inspect.signature(wrapper_like))
2374
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002375 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002376 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002377 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002378 with self.assertRaisesRegex(ValueError,
2379 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002380 inspect.signature(_testcapi.docstring_no_signature)
2381
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002382 with self.assertRaisesRegex(ValueError,
2383 'no signature found for builtin'):
2384 inspect.signature(str)
2385
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002386 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002387 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002388 inspect.signature(42)
2389
Yury Selivanov63da7c72014-01-31 14:48:37 -05002390 def test_signature_from_functionlike_object(self):
2391 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2392 pass
2393
2394 class funclike:
2395 # Has to be callable, and have correct
2396 # __code__, __annotations__, __defaults__, __name__,
2397 # and __kwdefaults__ attributes
2398
2399 def __init__(self, func):
2400 self.__name__ = func.__name__
2401 self.__code__ = func.__code__
2402 self.__annotations__ = func.__annotations__
2403 self.__defaults__ = func.__defaults__
2404 self.__kwdefaults__ = func.__kwdefaults__
2405 self.func = func
2406
2407 def __call__(self, *args, **kwargs):
2408 return self.func(*args, **kwargs)
2409
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002410 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002411
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002412 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002413 self.assertEqual(sig_funclike, sig_func)
2414
2415 sig_funclike = inspect.signature(funclike(func))
2416 self.assertEqual(sig_funclike, sig_func)
2417
2418 # If object is not a duck type of function, then
2419 # signature will try to get a signature for its '__call__'
2420 # method
2421 fl = funclike(func)
2422 del fl.__defaults__
2423 self.assertEqual(self.signature(fl),
2424 ((('args', ..., ..., "var_positional"),
2425 ('kwargs', ..., ..., "var_keyword")),
2426 ...))
2427
Yury Selivanova773de02014-02-21 18:30:53 -05002428 # Test with cython-like builtins:
2429 _orig_isdesc = inspect.ismethoddescriptor
2430 def _isdesc(obj):
2431 if hasattr(obj, '_builtinmock'):
2432 return True
2433 return _orig_isdesc(obj)
2434
2435 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2436 builtin_func = funclike(func)
2437 # Make sure that our mock setup is working
2438 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2439 builtin_func._builtinmock = True
2440 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2441 self.assertEqual(inspect.signature(builtin_func), sig_func)
2442
Yury Selivanov63da7c72014-01-31 14:48:37 -05002443 def test_signature_functionlike_class(self):
2444 # We only want to duck type function-like objects,
2445 # not classes.
2446
2447 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2448 pass
2449
2450 class funclike:
2451 def __init__(self, marker):
2452 pass
2453
2454 __name__ = func.__name__
2455 __code__ = func.__code__
2456 __annotations__ = func.__annotations__
2457 __defaults__ = func.__defaults__
2458 __kwdefaults__ = func.__kwdefaults__
2459
Yury Selivanov63da7c72014-01-31 14:48:37 -05002460 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2461
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002462 def test_signature_on_method(self):
2463 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002464 def __init__(*args):
2465 pass
2466 def m1(self, arg1, arg2=1) -> int:
2467 pass
2468 def m2(*args):
2469 pass
2470 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002471 pass
2472
Yury Selivanov62560fb2014-01-28 12:26:24 -05002473 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002474 ((('arg1', ..., ..., "positional_or_keyword"),
2475 ('arg2', 1, ..., "positional_or_keyword")),
2476 int))
2477
Yury Selivanov62560fb2014-01-28 12:26:24 -05002478 self.assertEqual(self.signature(Test().m2),
2479 ((('args', ..., ..., "var_positional"),),
2480 ...))
2481
2482 self.assertEqual(self.signature(Test),
2483 ((('args', ..., ..., "var_positional"),),
2484 ...))
2485
2486 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2487 self.signature(Test())
2488
Yury Selivanov46c759d2015-05-27 21:56:53 -04002489 def test_signature_wrapped_bound_method(self):
2490 # Issue 24298
2491 class Test:
2492 def m1(self, arg1, arg2=1) -> int:
2493 pass
2494 @functools.wraps(Test().m1)
2495 def m1d(*args, **kwargs):
2496 pass
2497 self.assertEqual(self.signature(m1d),
2498 ((('arg1', ..., ..., "positional_or_keyword"),
2499 ('arg2', 1, ..., "positional_or_keyword")),
2500 int))
2501
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002502 def test_signature_on_classmethod(self):
2503 class Test:
2504 @classmethod
2505 def foo(cls, arg1, *, arg2=1):
2506 pass
2507
2508 meth = Test().foo
2509 self.assertEqual(self.signature(meth),
2510 ((('arg1', ..., ..., "positional_or_keyword"),
2511 ('arg2', 1, ..., "keyword_only")),
2512 ...))
2513
2514 meth = Test.foo
2515 self.assertEqual(self.signature(meth),
2516 ((('arg1', ..., ..., "positional_or_keyword"),
2517 ('arg2', 1, ..., "keyword_only")),
2518 ...))
2519
2520 def test_signature_on_staticmethod(self):
2521 class Test:
2522 @staticmethod
2523 def foo(cls, *, arg):
2524 pass
2525
2526 meth = Test().foo
2527 self.assertEqual(self.signature(meth),
2528 ((('cls', ..., ..., "positional_or_keyword"),
2529 ('arg', ..., ..., "keyword_only")),
2530 ...))
2531
2532 meth = Test.foo
2533 self.assertEqual(self.signature(meth),
2534 ((('cls', ..., ..., "positional_or_keyword"),
2535 ('arg', ..., ..., "keyword_only")),
2536 ...))
2537
2538 def test_signature_on_partial(self):
2539 from functools import partial
2540
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002541 Parameter = inspect.Parameter
2542
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002543 def test():
2544 pass
2545
2546 self.assertEqual(self.signature(partial(test)), ((), ...))
2547
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002548 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002549 inspect.signature(partial(test, 1))
2550
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002551 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002552 inspect.signature(partial(test, a=1))
2553
2554 def test(a, b, *, c, d):
2555 pass
2556
2557 self.assertEqual(self.signature(partial(test)),
2558 ((('a', ..., ..., "positional_or_keyword"),
2559 ('b', ..., ..., "positional_or_keyword"),
2560 ('c', ..., ..., "keyword_only"),
2561 ('d', ..., ..., "keyword_only")),
2562 ...))
2563
2564 self.assertEqual(self.signature(partial(test, 1)),
2565 ((('b', ..., ..., "positional_or_keyword"),
2566 ('c', ..., ..., "keyword_only"),
2567 ('d', ..., ..., "keyword_only")),
2568 ...))
2569
2570 self.assertEqual(self.signature(partial(test, 1, c=2)),
2571 ((('b', ..., ..., "positional_or_keyword"),
2572 ('c', 2, ..., "keyword_only"),
2573 ('d', ..., ..., "keyword_only")),
2574 ...))
2575
2576 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2577 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002578 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002579 ('c', 2, ..., "keyword_only"),
2580 ('d', ..., ..., "keyword_only")),
2581 ...))
2582
2583 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002584 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002585 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002586 ('d', ..., ..., "keyword_only")),
2587 ...))
2588
2589 self.assertEqual(self.signature(partial(test, a=1)),
2590 ((('a', 1, ..., "keyword_only"),
2591 ('b', ..., ..., "keyword_only"),
2592 ('c', ..., ..., "keyword_only"),
2593 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002594 ...))
2595
2596 def test(a, *args, b, **kwargs):
2597 pass
2598
2599 self.assertEqual(self.signature(partial(test, 1)),
2600 ((('args', ..., ..., "var_positional"),
2601 ('b', ..., ..., "keyword_only"),
2602 ('kwargs', ..., ..., "var_keyword")),
2603 ...))
2604
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002605 self.assertEqual(self.signature(partial(test, a=1)),
2606 ((('a', 1, ..., "keyword_only"),
2607 ('b', ..., ..., "keyword_only"),
2608 ('kwargs', ..., ..., "var_keyword")),
2609 ...))
2610
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002611 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2612 ((('args', ..., ..., "var_positional"),
2613 ('b', ..., ..., "keyword_only"),
2614 ('kwargs', ..., ..., "var_keyword")),
2615 ...))
2616
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002617 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2618 ((('args', ..., ..., "var_positional"),
2619 ('b', ..., ..., "keyword_only"),
2620 ('kwargs', ..., ..., "var_keyword")),
2621 ...))
2622
2623 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2624 ((('args', ..., ..., "var_positional"),
2625 ('b', 0, ..., "keyword_only"),
2626 ('kwargs', ..., ..., "var_keyword")),
2627 ...))
2628
2629 self.assertEqual(self.signature(partial(test, b=0)),
2630 ((('a', ..., ..., "positional_or_keyword"),
2631 ('args', ..., ..., "var_positional"),
2632 ('b', 0, ..., "keyword_only"),
2633 ('kwargs', ..., ..., "var_keyword")),
2634 ...))
2635
2636 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2637 ((('a', ..., ..., "positional_or_keyword"),
2638 ('args', ..., ..., "var_positional"),
2639 ('b', 0, ..., "keyword_only"),
2640 ('kwargs', ..., ..., "var_keyword")),
2641 ...))
2642
2643 def test(a, b, c:int) -> 42:
2644 pass
2645
2646 sig = test.__signature__ = inspect.signature(test)
2647
2648 self.assertEqual(self.signature(partial(partial(test, 1))),
2649 ((('b', ..., ..., "positional_or_keyword"),
2650 ('c', ..., int, "positional_or_keyword")),
2651 42))
2652
2653 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2654 ((('c', ..., int, "positional_or_keyword"),),
2655 42))
2656
2657 psig = inspect.signature(partial(partial(test, 1), 2))
2658
2659 def foo(a):
2660 return a
2661 _foo = partial(partial(foo, a=10), a=20)
2662 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002663 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002664 ...))
2665 # check that we don't have any side-effects in signature(),
2666 # and the partial object is still functioning
2667 self.assertEqual(_foo(), 20)
2668
2669 def foo(a, b, c):
2670 return a, b, c
2671 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002672
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002673 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002674 ((('b', 30, ..., "keyword_only"),
2675 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002676 ...))
2677 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002678
2679 def foo(a, b, c, *, d):
2680 return a, b, c, d
2681 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2682 self.assertEqual(self.signature(_foo),
2683 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002684 ('b', 10, ..., "keyword_only"),
2685 ('c', 20, ..., "keyword_only"),
2686 ('d', 30, ..., "keyword_only"),
2687 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002688 ...))
2689 ba = inspect.signature(_foo).bind(a=200, b=11)
2690 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2691
2692 def foo(a=1, b=2, c=3):
2693 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002694 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2695
2696 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002697 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002698
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002699 ba = inspect.signature(_foo).bind(11, 12)
2700 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002701
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002702 ba = inspect.signature(_foo).bind(11, b=12)
2703 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002704
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002705 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002706 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2707
2708 _foo = partial(_foo, b=10, c=20)
2709 ba = inspect.signature(_foo).bind(12)
2710 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2711
2712
2713 def foo(a, b, c, d, **kwargs):
2714 pass
2715 sig = inspect.signature(foo)
2716 params = sig.parameters.copy()
2717 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2718 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2719 foo.__signature__ = inspect.Signature(params.values())
2720 sig = inspect.signature(foo)
2721 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2722
2723 self.assertEqual(self.signature(partial(foo, 1)),
2724 ((('b', ..., ..., 'positional_only'),
2725 ('c', ..., ..., 'positional_or_keyword'),
2726 ('d', ..., ..., 'positional_or_keyword'),
2727 ('kwargs', ..., ..., 'var_keyword')),
2728 ...))
2729
2730 self.assertEqual(self.signature(partial(foo, 1, 2)),
2731 ((('c', ..., ..., 'positional_or_keyword'),
2732 ('d', ..., ..., 'positional_or_keyword'),
2733 ('kwargs', ..., ..., 'var_keyword')),
2734 ...))
2735
2736 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2737 ((('d', ..., ..., 'positional_or_keyword'),
2738 ('kwargs', ..., ..., 'var_keyword')),
2739 ...))
2740
2741 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2742 ((('c', 3, ..., 'keyword_only'),
2743 ('d', ..., ..., 'keyword_only'),
2744 ('kwargs', ..., ..., 'var_keyword')),
2745 ...))
2746
2747 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2748 ((('b', ..., ..., 'positional_only'),
2749 ('c', 3, ..., 'keyword_only'),
2750 ('d', ..., ..., 'keyword_only'),
2751 ('kwargs', ..., ..., 'var_keyword')),
2752 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002753
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002754 def test_signature_on_partialmethod(self):
2755 from functools import partialmethod
2756
2757 class Spam:
2758 def test():
2759 pass
2760 ham = partialmethod(test)
2761
2762 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2763 inspect.signature(Spam.ham)
2764
2765 class Spam:
2766 def test(it, a, *, c) -> 'spam':
2767 pass
2768 ham = partialmethod(test, c=1)
2769
2770 self.assertEqual(self.signature(Spam.ham),
2771 ((('it', ..., ..., 'positional_or_keyword'),
2772 ('a', ..., ..., 'positional_or_keyword'),
2773 ('c', 1, ..., 'keyword_only')),
2774 'spam'))
2775
2776 self.assertEqual(self.signature(Spam().ham),
2777 ((('a', ..., ..., 'positional_or_keyword'),
2778 ('c', 1, ..., 'keyword_only')),
2779 'spam'))
2780
Yury Selivanov8a387212018-03-06 12:59:45 -05002781 class Spam:
2782 def test(self: 'anno', x):
2783 pass
2784
2785 g = partialmethod(test, 1)
2786
2787 self.assertEqual(self.signature(Spam.g),
2788 ((('self', ..., 'anno', 'positional_or_keyword'),),
2789 ...))
2790
Yury Selivanov0486f812014-01-29 12:18:59 -05002791 def test_signature_on_fake_partialmethod(self):
2792 def foo(a): pass
2793 foo._partialmethod = 'spam'
2794 self.assertEqual(str(inspect.signature(foo)), '(a)')
2795
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002796 def test_signature_on_decorated(self):
2797 import functools
2798
2799 def decorator(func):
2800 @functools.wraps(func)
2801 def wrapper(*args, **kwargs) -> int:
2802 return func(*args, **kwargs)
2803 return wrapper
2804
2805 class Foo:
2806 @decorator
2807 def bar(self, a, b):
2808 pass
2809
2810 self.assertEqual(self.signature(Foo.bar),
2811 ((('self', ..., ..., "positional_or_keyword"),
2812 ('a', ..., ..., "positional_or_keyword"),
2813 ('b', ..., ..., "positional_or_keyword")),
2814 ...))
2815
2816 self.assertEqual(self.signature(Foo().bar),
2817 ((('a', ..., ..., "positional_or_keyword"),
2818 ('b', ..., ..., "positional_or_keyword")),
2819 ...))
2820
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002821 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2822 ((('args', ..., ..., "var_positional"),
2823 ('kwargs', ..., ..., "var_keyword")),
2824 ...)) # functools.wraps will copy __annotations__
2825 # from "func" to "wrapper", hence no
2826 # return_annotation
2827
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002828 # Test that we handle method wrappers correctly
2829 def decorator(func):
2830 @functools.wraps(func)
2831 def wrapper(*args, **kwargs) -> int:
2832 return func(42, *args, **kwargs)
2833 sig = inspect.signature(func)
2834 new_params = tuple(sig.parameters.values())[1:]
2835 wrapper.__signature__ = sig.replace(parameters=new_params)
2836 return wrapper
2837
2838 class Foo:
2839 @decorator
2840 def __call__(self, a, b):
2841 pass
2842
2843 self.assertEqual(self.signature(Foo.__call__),
2844 ((('a', ..., ..., "positional_or_keyword"),
2845 ('b', ..., ..., "positional_or_keyword")),
2846 ...))
2847
2848 self.assertEqual(self.signature(Foo().__call__),
2849 ((('b', ..., ..., "positional_or_keyword"),),
2850 ...))
2851
Nick Coghlane8c45d62013-07-28 20:00:01 +10002852 # Test we handle __signature__ partway down the wrapper stack
2853 def wrapped_foo_call():
2854 pass
2855 wrapped_foo_call.__wrapped__ = Foo.__call__
2856
2857 self.assertEqual(self.signature(wrapped_foo_call),
2858 ((('a', ..., ..., "positional_or_keyword"),
2859 ('b', ..., ..., "positional_or_keyword")),
2860 ...))
2861
2862
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002863 def test_signature_on_class(self):
2864 class C:
2865 def __init__(self, a):
2866 pass
2867
2868 self.assertEqual(self.signature(C),
2869 ((('a', ..., ..., "positional_or_keyword"),),
2870 ...))
2871
2872 class CM(type):
2873 def __call__(cls, a):
2874 pass
2875 class C(metaclass=CM):
2876 def __init__(self, b):
2877 pass
2878
2879 self.assertEqual(self.signature(C),
2880 ((('a', ..., ..., "positional_or_keyword"),),
2881 ...))
2882
2883 class CM(type):
2884 def __new__(mcls, name, bases, dct, *, foo=1):
2885 return super().__new__(mcls, name, bases, dct)
2886 class C(metaclass=CM):
2887 def __init__(self, b):
2888 pass
2889
2890 self.assertEqual(self.signature(C),
2891 ((('b', ..., ..., "positional_or_keyword"),),
2892 ...))
2893
2894 self.assertEqual(self.signature(CM),
2895 ((('name', ..., ..., "positional_or_keyword"),
2896 ('bases', ..., ..., "positional_or_keyword"),
2897 ('dct', ..., ..., "positional_or_keyword"),
2898 ('foo', 1, ..., "keyword_only")),
2899 ...))
2900
2901 class CMM(type):
2902 def __new__(mcls, name, bases, dct, *, foo=1):
2903 return super().__new__(mcls, name, bases, dct)
2904 def __call__(cls, nm, bs, dt):
2905 return type(nm, bs, dt)
2906 class CM(type, metaclass=CMM):
2907 def __new__(mcls, name, bases, dct, *, bar=2):
2908 return super().__new__(mcls, name, bases, dct)
2909 class C(metaclass=CM):
2910 def __init__(self, b):
2911 pass
2912
2913 self.assertEqual(self.signature(CMM),
2914 ((('name', ..., ..., "positional_or_keyword"),
2915 ('bases', ..., ..., "positional_or_keyword"),
2916 ('dct', ..., ..., "positional_or_keyword"),
2917 ('foo', 1, ..., "keyword_only")),
2918 ...))
2919
2920 self.assertEqual(self.signature(CM),
2921 ((('nm', ..., ..., "positional_or_keyword"),
2922 ('bs', ..., ..., "positional_or_keyword"),
2923 ('dt', ..., ..., "positional_or_keyword")),
2924 ...))
2925
2926 self.assertEqual(self.signature(C),
2927 ((('b', ..., ..., "positional_or_keyword"),),
2928 ...))
2929
2930 class CM(type):
2931 def __init__(cls, name, bases, dct, *, bar=2):
2932 return super().__init__(name, bases, dct)
2933 class C(metaclass=CM):
2934 def __init__(self, b):
2935 pass
2936
2937 self.assertEqual(self.signature(CM),
2938 ((('name', ..., ..., "positional_or_keyword"),
2939 ('bases', ..., ..., "positional_or_keyword"),
2940 ('dct', ..., ..., "positional_or_keyword"),
2941 ('bar', 2, ..., "keyword_only")),
2942 ...))
2943
Yury Selivanov145dff82014-02-01 13:49:29 -05002944 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2945 "Signature information for builtins requires docstrings")
2946 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002947 # Test classes without user-defined __init__ or __new__
2948 class C: pass
2949 self.assertEqual(str(inspect.signature(C)), '()')
2950 class D(C): pass
2951 self.assertEqual(str(inspect.signature(D)), '()')
2952
2953 # Test meta-classes without user-defined __init__ or __new__
2954 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002955 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002956 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2957 self.assertEqual(inspect.signature(C), None)
2958 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2959 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002960
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002961 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2962 "Signature information for builtins requires docstrings")
2963 def test_signature_on_builtin_class(self):
Antoine Pitrou91f43802019-05-26 17:10:09 +02002964 expected = ('(file, protocol=None, fix_imports=True, '
2965 'buffer_callback=None)')
2966 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002967
2968 class P(_pickle.Pickler): pass
2969 class EmptyTrait: pass
2970 class P2(EmptyTrait, P): pass
Antoine Pitrou91f43802019-05-26 17:10:09 +02002971 self.assertEqual(str(inspect.signature(P)), expected)
2972 self.assertEqual(str(inspect.signature(P2)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002973
2974 class P3(P2):
2975 def __init__(self, spam):
2976 pass
2977 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2978
2979 class MetaP(type):
2980 def __call__(cls, foo, bar):
2981 pass
2982 class P4(P2, metaclass=MetaP):
2983 pass
2984 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2985
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002986 def test_signature_on_callable_objects(self):
2987 class Foo:
2988 def __call__(self, a):
2989 pass
2990
2991 self.assertEqual(self.signature(Foo()),
2992 ((('a', ..., ..., "positional_or_keyword"),),
2993 ...))
2994
2995 class Spam:
2996 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002997 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002998 inspect.signature(Spam())
2999
3000 class Bar(Spam, Foo):
3001 pass
3002
3003 self.assertEqual(self.signature(Bar()),
3004 ((('a', ..., ..., "positional_or_keyword"),),
3005 ...))
3006
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003007 class Wrapped:
3008 pass
3009 Wrapped.__wrapped__ = lambda a: None
3010 self.assertEqual(self.signature(Wrapped),
3011 ((('a', ..., ..., "positional_or_keyword"),),
3012 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10003013 # wrapper loop:
3014 Wrapped.__wrapped__ = Wrapped
3015 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3016 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003017
3018 def test_signature_on_lambdas(self):
3019 self.assertEqual(self.signature((lambda a=10: a)),
3020 ((('a', 10, ..., "positional_or_keyword"),),
3021 ...))
3022
3023 def test_signature_equality(self):
3024 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003025 self.assertFalse(inspect.signature(foo) == 42)
3026 self.assertTrue(inspect.signature(foo) != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003027 self.assertTrue(inspect.signature(foo) == ALWAYS_EQ)
3028 self.assertFalse(inspect.signature(foo) != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003029
3030 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003031 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3032 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003033 self.assertEqual(
3034 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003035
3036 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003037 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3038 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003039 self.assertNotEqual(
3040 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003041
3042 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003043 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3044 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003045 self.assertNotEqual(
3046 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003047
3048 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003049 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3050 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003051 self.assertNotEqual(
3052 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003053
3054 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003055 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3056 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003057 self.assertNotEqual(
3058 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003059
3060 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003061 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3062 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003063 self.assertNotEqual(
3064 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003065 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003066 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3067 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003068 self.assertNotEqual(
3069 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003070
3071 def foo(*, a, b, c): pass
3072 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003073 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3074 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003075 self.assertEqual(
3076 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003077
3078 def foo(*, a=1, b, c): pass
3079 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003080 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3081 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003082 self.assertEqual(
3083 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003084
3085 def foo(pos, *, a=1, b, c): pass
3086 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003087 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3088 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003089 self.assertEqual(
3090 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003091
3092 def foo(pos, *, a, b, c): pass
3093 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003094 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3095 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003096 self.assertNotEqual(
3097 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003098
3099 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3100 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003101 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3102 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003103 self.assertEqual(
3104 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003105
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003106 def test_signature_hashable(self):
3107 S = inspect.Signature
3108 P = inspect.Parameter
3109
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003110 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003111 foo_sig = inspect.signature(foo)
3112
3113 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3114
3115 self.assertEqual(hash(foo_sig), hash(manual_sig))
3116 self.assertNotEqual(hash(foo_sig),
3117 hash(manual_sig.replace(return_annotation='spam')))
3118
3119 def bar(a) -> 1: pass
3120 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3121
3122 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003123 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003124 hash(inspect.signature(foo))
3125
3126 def foo(a) -> {}: pass
3127 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3128 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003129
3130 def test_signature_str(self):
3131 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3132 pass
3133 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003134 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003135
3136 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3137 pass
3138 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003139 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003140
3141 def foo():
3142 pass
3143 self.assertEqual(str(inspect.signature(foo)), '()')
3144
3145 def test_signature_str_positional_only(self):
3146 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003147 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003148
3149 def test(a_po, *, b, **kwargs):
3150 return a_po, kwargs
3151
3152 sig = inspect.signature(test)
3153 new_params = list(sig.parameters.values())
3154 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3155 test.__signature__ = sig.replace(parameters=new_params)
3156
3157 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003158 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003159
Yury Selivanov2393dca2014-01-27 15:07:58 -05003160 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3161 '(foo, /)')
3162
3163 self.assertEqual(str(S(parameters=[
3164 P('foo', P.POSITIONAL_ONLY),
3165 P('bar', P.VAR_KEYWORD)])),
3166 '(foo, /, **bar)')
3167
3168 self.assertEqual(str(S(parameters=[
3169 P('foo', P.POSITIONAL_ONLY),
3170 P('bar', P.VAR_POSITIONAL)])),
3171 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003172
3173 def test_signature_replace_anno(self):
3174 def test() -> 42:
3175 pass
3176
3177 sig = inspect.signature(test)
3178 sig = sig.replace(return_annotation=None)
3179 self.assertIs(sig.return_annotation, None)
3180 sig = sig.replace(return_annotation=sig.empty)
3181 self.assertIs(sig.return_annotation, sig.empty)
3182 sig = sig.replace(return_annotation=42)
3183 self.assertEqual(sig.return_annotation, 42)
3184 self.assertEqual(sig, inspect.signature(test))
3185
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003186 def test_signature_on_mangled_parameters(self):
3187 class Spam:
3188 def foo(self, __p1:1=2, *, __p2:2=3):
3189 pass
3190 class Ham(Spam):
3191 pass
3192
3193 self.assertEqual(self.signature(Spam.foo),
3194 ((('self', ..., ..., "positional_or_keyword"),
3195 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3196 ('_Spam__p2', 3, 2, "keyword_only")),
3197 ...))
3198
3199 self.assertEqual(self.signature(Spam.foo),
3200 self.signature(Ham.foo))
3201
Yury Selivanovda396452014-03-27 12:09:24 -04003202 def test_signature_from_callable_python_obj(self):
3203 class MySignature(inspect.Signature): pass
3204 def foo(a, *, b:1): pass
3205 foo_sig = MySignature.from_callable(foo)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003206 self.assertIsInstance(foo_sig, MySignature)
3207
3208 def test_signature_from_callable_class(self):
3209 # A regression test for a class inheriting its signature from `object`.
3210 class MySignature(inspect.Signature): pass
3211 class foo: pass
3212 foo_sig = MySignature.from_callable(foo)
3213 self.assertIsInstance(foo_sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003214
3215 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3216 "Signature information for builtins requires docstrings")
3217 def test_signature_from_callable_builtin_obj(self):
3218 class MySignature(inspect.Signature): pass
3219 sig = MySignature.from_callable(_pickle.Pickler)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003220 self.assertIsInstance(sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003221
larryhastingsf36ba122018-01-28 11:13:09 -08003222 def test_signature_definition_order_preserved_on_kwonly(self):
3223 for fn in signatures_with_lexicographic_keyword_only_parameters():
3224 signature = inspect.signature(fn)
3225 l = list(signature.parameters)
3226 sorted_l = sorted(l)
3227 self.assertTrue(l)
3228 self.assertEqual(l, sorted_l)
3229 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3230 l = list(signature.parameters)
3231 self.assertEqual(l, unsorted_keyword_only_parameters)
3232
Jens Reidel611836a2020-03-18 03:22:46 +01003233 def test_signater_parameters_is_ordered(self):
3234 p1 = inspect.signature(lambda x, y: None).parameters
3235 p2 = inspect.signature(lambda y, x: None).parameters
3236 self.assertNotEqual(p1, p2)
3237
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003238
3239class TestParameterObject(unittest.TestCase):
3240 def test_signature_parameter_kinds(self):
3241 P = inspect.Parameter
3242 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3243 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3244
3245 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3246 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3247
3248 def test_signature_parameter_object(self):
3249 p = inspect.Parameter('foo', default=10,
3250 kind=inspect.Parameter.POSITIONAL_ONLY)
3251 self.assertEqual(p.name, 'foo')
3252 self.assertEqual(p.default, 10)
3253 self.assertIs(p.annotation, p.empty)
3254 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3255
Dong-hee Naa9cab432018-05-30 00:04:08 +09003256 with self.assertRaisesRegex(ValueError, "value '123' is "
3257 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003258 inspect.Parameter('foo', default=10, kind='123')
3259
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003260 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003261 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3262
Yury Selivanov2393dca2014-01-27 15:07:58 -05003263 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003264 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3265
Yury Selivanov2393dca2014-01-27 15:07:58 -05003266 with self.assertRaisesRegex(ValueError,
3267 'is not a valid parameter name'):
3268 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3269
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003270 with self.assertRaisesRegex(ValueError,
3271 'is not a valid parameter name'):
3272 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3273
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003274 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003275 inspect.Parameter('a', default=42,
3276 kind=inspect.Parameter.VAR_KEYWORD)
3277
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003278 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003279 inspect.Parameter('a', default=42,
3280 kind=inspect.Parameter.VAR_POSITIONAL)
3281
3282 p = inspect.Parameter('a', default=42,
3283 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003284 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003285 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3286
3287 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003288 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003289
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003290 def test_signature_parameter_hashable(self):
3291 P = inspect.Parameter
3292 foo = P('foo', kind=P.POSITIONAL_ONLY)
3293 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3294 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3295 default=42)))
3296 self.assertNotEqual(hash(foo),
3297 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3298
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003299 def test_signature_parameter_equality(self):
3300 P = inspect.Parameter
3301 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3302
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003303 self.assertTrue(p == p)
3304 self.assertFalse(p != p)
3305 self.assertFalse(p == 42)
3306 self.assertTrue(p != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003307 self.assertTrue(p == ALWAYS_EQ)
3308 self.assertFalse(p != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003309
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003310 self.assertTrue(p == P('foo', default=42,
3311 kind=inspect.Parameter.KEYWORD_ONLY))
3312 self.assertFalse(p != P('foo', default=42,
3313 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003314
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003315 def test_signature_parameter_replace(self):
3316 p = inspect.Parameter('foo', default=42,
3317 kind=inspect.Parameter.KEYWORD_ONLY)
3318
3319 self.assertIsNot(p, p.replace())
3320 self.assertEqual(p, p.replace())
3321
3322 p2 = p.replace(annotation=1)
3323 self.assertEqual(p2.annotation, 1)
3324 p2 = p2.replace(annotation=p2.empty)
3325 self.assertEqual(p, p2)
3326
3327 p2 = p2.replace(name='bar')
3328 self.assertEqual(p2.name, 'bar')
3329 self.assertNotEqual(p2, p)
3330
Yury Selivanov2393dca2014-01-27 15:07:58 -05003331 with self.assertRaisesRegex(ValueError,
3332 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003333 p2 = p2.replace(name=p2.empty)
3334
3335 p2 = p2.replace(name='foo', default=None)
3336 self.assertIs(p2.default, None)
3337 self.assertNotEqual(p2, p)
3338
3339 p2 = p2.replace(name='foo', default=p2.empty)
3340 self.assertIs(p2.default, p2.empty)
3341
3342
3343 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3344 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3345 self.assertNotEqual(p2, p)
3346
Dong-hee Naa9cab432018-05-30 00:04:08 +09003347 with self.assertRaisesRegex(ValueError,
3348 "value <class 'inspect._empty'> "
3349 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003350 p2 = p2.replace(kind=p2.empty)
3351
3352 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3353 self.assertEqual(p2, p)
3354
3355 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003356 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3357 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003358
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003359 @cpython_only
3360 def test_signature_parameter_implicit(self):
3361 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003362 'implicit arguments must be passed as '
3363 'positional or keyword arguments, '
3364 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003365 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3366
3367 param = inspect.Parameter(
3368 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3369 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3370 self.assertEqual(param.name, 'implicit0')
3371
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003372 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003373 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003374
3375 with self.assertRaises(AttributeError):
3376 p.foo = 'bar'
3377
3378 with self.assertRaises(AttributeError):
3379 p.kind = 123
3380
3381
3382class TestSignatureBind(unittest.TestCase):
3383 @staticmethod
3384 def call(func, *args, **kwargs):
3385 sig = inspect.signature(func)
3386 ba = sig.bind(*args, **kwargs)
3387 return func(*ba.args, **ba.kwargs)
3388
3389 def test_signature_bind_empty(self):
3390 def test():
3391 return 42
3392
3393 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003394 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003395 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003396 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003397 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003398 with self.assertRaisesRegex(
3399 TypeError, "got an unexpected keyword argument 'spam'"):
3400
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003401 self.call(test, spam=1)
3402
3403 def test_signature_bind_var(self):
3404 def test(*args, **kwargs):
3405 return args, kwargs
3406
3407 self.assertEqual(self.call(test), ((), {}))
3408 self.assertEqual(self.call(test, 1), ((1,), {}))
3409 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3410 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3411 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3412 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3413 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3414 ((1, 2), {'foo': 'bar'}))
3415
3416 def test_signature_bind_just_args(self):
3417 def test(a, b, c):
3418 return a, b, c
3419
3420 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3421
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003422 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003423 self.call(test, 1, 2, 3, 4)
3424
Yury Selivanov86872752015-05-19 00:27:49 -04003425 with self.assertRaisesRegex(TypeError,
3426 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003427 self.call(test, 1)
3428
Yury Selivanov86872752015-05-19 00:27:49 -04003429 with self.assertRaisesRegex(TypeError,
3430 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003431 self.call(test)
3432
3433 def test(a, b, c=10):
3434 return a, b, c
3435 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3436 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3437
3438 def test(a=1, b=2, c=3):
3439 return a, b, c
3440 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3441 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3442 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3443
3444 def test_signature_bind_varargs_order(self):
3445 def test(*args):
3446 return args
3447
3448 self.assertEqual(self.call(test), ())
3449 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3450
3451 def test_signature_bind_args_and_varargs(self):
3452 def test(a, b, c=3, *args):
3453 return a, b, c, args
3454
3455 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3456 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3457 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3458 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3459
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003460 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003461 "multiple values for argument 'c'"):
3462 self.call(test, 1, 2, 3, c=4)
3463
3464 def test_signature_bind_just_kwargs(self):
3465 def test(**kwargs):
3466 return kwargs
3467
3468 self.assertEqual(self.call(test), {})
3469 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3470 {'foo': 'bar', 'spam': 'ham'})
3471
3472 def test_signature_bind_args_and_kwargs(self):
3473 def test(a, b, c=3, **kwargs):
3474 return a, b, c, kwargs
3475
3476 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3477 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3478 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3479 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3480 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3481 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3482 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3483 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3484 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3485 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3486 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3487 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3488 (1, 2, 4, {'foo': 'bar'}))
3489 self.assertEqual(self.call(test, c=5, a=4, b=3),
3490 (4, 3, 5, {}))
3491
3492 def test_signature_bind_kwonly(self):
3493 def test(*, foo):
3494 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003495 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003496 'too many positional arguments'):
3497 self.call(test, 1)
3498 self.assertEqual(self.call(test, foo=1), 1)
3499
3500 def test(a, *, foo=1, bar):
3501 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003502 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003503 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003504 self.call(test, 1)
3505
3506 def test(foo, *, bar):
3507 return foo, bar
3508 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3509 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3510
Yury Selivanov86872752015-05-19 00:27:49 -04003511 with self.assertRaisesRegex(
3512 TypeError, "got an unexpected keyword argument 'spam'"):
3513
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003514 self.call(test, bar=2, foo=1, spam=10)
3515
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003516 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003517 'too many positional arguments'):
3518 self.call(test, 1, 2)
3519
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003520 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003521 'too many positional arguments'):
3522 self.call(test, 1, 2, bar=2)
3523
Yury Selivanov86872752015-05-19 00:27:49 -04003524 with self.assertRaisesRegex(
3525 TypeError, "got an unexpected keyword argument 'spam'"):
3526
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003527 self.call(test, 1, bar=2, spam='ham')
3528
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003529 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003530 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003531 self.call(test, 1)
3532
3533 def test(foo, *, bar, **bin):
3534 return foo, bar, bin
3535 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3536 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3537 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3538 (1, 2, {'spam': 'ham'}))
3539 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3540 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003541 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003542 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003543 self.call(test, spam='ham', bar=2)
3544 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3545 (1, 2, {'bin': 1, 'spam': 10}))
3546
3547 def test_signature_bind_arguments(self):
3548 def test(a, *args, b, z=100, **kwargs):
3549 pass
3550 sig = inspect.signature(test)
3551 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3552 # we won't have 'z' argument in the bound arguments object, as we didn't
3553 # pass it to the 'bind'
3554 self.assertEqual(tuple(ba.arguments.items()),
3555 (('a', 10), ('args', (20,)), ('b', 30),
3556 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3557 self.assertEqual(ba.kwargs,
3558 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3559 self.assertEqual(ba.args, (10, 20))
3560
3561 def test_signature_bind_positional_only(self):
3562 P = inspect.Parameter
3563
3564 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3565 return a_po, b_po, c_po, foo, bar, kwargs
3566
3567 sig = inspect.signature(test)
3568 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3569 for name in ('a_po', 'b_po', 'c_po'):
3570 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3571 new_sig = sig.replace(parameters=new_params.values())
3572 test.__signature__ = new_sig
3573
3574 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3575 (1, 2, 4, 5, 6, {}))
3576
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003577 self.assertEqual(self.call(test, 1, 2),
3578 (1, 2, 3, 42, 50, {}))
3579
3580 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3581 (1, 2, 3, 4, 5, {}))
3582
3583 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3584 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3585
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003586 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003587 self.call(test, 1, 2, c_po=4)
3588
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003589 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003590 self.call(test, a_po=1, b_po=2)
3591
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003592 def test_signature_bind_with_self_arg(self):
3593 # Issue #17071: one of the parameters is named "self
3594 def test(a, self, b):
3595 pass
3596 sig = inspect.signature(test)
3597 ba = sig.bind(1, 2, 3)
3598 self.assertEqual(ba.args, (1, 2, 3))
3599 ba = sig.bind(1, self=2, b=3)
3600 self.assertEqual(ba.args, (1, 2, 3))
3601
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003602 def test_signature_bind_vararg_name(self):
3603 def test(a, *args):
3604 return a, args
3605 sig = inspect.signature(test)
3606
Yury Selivanov86872752015-05-19 00:27:49 -04003607 with self.assertRaisesRegex(
3608 TypeError, "got an unexpected keyword argument 'args'"):
3609
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003610 sig.bind(a=0, args=1)
3611
3612 def test(*args, **kwargs):
3613 return args, kwargs
3614 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3615
3616 sig = inspect.signature(test)
3617 ba = sig.bind(args=1)
3618 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3619
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003620 @cpython_only
3621 def test_signature_bind_implicit_arg(self):
3622 # Issue #19611: getcallargs should work with set comprehensions
3623 def make_set():
3624 return {z * z for z in range(5)}
3625 setcomp_code = make_set.__code__.co_consts[1]
3626 setcomp_func = types.FunctionType(setcomp_code, {})
3627
3628 iterator = iter(range(5))
3629 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3630
Pablo Galindof3ef06a2019-10-15 12:40:02 +01003631 def test_signature_bind_posonly_kwargs(self):
3632 def foo(bar, /, **kwargs):
3633 return bar, kwargs.get(bar)
3634
3635 sig = inspect.signature(foo)
3636 result = sig.bind("pos-only", bar="keyword")
3637
3638 self.assertEqual(result.kwargs, {"bar": "keyword"})
3639 self.assertIn(("bar", "pos-only"), result.arguments.items())
3640
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003641
3642class TestBoundArguments(unittest.TestCase):
3643 def test_signature_bound_arguments_unhashable(self):
3644 def foo(a): pass
3645 ba = inspect.signature(foo).bind(1)
3646
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003647 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003648 hash(ba)
3649
3650 def test_signature_bound_arguments_equality(self):
3651 def foo(a): pass
3652 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003653 self.assertTrue(ba == ba)
3654 self.assertFalse(ba != ba)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003655 self.assertTrue(ba == ALWAYS_EQ)
3656 self.assertFalse(ba != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003657
3658 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003659 self.assertTrue(ba == ba2)
3660 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003661
3662 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003663 self.assertFalse(ba == ba3)
3664 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003665 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003666 self.assertTrue(ba == ba3)
3667 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003668
3669 def bar(b): pass
3670 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003671 self.assertFalse(ba == ba4)
3672 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003673
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003674 def foo(*, a, b): pass
3675 sig = inspect.signature(foo)
3676 ba1 = sig.bind(a=1, b=2)
3677 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003678 self.assertTrue(ba1 == ba2)
3679 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003680
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003681 def test_signature_bound_arguments_pickle(self):
3682 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3683 sig = inspect.signature(foo)
3684 ba = sig.bind(20, 30, z={})
3685
3686 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3687 with self.subTest(pickle_ver=ver):
3688 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3689 self.assertEqual(ba, ba_pickled)
3690
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003691 def test_signature_bound_arguments_repr(self):
3692 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3693 sig = inspect.signature(foo)
3694 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003695 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003696
Yury Selivanovb907a512015-05-16 13:45:09 -04003697 def test_signature_bound_arguments_apply_defaults(self):
3698 def foo(a, b=1, *args, c:1={}, **kw): pass
3699 sig = inspect.signature(foo)
3700
3701 ba = sig.bind(20)
3702 ba.apply_defaults()
3703 self.assertEqual(
3704 list(ba.arguments.items()),
3705 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3706
3707 # Make sure that we preserve the order:
3708 # i.e. 'c' should be *before* 'kw'.
3709 ba = sig.bind(10, 20, 30, d=1)
3710 ba.apply_defaults()
3711 self.assertEqual(
3712 list(ba.arguments.items()),
3713 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3714
3715 # Make sure that BoundArguments produced by bind_partial()
3716 # are supported.
3717 def foo(a, b): pass
3718 sig = inspect.signature(foo)
3719 ba = sig.bind_partial(20)
3720 ba.apply_defaults()
3721 self.assertEqual(
3722 list(ba.arguments.items()),
3723 [('a', 20)])
3724
3725 # Test no args
3726 def foo(): pass
3727 sig = inspect.signature(foo)
3728 ba = sig.bind()
3729 ba.apply_defaults()
3730 self.assertEqual(list(ba.arguments.items()), [])
3731
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003732 # Make sure a no-args binding still acquires proper defaults.
3733 def foo(a='spam'): pass
3734 sig = inspect.signature(foo)
3735 ba = sig.bind()
3736 ba.apply_defaults()
3737 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3738
Rémi Lapeyre2cca8ef2020-01-28 13:47:03 +01003739 def test_signature_bound_arguments_arguments_type(self):
3740 def foo(a): pass
3741 ba = inspect.signature(foo).bind(1)
3742 self.assertIs(type(ba.arguments), dict)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003743
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003744class TestSignaturePrivateHelpers(unittest.TestCase):
3745 def test_signature_get_bound_param(self):
3746 getter = inspect._signature_get_bound_param
3747
3748 self.assertEqual(getter('($self)'), 'self')
3749 self.assertEqual(getter('($self, obj)'), 'self')
3750 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3751
Larry Hastings2623c8c2014-02-08 22:15:29 -08003752 def _strip_non_python_syntax(self, input,
3753 clean_signature, self_parameter, last_positional_only):
3754 computed_clean_signature, \
3755 computed_self_parameter, \
3756 computed_last_positional_only = \
3757 inspect._signature_strip_non_python_syntax(input)
3758 self.assertEqual(computed_clean_signature, clean_signature)
3759 self.assertEqual(computed_self_parameter, self_parameter)
3760 self.assertEqual(computed_last_positional_only, last_positional_only)
3761
3762 def test_signature_strip_non_python_syntax(self):
3763 self._strip_non_python_syntax(
3764 "($module, /, path, mode, *, dir_fd=None, " +
3765 "effective_ids=False,\n follow_symlinks=True)",
3766 "(module, path, mode, *, dir_fd=None, " +
3767 "effective_ids=False, follow_symlinks=True)",
3768 0,
3769 0)
3770
3771 self._strip_non_python_syntax(
3772 "($module, word, salt, /)",
3773 "(module, word, salt)",
3774 0,
3775 2)
3776
3777 self._strip_non_python_syntax(
3778 "(x, y=None, z=None, /)",
3779 "(x, y=None, z=None)",
3780 None,
3781 2)
3782
3783 self._strip_non_python_syntax(
3784 "(x, y=None, z=None)",
3785 "(x, y=None, z=None)",
3786 None,
3787 None)
3788
3789 self._strip_non_python_syntax(
3790 "(x,\n y=None,\n z = None )",
3791 "(x, y=None, z=None)",
3792 None,
3793 None)
3794
3795 self._strip_non_python_syntax(
3796 "",
3797 "",
3798 None,
3799 None)
3800
3801 self._strip_non_python_syntax(
3802 None,
3803 None,
3804 None,
3805 None)
3806
Nick Coghlan9c680b02015-04-13 12:54:54 -04003807class TestSignatureDefinitions(unittest.TestCase):
3808 # This test case provides a home for checking that particular APIs
3809 # have signatures available for introspection
3810
3811 @cpython_only
3812 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3813 "Signature information for builtins requires docstrings")
3814 def test_builtins_have_signatures(self):
3815 # This checks all builtin callables in CPython have signatures
3816 # A few have signatures Signature can't yet handle, so we skip those
3817 # since they will have to wait until PEP 457 adds the required
3818 # introspection support to the inspect module
3819 # Some others also haven't been converted yet for various other
3820 # reasons, so we also skip those for the time being, but design
3821 # the test to fail in order to indicate when it needs to be
3822 # updated.
3823 no_signature = set()
3824 # These need PEP 457 groups
3825 needs_groups = {"range", "slice", "dir", "getattr",
3826 "next", "iter", "vars"}
3827 no_signature |= needs_groups
3828 # These need PEP 457 groups or a signature change to accept None
3829 needs_semantic_update = {"round"}
3830 no_signature |= needs_semantic_update
3831 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003832 needs_varargs = {"breakpoint", "min", "max", "print",
3833 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003834 no_signature |= needs_varargs
3835 # These simply weren't covered in the initial AC conversion
3836 # for builtin callables
3837 not_converted_yet = {"open", "__import__"}
3838 no_signature |= not_converted_yet
3839 # These builtin types are expected to provide introspection info
3840 types_with_signatures = set()
3841 # Check the signatures we expect to be there
3842 ns = vars(builtins)
3843 for name, obj in sorted(ns.items()):
3844 if not callable(obj):
3845 continue
3846 # The builtin types haven't been converted to AC yet
3847 if isinstance(obj, type) and (name not in types_with_signatures):
3848 # Note that this also skips all the exception types
3849 no_signature.add(name)
3850 if (name in no_signature):
3851 # Not yet converted
3852 continue
3853 with self.subTest(builtin=name):
3854 self.assertIsNotNone(inspect.signature(obj))
3855 # Check callables that haven't been converted don't claim a signature
3856 # This ensures this test will start failing as more signatures are
3857 # added, so the affected items can be moved into the scope of the
3858 # regression test above
3859 for name in no_signature:
3860 with self.subTest(builtin=name):
3861 self.assertIsNone(obj.__text_signature__)
3862
Serhiy Storchakad53cf992019-05-06 22:40:27 +03003863 def test_python_function_override_signature(self):
3864 def func(*args, **kwargs):
3865 pass
3866 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
3867 sig = inspect.signature(func)
3868 self.assertIsNotNone(sig)
3869 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
3870 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
3871 sig = inspect.signature(func)
3872 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
3873
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003874
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003875class NTimesUnwrappable:
3876 def __init__(self, n):
3877 self.n = n
3878 self._next = None
3879
3880 @property
3881 def __wrapped__(self):
3882 if self.n <= 0:
3883 raise Exception("Unwrapped too many times")
3884 if self._next is None:
3885 self._next = NTimesUnwrappable(self.n - 1)
3886 return self._next
3887
Nick Coghlane8c45d62013-07-28 20:00:01 +10003888class TestUnwrap(unittest.TestCase):
3889
3890 def test_unwrap_one(self):
3891 def func(a, b):
3892 return a + b
3893 wrapper = functools.lru_cache(maxsize=20)(func)
3894 self.assertIs(inspect.unwrap(wrapper), func)
3895
3896 def test_unwrap_several(self):
3897 def func(a, b):
3898 return a + b
3899 wrapper = func
3900 for __ in range(10):
3901 @functools.wraps(wrapper)
3902 def wrapper():
3903 pass
3904 self.assertIsNot(wrapper.__wrapped__, func)
3905 self.assertIs(inspect.unwrap(wrapper), func)
3906
3907 def test_stop(self):
3908 def func1(a, b):
3909 return a + b
3910 @functools.wraps(func1)
3911 def func2():
3912 pass
3913 @functools.wraps(func2)
3914 def wrapper():
3915 pass
3916 func2.stop_here = 1
3917 unwrapped = inspect.unwrap(wrapper,
3918 stop=(lambda f: hasattr(f, "stop_here")))
3919 self.assertIs(unwrapped, func2)
3920
3921 def test_cycle(self):
3922 def func1(): pass
3923 func1.__wrapped__ = func1
3924 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3925 inspect.unwrap(func1)
3926
3927 def func2(): pass
3928 func2.__wrapped__ = func1
3929 func1.__wrapped__ = func2
3930 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3931 inspect.unwrap(func1)
3932 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3933 inspect.unwrap(func2)
3934
3935 def test_unhashable(self):
3936 def func(): pass
3937 func.__wrapped__ = None
3938 class C:
3939 __hash__ = None
3940 __wrapped__ = func
3941 self.assertIsNone(inspect.unwrap(C()))
3942
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003943 def test_recursion_limit(self):
3944 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3945 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3946 inspect.unwrap(obj)
3947
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003948class TestMain(unittest.TestCase):
3949 def test_only_source(self):
3950 module = importlib.import_module('unittest')
3951 rc, out, err = assert_python_ok('-m', 'inspect',
3952 'unittest')
3953 lines = out.decode().splitlines()
3954 # ignore the final newline
3955 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3956 self.assertEqual(err, b'')
3957
Yury Selivanov42407ab2014-06-23 10:23:50 -07003958 def test_custom_getattr(self):
3959 def foo():
3960 pass
3961 foo.__signature__ = 42
3962 with self.assertRaises(TypeError):
3963 inspect.signature(foo)
3964
Brett Cannon634a8fc2013-10-02 10:25:42 -04003965 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003966 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003967 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003968 rc, out, err = assert_python_ok('-m', 'inspect',
3969 'concurrent.futures:ThreadPoolExecutor')
3970 lines = out.decode().splitlines()
3971 # ignore the final newline
3972 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003973 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003974 self.assertEqual(err, b'')
3975
3976 def test_builtins(self):
3977 module = importlib.import_module('unittest')
3978 _, out, err = assert_python_failure('-m', 'inspect',
3979 'sys')
3980 lines = err.decode().splitlines()
3981 self.assertEqual(lines, ["Can't get info for builtin modules."])
3982
3983 def test_details(self):
3984 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003985 args = support.optim_args_from_interpreter_flags()
3986 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003987 'unittest', '--details')
3988 output = out.decode()
3989 # Just a quick sanity check on the output
3990 self.assertIn(module.__name__, output)
3991 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003992 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003993 self.assertEqual(err, b'')
3994
3995
Yury Selivanovef1e7502014-12-08 16:05:34 -05003996class TestReload(unittest.TestCase):
3997
3998 src_before = textwrap.dedent("""\
3999def foo():
4000 print("Bla")
4001 """)
4002
4003 src_after = textwrap.dedent("""\
4004def foo():
4005 print("Oh no!")
4006 """)
4007
4008 def assertInspectEqual(self, path, source):
4009 inspected_src = inspect.getsource(source)
4010 with open(path) as src:
4011 self.assertEqual(
4012 src.read().splitlines(True),
4013 inspected_src.splitlines(True)
4014 )
4015
4016 def test_getsource_reload(self):
4017 # see issue 1218234
4018 with _ready_to_import('reload_bug', self.src_before) as (name, path):
4019 module = importlib.import_module(name)
4020 self.assertInspectEqual(path, module)
4021 with open(path, 'w') as src:
4022 src.write(self.src_after)
4023 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004024
Nick Coghlane8c45d62013-07-28 20:00:01 +10004025
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004026def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00004027 run_unittest(
4028 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
4029 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
4030 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00004031 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004032 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04004033 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04004034 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04004035 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07004036 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00004037 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00004038
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004039if __name__ == "__main__":
4040 test_main()