blob: e3e2be52076c6aab89f2d10f35114f280d16632d [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 Storchaka08b47c32020-05-18 20:25:07 +0300442 self.assertEqual(inspect.getdoc(mod.FesteringGob),
443 'A longer,\n\nindented\n\ndocstring.')
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300444 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
445 'Another\n\ndocstring\n\ncontaining\n\ntabs')
446 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
447 'Another\n\ndocstring\n\ncontaining\n\ntabs')
448 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
449 'The automatic gainsaying.')
450
451 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
452 def test_finddoc(self):
453 finddoc = inspect._finddoc
Serhiy Storchaka08b47c32020-05-18 20:25:07 +0300454 self.assertEqual(finddoc(int), int.__doc__)
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300455 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
456 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
457 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
458 self.assertEqual(finddoc(int.real), int.real.__doc__)
459
Georg Brandl0c77a822008-06-10 16:37:50 +0000460 def test_cleandoc(self):
461 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
462 'An\nindented\ndocstring.')
463
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000464 def test_getcomments(self):
465 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
466 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530467 self.assertEqual(inspect.getcomments(mod2.cls160), '# line 159\n')
Marco Buttu3f2155f2017-03-17 09:50:23 +0100468 # If the object source file is not available, return None.
469 co = compile('x=1', '_non_existing_filename.py', 'exec')
470 self.assertIsNone(inspect.getcomments(co))
471 # If the object has been defined in C, return None.
472 self.assertIsNone(inspect.getcomments(list))
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000473
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000474 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000475 # Check actual module
476 self.assertEqual(inspect.getmodule(mod), mod)
477 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000478 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000479 # Check a method (no __module__ attribute, falls back to filename)
480 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
481 # Do it again (check the caching isn't broken)
482 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
483 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000484 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000485 # Check filename override
486 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000487
Berker Peksagff0e3b72017-01-02 06:57:43 +0300488 def test_getframeinfo_get_first_line(self):
489 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
490 self.assertEqual(frame_info.code_context[0], "# line 1\n")
491 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
492
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000493 def test_getsource(self):
494 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200495 self.assertSourceEqual(mod.StupidGit, 21, 51)
496 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000497
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000498 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000499 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
500 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000501 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100502 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000503 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000504 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200505 try:
506 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
507 finally:
508 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000509
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000510 def test_getfile(self):
511 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000512
Philipp Ad407d2a2019-06-08 14:05:46 +0200513 def test_getfile_builtin_module(self):
514 with self.assertRaises(TypeError) as e:
515 inspect.getfile(sys)
516 self.assertTrue(str(e.exception).startswith('<module'))
517
518 def test_getfile_builtin_class(self):
519 with self.assertRaises(TypeError) as e:
520 inspect.getfile(int)
521 self.assertTrue(str(e.exception).startswith('<class'))
522
523 def test_getfile_builtin_function_or_method(self):
524 with self.assertRaises(TypeError) as e_abs:
525 inspect.getfile(abs)
526 self.assertIn('expected, got', str(e_abs.exception))
527 with self.assertRaises(TypeError) as e_append:
528 inspect.getfile(list.append)
529 self.assertIn('expected, got', str(e_append.exception))
530
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500531 def test_getfile_class_without_module(self):
532 class CM(type):
533 @property
534 def __module__(cls):
535 raise AttributeError
536 class C(metaclass=CM):
537 pass
538 with self.assertRaises(TypeError):
539 inspect.getfile(C)
540
Thomas Kluyvere968bc732017-10-24 13:42:36 +0100541 def test_getfile_broken_repr(self):
542 class ErrorRepr:
543 def __repr__(self):
544 raise Exception('xyz')
545 er = ErrorRepr()
546 with self.assertRaises(TypeError):
547 inspect.getfile(er)
548
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000549 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000550 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000551 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000552 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000553 m.__file__ = "<string>" # hopefully not a real filename...
554 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000555 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000556 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000557 del sys.modules[name]
558 inspect.getmodule(compile('a=10','','single'))
559
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500560 def test_proceed_with_fake_filename(self):
561 '''doctest monkeypatches linecache to enable inspection'''
562 fn, source = '<test>', 'def x(): pass\n'
563 getlines = linecache.getlines
564 def monkey(filename, module_globals=None):
565 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300566 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500567 else:
568 return getlines(filename, module_globals)
569 linecache.getlines = monkey
570 try:
571 ns = {}
572 exec(compile(source, fn, 'single'), ns)
573 inspect.getsource(ns["x"])
574 finally:
575 linecache.getlines = getlines
576
Antoine Pitroua8723a02015-04-15 00:41:29 +0200577 def test_getsource_on_code_object(self):
578 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
579
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700580class TestGettingSourceOfToplevelFrames(GetSourceBase):
581 fodderModule = mod
582
583 def test_range_toplevel_frame(self):
584 self.maxDiff = None
585 self.assertSourceEqual(mod.currentframe, 1, None)
586
587 def test_range_traceback_toplevel_frame(self):
588 self.assertSourceEqual(mod.tb, 1, None)
589
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000590class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000591 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000592
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000593 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000594 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000595
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000596 def test_replacing_decorator(self):
597 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000598
Yury Selivanov081bbf62014-09-26 17:34:54 -0400599 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200600 self.assertSourceEqual(mod2.real, 130, 132)
601
602 def test_decorator_with_lambda(self):
603 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400604
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000605class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000606 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000607 def test_oneline_lambda(self):
608 # Test inspect.getsource with a one-line lambda function.
609 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000610
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000611 def test_threeline_lambda(self):
612 # Test inspect.getsource with a three-line lambda function,
613 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000614 self.assertSourceEqual(mod2.tll, 28, 30)
615
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000616 def test_twoline_indented_lambda(self):
617 # Test inspect.getsource with a two-line lambda function,
618 # where the second line _is_ indented.
619 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000620
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000621 def test_onelinefunc(self):
622 # Test inspect.getsource with a regular one-line function.
623 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000624
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000625 def test_manyargs(self):
626 # Test inspect.getsource with a regular function where
627 # the arguments are on two lines and _not_ indented and
628 # the body on the second line with the last arguments.
629 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000630
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000631 def test_twolinefunc(self):
632 # Test inspect.getsource with a regular function where
633 # the body is on two lines, following the argument list and
634 # continued on the next line by a \\.
635 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000636
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000637 def test_lambda_in_list(self):
638 # Test inspect.getsource with a one-line lambda function
639 # defined in a list, indented.
640 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000641
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000642 def test_anonymous(self):
643 # Test inspect.getsource with a lambda function defined
644 # as argument to another function.
645 self.assertSourceEqual(mod2.anonymous, 55, 55)
646
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000647class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000648 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000649
650 def test_with_comment(self):
651 self.assertSourceEqual(mod2.with_comment, 58, 59)
652
653 def test_multiline_sig(self):
654 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
655
Armin Rigodd5c0232005-09-25 11:45:45 +0000656 def test_nested_class(self):
657 self.assertSourceEqual(mod2.func69().func71, 71, 72)
658
659 def test_one_liner_followed_by_non_name(self):
660 self.assertSourceEqual(mod2.func77, 77, 77)
661
662 def test_one_liner_dedent_non_name(self):
663 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
664
665 def test_with_comment_instead_of_docstring(self):
666 self.assertSourceEqual(mod2.func88, 88, 90)
667
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000668 def test_method_in_dynamic_class(self):
669 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
670
R David Murray32562d72014-10-03 11:15:38 -0400671 # This should not skip for CPython, but might on a repackaged python where
672 # unicodedata is not an external module, or on pypy.
673 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
674 unicodedata.__file__.endswith('.py'),
675 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000676 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200677 self.assertRaises(OSError, inspect.getsource, unicodedata)
678 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000679
R. David Murraya1b37402010-06-17 02:04:29 +0000680 def test_findsource_code_in_linecache(self):
681 lines = ["x=1"]
682 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200683 self.assertRaises(OSError, inspect.findsource, co)
684 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000685 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200686 try:
687 self.assertEqual(inspect.findsource(co), (lines,0))
688 self.assertEqual(inspect.getsource(co), lines[0])
689 finally:
690 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000691
Ezio Melotti1b145922013-03-30 05:17:24 +0200692 def test_findsource_without_filename(self):
693 for fname in ['', '<string>']:
694 co = compile('x=1', fname, "exec")
695 self.assertRaises(IOError, inspect.findsource, co)
696 self.assertRaises(IOError, inspect.getsource, co)
697
Antoine Pitroua8723a02015-04-15 00:41:29 +0200698 def test_getsource_on_method(self):
699 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
700
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300701 def test_nested_func(self):
702 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
703
Karthikeyan Singaravelan696136b2020-04-18 21:49:32 +0530704 def test_class_definition_in_multiline_string_definition(self):
705 self.assertSourceEqual(mod2.cls149, 149, 152)
706
707 def test_class_definition_in_multiline_comment(self):
708 self.assertSourceEqual(mod2.cls160, 160, 163)
709
710 def test_nested_class_definition_indented_string(self):
711 self.assertSourceEqual(mod2.cls173.cls175, 175, 176)
712
713 def test_nested_class_definition(self):
714 self.assertSourceEqual(mod2.cls183, 183, 188)
715 self.assertSourceEqual(mod2.cls183.cls185, 185, 188)
716
717 def test_class_decorator(self):
718 self.assertSourceEqual(mod2.cls196, 194, 201)
719 self.assertSourceEqual(mod2.cls196.cls200, 198, 201)
720
721 def test_class_inside_conditional(self):
722 self.assertSourceEqual(mod2.cls238, 238, 240)
723 self.assertSourceEqual(mod2.cls238.cls239, 239, 240)
724
725 def test_multiple_children_classes(self):
726 self.assertSourceEqual(mod2.cls203, 203, 209)
727 self.assertSourceEqual(mod2.cls203.cls204, 204, 206)
728 self.assertSourceEqual(mod2.cls203.cls204.cls205, 205, 206)
729 self.assertSourceEqual(mod2.cls203.cls207, 207, 209)
730 self.assertSourceEqual(mod2.cls203.cls207.cls205, 208, 209)
731
732 def test_nested_class_definition_inside_function(self):
733 self.assertSourceEqual(mod2.func212(), 213, 214)
734 self.assertSourceEqual(mod2.cls213, 218, 222)
735 self.assertSourceEqual(mod2.cls213().func219(), 220, 221)
736
737 def test_nested_class_definition_inside_async_function(self):
738 import asyncio
739 self.addCleanup(asyncio.set_event_loop_policy, None)
740 self.assertSourceEqual(asyncio.run(mod2.func225()), 226, 227)
741 self.assertSourceEqual(mod2.cls226, 231, 235)
742 self.assertSourceEqual(asyncio.run(mod2.cls226().func232()), 233, 234)
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300743
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000744class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400745 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000746 self.tempdir = TESTFN + '_dir'
747 os.mkdir(self.tempdir)
748 with open(os.path.join(self.tempdir,
749 'inspect_fodder3%spy' % os.extsep), 'w') as f:
750 f.write("class X:\n pass # No EOL")
751 with DirsOnSysPath(self.tempdir):
752 import inspect_fodder3 as mod3
753 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400754 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000755
756 def tearDown(self):
757 shutil.rmtree(self.tempdir)
758
759 def test_class(self):
760 self.assertSourceEqual(self.fodderModule.X, 1, 2)
761
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100762
763class _BrokenDataDescriptor(object):
764 """
765 A broken data descriptor. See bug #1785.
766 """
767 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700768 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100769
770 def __set__(*args):
771 raise RuntimeError
772
773 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700774 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100775
776
777class _BrokenMethodDescriptor(object):
778 """
779 A broken method descriptor. See bug #1785.
780 """
781 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700782 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100783
784 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700785 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100786
787
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000788# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000789def attrs_wo_objs(cls):
790 return [t[:3] for t in inspect.classify_class_attrs(cls)]
791
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100792
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000793class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000794 def test_newstyle_mro(self):
795 # The same w/ new-class MRO.
796 class A(object): pass
797 class B(A): pass
798 class C(A): pass
799 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000800
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000801 expected = (D, B, C, A, object)
802 got = inspect.getmro(D)
803 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000804
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500805 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
806 varkw_e=None, defaults_e=None, formatted=None):
Xtreak6d0b7472019-05-30 17:31:39 +0530807 with self.assertWarns(DeprecationWarning):
808 args, varargs, varkw, defaults = inspect.getargspec(routine)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500809 self.assertEqual(args, args_e)
810 self.assertEqual(varargs, varargs_e)
811 self.assertEqual(varkw, varkw_e)
812 self.assertEqual(defaults, defaults_e)
813 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530814 with self.assertWarns(DeprecationWarning):
815 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
816 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500817
Christian Heimes3795b532007-11-08 13:48:53 +0000818 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
819 varkw_e=None, defaults_e=None,
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100820 posonlyargs_e=[], kwonlyargs_e=[],
821 kwonlydefaults_e=None,
Christian Heimes3795b532007-11-08 13:48:53 +0000822 ann_e={}, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100823 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
824 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000825 self.assertEqual(args, args_e)
826 self.assertEqual(varargs, varargs_e)
827 self.assertEqual(varkw, varkw_e)
828 self.assertEqual(defaults, defaults_e)
829 self.assertEqual(kwonlyargs, kwonlyargs_e)
830 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
831 self.assertEqual(ann, ann_e)
832 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530833 with self.assertWarns(DeprecationWarning):
834 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
835 kwonlyargs, kwonlydefaults, ann),
836 formatted)
Christian Heimes3795b532007-11-08 13:48:53 +0000837
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500838 def test_getargspec(self):
839 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
840
Pablo Galindod5d2b452019-04-30 02:01:14 +0100841 self.assertArgSpecEquals(mod.spam,
842 ['a', 'b', 'c', 'd', 'e', 'f'],
843 'g', 'h', (3, 4, 5),
844 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500845
846 self.assertRaises(ValueError, self.assertArgSpecEquals,
847 mod2.keyworded, [])
848
849 self.assertRaises(ValueError, self.assertArgSpecEquals,
850 mod2.annotated, [])
851 self.assertRaises(ValueError, self.assertArgSpecEquals,
852 mod2.keyword_only_arg, [])
853
854
Christian Heimes3795b532007-11-08 13:48:53 +0000855 def test_getfullargspec(self):
856 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
857 kwonlyargs_e=['arg2'],
858 kwonlydefaults_e={'arg2':1},
859 formatted='(*arg1, arg2=1)')
860
861 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000862 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000863 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000864 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
865 kwonlyargs_e=['arg'],
866 formatted='(*, arg)')
867
Pablo Galindod5d2b452019-04-30 02:01:14 +0100868 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100869 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100870 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100871
872 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100873 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100874 varargs_e='args',
875 varkw_e='kwargs',
876 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100877 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100878
Pablo Galindod5d2b452019-04-30 02:01:14 +0100879 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100880 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100881 kwonlyargs_e=['e', 'f'],
882 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100883 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100884
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500885 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500886 # Issue 20684: low level introspection API must ignore __wrapped__
887 @functools.wraps(mod.spam)
888 def ham(x, y):
889 pass
890 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500891 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500892 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
893 self.assertFullArgSpecEquals(functools.partial(ham),
894 ['x', 'y'], formatted='(x, y)')
895 # Other variants
896 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500897 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
898 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500899 class C:
900 @functools.wraps(mod.spam)
901 def ham(self, x, y):
902 pass
903 pham = functools.partialmethod(ham)
904 @functools.wraps(mod.spam)
905 def __call__(self, x, y):
906 pass
907 check_method(C())
908 check_method(C.ham)
909 check_method(C().ham)
910 check_method(C.pham)
911 check_method(C().pham)
912
913 class C_new:
914 @functools.wraps(mod.spam)
915 def __new__(self, x, y):
916 pass
917 check_method(C_new)
918
919 class C_init:
920 @functools.wraps(mod.spam)
921 def __init__(self, x, y):
922 pass
923 check_method(C_init)
924
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500925 def test_getfullargspec_signature_attr(self):
926 def test():
927 pass
928 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
929 test.__signature__ = inspect.Signature(parameters=(spam_param,))
930
Pablo Galindod5d2b452019-04-30 02:01:14 +0100931 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500932
Yury Selivanov4cb93912014-01-29 11:54:12 -0500933 def test_getfullargspec_signature_annos(self):
934 def test(a:'spam') -> 'ham': pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100935 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500936 self.assertEqual(test.__annotations__, spec.annotations)
937
938 def test(): pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100939 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500940 self.assertEqual(test.__annotations__, spec.annotations)
941
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500942 @unittest.skipIf(MISSING_C_DOCSTRINGS,
943 "Signature information for builtins requires docstrings")
944 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100945 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
946 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500947
Pablo Galindod5d2b452019-04-30 02:01:14 +0100948 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
949 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500950
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500951 self.assertFullArgSpecEquals(
952 os.stat,
953 args_e=['path'],
954 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
955 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
956 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
957
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200958 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500959 @unittest.skipIf(MISSING_C_DOCSTRINGS,
960 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800961 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200962 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500963 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindoaee19f52019-05-16 21:08:15 +0100964 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500965 self.assertEqual(spec.defaults[0], 'avocado')
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_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200971 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500972 builtin = _testcapi.docstring_no_signature
Pablo Galindoaee19f52019-05-16 21:08:15 +0100973 with self.assertRaises(TypeError):
974 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000975
larryhastingsf36ba122018-01-28 11:13:09 -0800976 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
977 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindoaee19f52019-05-16 21:08:15 +0100978 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800979 l = list(signature.kwonlyargs)
980 sorted_l = sorted(l)
981 self.assertTrue(l)
982 self.assertEqual(l, sorted_l)
Pablo Galindoaee19f52019-05-16 21:08:15 +0100983 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800984 l = list(signature.kwonlyargs)
985 self.assertEqual(l, unsorted_keyword_only_parameters)
986
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500987 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000988 class A(object):
989 def m(self):
990 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500991 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000992
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000993 def test_classify_newstyle(self):
994 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000995
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000996 def s(): pass
997 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000998
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000999 def c(cls): pass
1000 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +00001001
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001002 def getp(self): pass
1003 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +00001004
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001005 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001006
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001007 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001008
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001009 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +00001010
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001011 dd = _BrokenDataDescriptor()
1012 md = _BrokenMethodDescriptor()
1013
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001014 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001015
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001016 self.assertIn(('__new__', 'static method', object), attrs,
1017 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -05001018 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
1019
Benjamin Peterson577473f2010-01-19 00:09:57 +00001020 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1021 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1022 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001023 self.assertIn(('m', 'method', A), attrs,
1024 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001025 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1026 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001027 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1028 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001029
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001030 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001031
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001032 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001033
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001034 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001035 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1036 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1037 self.assertIn(('p', 'property', A), attrs, 'missing property')
1038 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1039 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1040 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001041 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1042 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001043
1044
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001045 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001046
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001047 def m(self): pass
1048 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001049
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001050 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001051 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1052 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1053 self.assertIn(('p', 'property', A), attrs, 'missing property')
1054 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
1055 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1056 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001057 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1058 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001059
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001060 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001061
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001062 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001063
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001064 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001065 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1066 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1067 self.assertIn(('p', 'property', A), attrs, 'missing property')
1068 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1069 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1070 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001071 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1072 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1073
1074 def test_classify_builtin_types(self):
1075 # Simple sanity check that all built-in types can have their
1076 # attributes classified.
1077 for name in dir(__builtins__):
1078 builtin = getattr(__builtins__, name)
1079 if isinstance(builtin, type):
1080 inspect.classify_class_attrs(builtin)
1081
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001082 attrs = attrs_wo_objs(bool)
1083 self.assertIn(('__new__', 'static method', bool), attrs,
1084 'missing __new__')
1085 self.assertIn(('from_bytes', 'class method', int), attrs,
1086 'missing class method')
1087 self.assertIn(('to_bytes', 'method', int), attrs,
1088 'missing plain method')
1089 self.assertIn(('__add__', 'method', int), attrs,
1090 'missing plain method')
1091 self.assertIn(('__and__', 'method', bool), attrs,
1092 'missing plain method')
1093
Ethan Furman63c141c2013-10-18 00:27:39 -07001094 def test_classify_DynamicClassAttribute(self):
1095 class Meta(type):
1096 def __getattr__(self, name):
1097 if name == 'ham':
1098 return 'spam'
1099 return super().__getattr__(name)
1100 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001101 @types.DynamicClassAttribute
1102 def ham(self):
1103 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001104 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1105 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001106 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001107 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1108
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001109 def test_classify_overrides_bool(self):
1110 class NoBool(object):
1111 def __eq__(self, other):
1112 return NoBool()
1113
1114 def __bool__(self):
1115 raise NotImplementedError(
1116 "This object does not specify a boolean value")
1117
1118 class HasNB(object):
1119 dd = NoBool()
1120
1121 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1122 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1123
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001124 def test_classify_metaclass_class_attribute(self):
1125 class Meta(type):
1126 fish = 'slap'
1127 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001128 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001129 class Class(metaclass=Meta):
1130 pass
1131 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1132 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1133
Ethan Furman63c141c2013-10-18 00:27:39 -07001134 def test_classify_VirtualAttribute(self):
1135 class Meta(type):
1136 def __dir__(cls):
1137 return ['__class__', '__module__', '__name__', 'BOOM']
1138 def __getattr__(self, name):
1139 if name =='BOOM':
1140 return 42
1141 return super().__getattr(name)
1142 class Class(metaclass=Meta):
1143 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001144 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001145 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1146
1147 def test_classify_VirtualAttribute_multi_classes(self):
1148 class Meta1(type):
1149 def __dir__(cls):
1150 return ['__class__', '__module__', '__name__', 'one']
1151 def __getattr__(self, name):
1152 if name =='one':
1153 return 1
1154 return super().__getattr__(name)
1155 class Meta2(type):
1156 def __dir__(cls):
1157 return ['__class__', '__module__', '__name__', 'two']
1158 def __getattr__(self, name):
1159 if name =='two':
1160 return 2
1161 return super().__getattr__(name)
1162 class Meta3(Meta1, Meta2):
1163 def __dir__(cls):
1164 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1165 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1166 def __getattr__(self, name):
1167 if name =='three':
1168 return 3
1169 return super().__getattr__(name)
1170 class Class1(metaclass=Meta1):
1171 pass
1172 class Class2(Class1, metaclass=Meta3):
1173 pass
1174
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001175 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1176 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1177 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001178 cca = inspect.classify_class_attrs(Class2)
1179 for sf in (should_find1, should_find2, should_find3):
1180 self.assertIn(sf, cca)
1181
1182 def test_classify_class_attrs_with_buggy_dir(self):
1183 class M(type):
1184 def __dir__(cls):
1185 return ['__class__', '__name__', 'missing']
1186 class C(metaclass=M):
1187 pass
1188 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1189 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001190
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001191 def test_getmembers_descriptors(self):
1192 class A(object):
1193 dd = _BrokenDataDescriptor()
1194 md = _BrokenMethodDescriptor()
1195
1196 def pred_wrapper(pred):
1197 # A quick'n'dirty way to discard standard attributes of new-style
1198 # classes.
1199 class Empty(object):
1200 pass
1201 def wrapped(x):
1202 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1203 return False
1204 return pred(x)
1205 return wrapped
1206
1207 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1208 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1209
1210 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1211 [('md', A.__dict__['md'])])
1212 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1213 [('dd', A.__dict__['dd'])])
1214
1215 class B(A):
1216 pass
1217
1218 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1219 [('md', A.__dict__['md'])])
1220 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1221 [('dd', A.__dict__['dd'])])
1222
Antoine Pitrou0c603812012-01-18 17:40:18 +01001223 def test_getmembers_method(self):
1224 class B:
1225 def f(self):
1226 pass
1227
1228 self.assertIn(('f', B.f), inspect.getmembers(B))
1229 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1230 b = B()
1231 self.assertIn(('f', b.f), inspect.getmembers(b))
1232 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1233
Ethan Furmane03ea372013-09-25 07:14:41 -07001234 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001235 class M(type):
1236 def __getattr__(cls, name):
1237 if name == 'eggs':
1238 return 'scrambled'
1239 return super().__getattr__(name)
1240 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001241 @types.DynamicClassAttribute
1242 def eggs(self):
1243 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001244 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1245 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1246
1247 def test_getmembers_with_buggy_dir(self):
1248 class M(type):
1249 def __dir__(cls):
1250 return ['__class__', '__name__', 'missing']
1251 class C(metaclass=M):
1252 pass
1253 attrs = [a[0] for a in inspect.getmembers(C)]
1254 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001255
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001256class TestIsDataDescriptor(unittest.TestCase):
1257
1258 def test_custom_descriptors(self):
1259 class NonDataDescriptor:
1260 def __get__(self, value, type=None): pass
1261 class DataDescriptor0:
1262 def __set__(self, name, value): pass
1263 class DataDescriptor1:
1264 def __delete__(self, name): pass
1265 class DataDescriptor2:
1266 __set__ = None
1267 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1268 'class with only __get__ not a data descriptor')
1269 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1270 'class with __set__ is a data descriptor')
1271 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1272 'class with __delete__ is a data descriptor')
1273 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1274 'class with __set__ = None is a data descriptor')
1275
1276 def test_slot(self):
1277 class Slotted:
1278 __slots__ = 'foo',
1279 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1280 'a slot is a data descriptor')
1281
1282 def test_property(self):
1283 class Propertied:
1284 @property
1285 def a_property(self):
1286 pass
1287 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1288 'a property is a data descriptor')
1289
1290 def test_functions(self):
1291 class Test(object):
1292 def instance_method(self): pass
1293 @classmethod
1294 def class_method(cls): pass
1295 @staticmethod
1296 def static_method(): pass
1297 def function():
1298 pass
1299 a_lambda = lambda: None
1300 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1301 'a instance method is not a data descriptor')
1302 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1303 'a class method is not a data descriptor')
1304 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1305 'a static method is not a data descriptor')
1306 self.assertFalse(inspect.isdatadescriptor(function),
1307 'a function is not a data descriptor')
1308 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1309 'a lambda is not a data descriptor')
1310
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001311
Nick Coghlan2f92e542012-06-23 19:39:55 +10001312_global_ref = object()
1313class TestGetClosureVars(unittest.TestCase):
1314
1315 def test_name_resolution(self):
1316 # Basic test of the 4 different resolution mechanisms
1317 def f(nonlocal_ref):
1318 def g(local_ref):
1319 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1320 return g
1321 _arg = object()
1322 nonlocal_vars = {"nonlocal_ref": _arg}
1323 global_vars = {"_global_ref": _global_ref}
1324 builtin_vars = {"print": print}
1325 unbound_names = {"unbound_ref"}
1326 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1327 builtin_vars, unbound_names)
1328 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1329
1330 def test_generator_closure(self):
1331 def f(nonlocal_ref):
1332 def g(local_ref):
1333 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1334 yield
1335 return g
1336 _arg = object()
1337 nonlocal_vars = {"nonlocal_ref": _arg}
1338 global_vars = {"_global_ref": _global_ref}
1339 builtin_vars = {"print": print}
1340 unbound_names = {"unbound_ref"}
1341 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1342 builtin_vars, unbound_names)
1343 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1344
1345 def test_method_closure(self):
1346 class C:
1347 def f(self, nonlocal_ref):
1348 def g(local_ref):
1349 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1350 return g
1351 _arg = object()
1352 nonlocal_vars = {"nonlocal_ref": _arg}
1353 global_vars = {"_global_ref": _global_ref}
1354 builtin_vars = {"print": print}
1355 unbound_names = {"unbound_ref"}
1356 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1357 builtin_vars, unbound_names)
1358 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1359
1360 def test_nonlocal_vars(self):
1361 # More complex tests of nonlocal resolution
1362 def _nonlocal_vars(f):
1363 return inspect.getclosurevars(f).nonlocals
1364
1365 def make_adder(x):
1366 def add(y):
1367 return x + y
1368 return add
1369
1370 def curry(func, arg1):
1371 return lambda arg2: func(arg1, arg2)
1372
1373 def less_than(a, b):
1374 return a < b
1375
1376 # The infamous Y combinator.
1377 def Y(le):
1378 def g(f):
1379 return le(lambda x: f(f)(x))
1380 Y.g_ref = g
1381 return g(g)
1382
1383 def check_y_combinator(func):
1384 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1385
1386 inc = make_adder(1)
1387 add_two = make_adder(2)
1388 greater_than_five = curry(less_than, 5)
1389
1390 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1391 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1392 self.assertEqual(_nonlocal_vars(greater_than_five),
1393 {'arg1': 5, 'func': less_than})
1394 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1395 {'x': 3})
1396 Y(check_y_combinator)
1397
1398 def test_getclosurevars_empty(self):
1399 def foo(): pass
1400 _empty = inspect.ClosureVars({}, {}, {}, set())
1401 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1402 self.assertEqual(inspect.getclosurevars(foo), _empty)
1403
1404 def test_getclosurevars_error(self):
1405 class T: pass
1406 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1407 self.assertRaises(TypeError, inspect.getclosurevars, list)
1408 self.assertRaises(TypeError, inspect.getclosurevars, {})
1409
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001410 def _private_globals(self):
1411 code = """def f(): print(path)"""
1412 ns = {}
1413 exec(code, ns)
1414 return ns["f"], ns
1415
1416 def test_builtins_fallback(self):
1417 f, ns = self._private_globals()
1418 ns.pop("__builtins__", None)
1419 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1420 self.assertEqual(inspect.getclosurevars(f), expected)
1421
1422 def test_builtins_as_dict(self):
1423 f, ns = self._private_globals()
1424 ns["__builtins__"] = {"path":1}
1425 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1426 self.assertEqual(inspect.getclosurevars(f), expected)
1427
1428 def test_builtins_as_module(self):
1429 f, ns = self._private_globals()
1430 ns["__builtins__"] = os
1431 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1432 self.assertEqual(inspect.getclosurevars(f), expected)
1433
Nick Coghlan2f92e542012-06-23 19:39:55 +10001434
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001435class TestGetcallargsFunctions(unittest.TestCase):
1436
1437 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1438 locs = dict(locs or {}, func=func)
1439 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001440 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1441 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001442 self.assertEqual(r1, r2)
1443
1444 def assertEqualException(self, func, call_param_string, locs=None):
1445 locs = dict(locs or {}, func=func)
1446 try:
1447 eval('func(%s)' % call_param_string, None, locs)
1448 except Exception as e:
1449 ex1 = e
1450 else:
1451 self.fail('Exception not raised')
1452 try:
Pablo Galindoaee19f52019-05-16 21:08:15 +01001453 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1454 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001455 except Exception as e:
1456 ex2 = e
1457 else:
1458 self.fail('Exception not raised')
1459 self.assertIs(type(ex1), type(ex2))
1460 self.assertEqual(str(ex1), str(ex2))
1461 del ex1, ex2
1462
1463 def makeCallable(self, signature):
1464 """Create a function that returns its locals()"""
1465 code = "lambda %s: locals()"
1466 return eval(code % signature)
1467
1468 def test_plain(self):
1469 f = self.makeCallable('a, b=1')
1470 self.assertEqualCallArgs(f, '2')
1471 self.assertEqualCallArgs(f, '2, 3')
1472 self.assertEqualCallArgs(f, 'a=2')
1473 self.assertEqualCallArgs(f, 'b=3, a=2')
1474 self.assertEqualCallArgs(f, '2, b=3')
1475 # expand *iterable / **mapping
1476 self.assertEqualCallArgs(f, '*(2,)')
1477 self.assertEqualCallArgs(f, '*[2]')
1478 self.assertEqualCallArgs(f, '*(2, 3)')
1479 self.assertEqualCallArgs(f, '*[2, 3]')
1480 self.assertEqualCallArgs(f, '**{"a":2}')
1481 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1482 self.assertEqualCallArgs(f, '2, **{"b":3}')
1483 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1484 # expand UserList / UserDict
1485 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1486 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1487 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1488 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1489 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1490
1491 def test_varargs(self):
1492 f = self.makeCallable('a, b=1, *c')
1493 self.assertEqualCallArgs(f, '2')
1494 self.assertEqualCallArgs(f, '2, 3')
1495 self.assertEqualCallArgs(f, '2, 3, 4')
1496 self.assertEqualCallArgs(f, '*(2,3,4)')
1497 self.assertEqualCallArgs(f, '2, *[3,4]')
1498 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1499
1500 def test_varkw(self):
1501 f = self.makeCallable('a, b=1, **c')
1502 self.assertEqualCallArgs(f, 'a=2')
1503 self.assertEqualCallArgs(f, '2, b=3, c=4')
1504 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1505 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1506 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1507 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1508 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1509 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1510 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1511
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001512 def test_varkw_only(self):
1513 # issue11256:
1514 f = self.makeCallable('**c')
1515 self.assertEqualCallArgs(f, '')
1516 self.assertEqualCallArgs(f, 'a=1')
1517 self.assertEqualCallArgs(f, 'a=1, b=2')
1518 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1519 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1520 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1521
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001522 def test_keyword_only(self):
1523 f = self.makeCallable('a=3, *, c, d=2')
1524 self.assertEqualCallArgs(f, 'c=3')
1525 self.assertEqualCallArgs(f, 'c=3, a=3')
1526 self.assertEqualCallArgs(f, 'a=2, c=4')
1527 self.assertEqualCallArgs(f, '4, c=4')
1528 self.assertEqualException(f, '')
1529 self.assertEqualException(f, '3')
1530 self.assertEqualException(f, 'a=3')
1531 self.assertEqualException(f, 'd=4')
1532
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001533 f = self.makeCallable('*, c, d=2')
1534 self.assertEqualCallArgs(f, 'c=3')
1535 self.assertEqualCallArgs(f, 'c=3, d=4')
1536 self.assertEqualCallArgs(f, 'd=4, c=3')
1537
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001538 def test_multiple_features(self):
1539 f = self.makeCallable('a, b=2, *f, **g')
1540 self.assertEqualCallArgs(f, '2, 3, 7')
1541 self.assertEqualCallArgs(f, '2, 3, x=8')
1542 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1543 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1544 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1545 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1546 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1547 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1548 '(4,[5,6])]), **collections.UserDict('
1549 'y=9, z=10)')
1550
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001551 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1552 self.assertEqualCallArgs(f, '2, 3, x=8')
1553 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1554 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1555 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1556 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1557 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1558 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1559 '(4,[5,6])]), q=0, **collections.UserDict('
1560 'y=9, z=10)')
1561
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001562 def test_errors(self):
1563 f0 = self.makeCallable('')
1564 f1 = self.makeCallable('a, b')
1565 f2 = self.makeCallable('a, b=1')
1566 # f0 takes no arguments
1567 self.assertEqualException(f0, '1')
1568 self.assertEqualException(f0, 'x=1')
1569 self.assertEqualException(f0, '1,x=1')
1570 # f1 takes exactly 2 arguments
1571 self.assertEqualException(f1, '')
1572 self.assertEqualException(f1, '1')
1573 self.assertEqualException(f1, 'a=2')
1574 self.assertEqualException(f1, 'b=3')
1575 # f2 takes at least 1 argument
1576 self.assertEqualException(f2, '')
1577 self.assertEqualException(f2, 'b=3')
1578 for f in f1, f2:
1579 # f1/f2 takes exactly/at most 2 arguments
1580 self.assertEqualException(f, '2, 3, 4')
1581 self.assertEqualException(f, '1, 2, 3, a=1')
1582 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001583 # XXX: success of this one depends on dict order
1584 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001585 # f got an unexpected keyword argument
1586 self.assertEqualException(f, 'c=2')
1587 self.assertEqualException(f, '2, c=3')
1588 self.assertEqualException(f, '2, 3, c=4')
1589 self.assertEqualException(f, '2, c=4, b=3')
1590 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1591 # f got multiple values for keyword argument
1592 self.assertEqualException(f, '1, a=2')
1593 self.assertEqualException(f, '1, **{"a":2}')
1594 self.assertEqualException(f, '1, 2, b=3')
1595 # XXX: Python inconsistency
1596 # - for functions and bound methods: unexpected keyword 'c'
1597 # - for unbound methods: multiple values for keyword 'a'
1598 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001599 # issue11256:
1600 f3 = self.makeCallable('**c')
1601 self.assertEqualException(f3, '1, 2')
1602 self.assertEqualException(f3, '1, 2, a=1, b=2')
1603 f4 = self.makeCallable('*, a, b=0')
1604 self.assertEqualException(f3, '1, 2')
1605 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001606
Yury Selivanov875df202014-03-27 18:23:03 -04001607 # issue #20816: getcallargs() fails to iterate over non-existent
1608 # kwonlydefaults and raises a wrong TypeError
1609 def f5(*, a): pass
1610 with self.assertRaisesRegex(TypeError,
1611 'missing 1 required keyword-only'):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001612 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001613
1614
Yury Selivanovdccfa132014-03-27 18:42:52 -04001615 # issue20817:
1616 def f6(a, b, c):
1617 pass
1618 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001619 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001620
Dong-hee Naa9cab432018-05-30 00:04:08 +09001621 # bpo-33197
1622 with self.assertRaisesRegex(ValueError,
1623 'variadic keyword parameters cannot'
1624 ' have default values'):
1625 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1626 default=42)
1627 with self.assertRaisesRegex(ValueError,
1628 "value 5 is not a valid Parameter.kind"):
1629 inspect.Parameter("bar", kind=5, default=42)
1630
1631 with self.assertRaisesRegex(TypeError,
1632 'name must be a str, not a int'):
1633 inspect.Parameter(123, kind=4)
1634
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001635class TestGetcallargsMethods(TestGetcallargsFunctions):
1636
1637 def setUp(self):
1638 class Foo(object):
1639 pass
1640 self.cls = Foo
1641 self.inst = Foo()
1642
1643 def makeCallable(self, signature):
1644 assert 'self' not in signature
1645 mk = super(TestGetcallargsMethods, self).makeCallable
1646 self.cls.method = mk('self, ' + signature)
1647 return self.inst.method
1648
1649class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1650
1651 def makeCallable(self, signature):
1652 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1653 return self.cls.method
1654
1655 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1656 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1657 *self._getAssertEqualParams(func, call_params_string, locs))
1658
1659 def assertEqualException(self, func, call_params_string, locs=None):
1660 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1661 *self._getAssertEqualParams(func, call_params_string, locs))
1662
1663 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1664 assert 'inst' not in call_params_string
1665 locs = dict(locs or {}, inst=self.inst)
1666 return (func, 'inst,' + call_params_string, locs)
1667
Michael Foord95fc51d2010-11-20 15:07:30 +00001668
1669class TestGetattrStatic(unittest.TestCase):
1670
1671 def test_basic(self):
1672 class Thing(object):
1673 x = object()
1674
1675 thing = Thing()
1676 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1677 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1678 with self.assertRaises(AttributeError):
1679 inspect.getattr_static(thing, 'y')
1680
1681 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1682
1683 def test_inherited(self):
1684 class Thing(object):
1685 x = object()
1686 class OtherThing(Thing):
1687 pass
1688
1689 something = OtherThing()
1690 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1691
1692 def test_instance_attr(self):
1693 class Thing(object):
1694 x = 2
1695 def __init__(self, x):
1696 self.x = x
1697 thing = Thing(3)
1698 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1699 del thing.x
1700 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1701
1702 def test_property(self):
1703 class Thing(object):
1704 @property
1705 def x(self):
1706 raise AttributeError("I'm pretending not to exist")
1707 thing = Thing()
1708 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1709
Ezio Melotti75cbd732011-04-28 00:59:29 +03001710 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001711 class descriptor(object):
1712 def __get__(*_):
1713 raise AttributeError("I'm pretending not to exist")
1714 desc = descriptor()
1715 class Thing(object):
1716 x = desc
1717 thing = Thing()
1718 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1719
1720 def test_classAttribute(self):
1721 class Thing(object):
1722 x = object()
1723
1724 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1725
Ethan Furmane03ea372013-09-25 07:14:41 -07001726 def test_classVirtualAttribute(self):
1727 class Thing(object):
1728 @types.DynamicClassAttribute
1729 def x(self):
1730 return self._x
1731 _x = object()
1732
1733 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1734
Michael Foord95fc51d2010-11-20 15:07:30 +00001735 def test_inherited_classattribute(self):
1736 class Thing(object):
1737 x = object()
1738 class OtherThing(Thing):
1739 pass
1740
1741 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1742
1743 def test_slots(self):
1744 class Thing(object):
1745 y = 'bar'
1746 __slots__ = ['x']
1747 def __init__(self):
1748 self.x = 'foo'
1749 thing = Thing()
1750 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1751 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1752
1753 del thing.x
1754 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1755
1756 def test_metaclass(self):
1757 class meta(type):
1758 attr = 'foo'
1759 class Thing(object, metaclass=meta):
1760 pass
1761 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1762
1763 class sub(meta):
1764 pass
1765 class OtherThing(object, metaclass=sub):
1766 x = 3
1767 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1768
1769 class OtherOtherThing(OtherThing):
1770 pass
1771 # this test is odd, but it was added as it exposed a bug
1772 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1773
1774 def test_no_dict_no_slots(self):
1775 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1776 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1777
1778 def test_no_dict_no_slots_instance_member(self):
1779 # returns descriptor
1780 with open(__file__) as handle:
1781 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1782
1783 def test_inherited_slots(self):
1784 # returns descriptor
1785 class Thing(object):
1786 __slots__ = ['x']
1787 def __init__(self):
1788 self.x = 'foo'
1789
1790 class OtherThing(Thing):
1791 pass
1792 # it would be nice if this worked...
1793 # we get the descriptor instead of the instance attribute
1794 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1795
1796 def test_descriptor(self):
1797 class descriptor(object):
1798 def __get__(self, instance, owner):
1799 return 3
1800 class Foo(object):
1801 d = descriptor()
1802
1803 foo = Foo()
1804
1805 # for a non data descriptor we return the instance attribute
1806 foo.__dict__['d'] = 1
1807 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1808
Mike53f7a7c2017-12-14 14:04:53 +03001809 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001810 # descriptor
1811 descriptor.__set__ = lambda s, i, v: None
1812 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1813
1814
1815 def test_metaclass_with_descriptor(self):
1816 class descriptor(object):
1817 def __get__(self, instance, owner):
1818 return 3
1819 class meta(type):
1820 d = descriptor()
1821 class Thing(object, metaclass=meta):
1822 pass
1823 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1824
1825
Michael Foordcc7ebb82010-11-20 16:20:16 +00001826 def test_class_as_property(self):
1827 class Base(object):
1828 foo = 3
1829
1830 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001831 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001832 @property
1833 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001834 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001835 return object
1836
Michael Foord35184ed2010-11-20 16:58:30 +00001837 instance = Something()
1838 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1839 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001840 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1841
Michael Foorde5162652010-11-20 16:40:44 +00001842 def test_mro_as_property(self):
1843 class Meta(type):
1844 @property
1845 def __mro__(self):
1846 return (object,)
1847
1848 class Base(object):
1849 foo = 3
1850
1851 class Something(Base, metaclass=Meta):
1852 pass
1853
1854 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1855 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1856
Michael Foorddcebe0f2011-03-15 19:20:44 -04001857 def test_dict_as_property(self):
1858 test = self
1859 test.called = False
1860
1861 class Foo(dict):
1862 a = 3
1863 @property
1864 def __dict__(self):
1865 test.called = True
1866 return {}
1867
1868 foo = Foo()
1869 foo.a = 4
1870 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1871 self.assertFalse(test.called)
1872
1873 def test_custom_object_dict(self):
1874 test = self
1875 test.called = False
1876
1877 class Custom(dict):
1878 def get(self, key, default=None):
1879 test.called = True
1880 super().get(key, default)
1881
1882 class Foo(object):
1883 a = 3
1884 foo = Foo()
1885 foo.__dict__ = Custom()
1886 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1887 self.assertFalse(test.called)
1888
1889 def test_metaclass_dict_as_property(self):
1890 class Meta(type):
1891 @property
1892 def __dict__(self):
1893 self.executed = True
1894
1895 class Thing(metaclass=Meta):
1896 executed = False
1897
1898 def __init__(self):
1899 self.spam = 42
1900
1901 instance = Thing()
1902 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1903 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001904
Michael Foorda51623b2011-12-18 22:01:40 +00001905 def test_module(self):
1906 sentinel = object()
1907 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1908 sentinel)
1909
Michael Foord3ba95f82011-12-22 01:13:37 +00001910 def test_metaclass_with_metaclass_with_dict_as_property(self):
1911 class MetaMeta(type):
1912 @property
1913 def __dict__(self):
1914 self.executed = True
1915 return dict(spam=42)
1916
1917 class Meta(type, metaclass=MetaMeta):
1918 executed = False
1919
1920 class Thing(metaclass=Meta):
1921 pass
1922
1923 with self.assertRaises(AttributeError):
1924 inspect.getattr_static(Thing, "spam")
1925 self.assertFalse(Thing.executed)
1926
Nick Coghlane0f04652010-11-21 03:44:04 +00001927class TestGetGeneratorState(unittest.TestCase):
1928
1929 def setUp(self):
1930 def number_generator():
1931 for number in range(5):
1932 yield number
1933 self.generator = number_generator()
1934
1935 def _generatorstate(self):
1936 return inspect.getgeneratorstate(self.generator)
1937
1938 def test_created(self):
1939 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1940
1941 def test_suspended(self):
1942 next(self.generator)
1943 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1944
1945 def test_closed_after_exhaustion(self):
1946 for i in self.generator:
1947 pass
1948 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1949
1950 def test_closed_after_immediate_exception(self):
1951 with self.assertRaises(RuntimeError):
1952 self.generator.throw(RuntimeError)
1953 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1954
1955 def test_running(self):
1956 # As mentioned on issue #10220, checking for the RUNNING state only
1957 # makes sense inside the generator itself.
1958 # The following generator checks for this by using the closure's
1959 # reference to self and the generator state checking helper method
1960 def running_check_generator():
1961 for number in range(5):
1962 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1963 yield number
1964 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1965 self.generator = running_check_generator()
1966 # Running up to the first yield
1967 next(self.generator)
1968 # Running after the first yield
1969 next(self.generator)
1970
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001971 def test_easy_debugging(self):
1972 # repr() and str() of a generator state should contain the state name
1973 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1974 for name in names:
1975 state = getattr(inspect, name)
1976 self.assertIn(name, repr(state))
1977 self.assertIn(name, str(state))
1978
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001979 def test_getgeneratorlocals(self):
1980 def each(lst, a=None):
1981 b=(1, 2, 3)
1982 for v in lst:
1983 if v == 3:
1984 c = 12
1985 yield v
1986
1987 numbers = each([1, 2, 3])
1988 self.assertEqual(inspect.getgeneratorlocals(numbers),
1989 {'a': None, 'lst': [1, 2, 3]})
1990 next(numbers)
1991 self.assertEqual(inspect.getgeneratorlocals(numbers),
1992 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1993 'b': (1, 2, 3)})
1994 next(numbers)
1995 self.assertEqual(inspect.getgeneratorlocals(numbers),
1996 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1997 'b': (1, 2, 3)})
1998 next(numbers)
1999 self.assertEqual(inspect.getgeneratorlocals(numbers),
2000 {'a': None, 'lst': [1, 2, 3], 'v': 3,
2001 'b': (1, 2, 3), 'c': 12})
2002 try:
2003 next(numbers)
2004 except StopIteration:
2005 pass
2006 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
2007
2008 def test_getgeneratorlocals_empty(self):
2009 def yield_one():
2010 yield 1
2011 one = yield_one()
2012 self.assertEqual(inspect.getgeneratorlocals(one), {})
2013 try:
2014 next(one)
2015 except StopIteration:
2016 pass
2017 self.assertEqual(inspect.getgeneratorlocals(one), {})
2018
2019 def test_getgeneratorlocals_error(self):
2020 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
2021 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
2022 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
2023 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
2024
Nick Coghlane0f04652010-11-21 03:44:04 +00002025
Yury Selivanov5376ba92015-06-22 12:19:30 -04002026class TestGetCoroutineState(unittest.TestCase):
2027
2028 def setUp(self):
2029 @types.coroutine
2030 def number_coroutine():
2031 for number in range(5):
2032 yield number
2033 async def coroutine():
2034 await number_coroutine()
2035 self.coroutine = coroutine()
2036
2037 def tearDown(self):
2038 self.coroutine.close()
2039
2040 def _coroutinestate(self):
2041 return inspect.getcoroutinestate(self.coroutine)
2042
2043 def test_created(self):
2044 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
2045
2046 def test_suspended(self):
2047 self.coroutine.send(None)
2048 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
2049
2050 def test_closed_after_exhaustion(self):
2051 while True:
2052 try:
2053 self.coroutine.send(None)
2054 except StopIteration:
2055 break
2056
2057 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2058
2059 def test_closed_after_immediate_exception(self):
2060 with self.assertRaises(RuntimeError):
2061 self.coroutine.throw(RuntimeError)
2062 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2063
2064 def test_easy_debugging(self):
2065 # repr() and str() of a coroutine state should contain the state name
2066 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2067 for name in names:
2068 state = getattr(inspect, name)
2069 self.assertIn(name, repr(state))
2070 self.assertIn(name, str(state))
2071
2072 def test_getcoroutinelocals(self):
2073 @types.coroutine
2074 def gencoro():
2075 yield
2076
2077 gencoro = gencoro()
2078 async def func(a=None):
2079 b = 'spam'
2080 await gencoro
2081
2082 coro = func()
2083 self.assertEqual(inspect.getcoroutinelocals(coro),
2084 {'a': None, 'gencoro': gencoro})
2085 coro.send(None)
2086 self.assertEqual(inspect.getcoroutinelocals(coro),
2087 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2088
2089
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002090class MySignature(inspect.Signature):
2091 # Top-level to make it picklable;
2092 # used in test_signature_object_pickle
2093 pass
2094
2095class MyParameter(inspect.Parameter):
2096 # Top-level to make it picklable;
2097 # used in test_signature_object_pickle
2098 pass
2099
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002100
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002101
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002102class TestSignatureObject(unittest.TestCase):
2103 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002104 def signature(func, **kw):
2105 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002106 return (tuple((param.name,
2107 (... if param.default is param.empty else param.default),
2108 (... if param.annotation is param.empty
2109 else param.annotation),
2110 str(param.kind).lower())
2111 for param in sig.parameters.values()),
2112 (... if sig.return_annotation is sig.empty
2113 else sig.return_annotation))
2114
2115 def test_signature_object(self):
2116 S = inspect.Signature
2117 P = inspect.Parameter
2118
2119 self.assertEqual(str(S()), '()')
Jens Reidel611836a2020-03-18 03:22:46 +01002120 self.assertEqual(repr(S().parameters), 'mappingproxy(OrderedDict())')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002121
Yury Selivanov07a9e452014-01-29 10:58:16 -05002122 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002123 pass
2124 sig = inspect.signature(test)
2125 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002126 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002127 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002128 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002129 args = sig.parameters['args']
2130 ko = sig.parameters['ko']
2131 kwargs = sig.parameters['kwargs']
2132
2133 S((po, pk, args, ko, kwargs))
2134
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002135 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002136 S((pk, po, args, ko, kwargs))
2137
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002138 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002139 S((po, args, pk, ko, kwargs))
2140
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002141 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002142 S((args, po, pk, 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((po, pk, args, kwargs, ko))
2146
2147 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002148 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002149 S((po, pk, args, kwargs2, ko))
2150
Yury Selivanov07a9e452014-01-29 10:58:16 -05002151 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2152 S((pod, po))
2153
2154 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2155 S((po, pkd, pk))
2156
2157 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2158 S((pkd, pk))
2159
Yury Selivanov374375d2014-03-27 12:41:53 -04002160 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002161 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002162
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002163 def test_signature_object_pickle(self):
2164 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2165 foo_partial = functools.partial(foo, a=1)
2166
2167 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002168
2169 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2170 with self.subTest(pickle_ver=ver, subclass=False):
2171 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2172 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002173
2174 # Test that basic sub-classing works
2175 sig = inspect.signature(foo)
2176 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2177 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2178 mysig = MySignature().replace(parameters=myparams.values(),
2179 return_annotation=sig.return_annotation)
2180 self.assertTrue(isinstance(mysig, MySignature))
2181 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2182
2183 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2184 with self.subTest(pickle_ver=ver, subclass=True):
2185 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2186 self.assertEqual(mysig, sig_pickled)
2187 self.assertTrue(isinstance(sig_pickled, MySignature))
2188 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2189 MyParameter))
2190
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002191 def test_signature_immutability(self):
2192 def test(a):
2193 pass
2194 sig = inspect.signature(test)
2195
2196 with self.assertRaises(AttributeError):
2197 sig.foo = 'bar'
2198
2199 with self.assertRaises(TypeError):
2200 sig.parameters['a'] = None
2201
2202 def test_signature_on_noarg(self):
2203 def test():
2204 pass
2205 self.assertEqual(self.signature(test), ((), ...))
2206
2207 def test_signature_on_wargs(self):
2208 def test(a, b:'foo') -> 123:
2209 pass
2210 self.assertEqual(self.signature(test),
2211 ((('a', ..., ..., "positional_or_keyword"),
2212 ('b', ..., 'foo', "positional_or_keyword")),
2213 123))
2214
2215 def test_signature_on_wkwonly(self):
2216 def test(*, a:float, b:str) -> int:
2217 pass
2218 self.assertEqual(self.signature(test),
2219 ((('a', ..., float, "keyword_only"),
2220 ('b', ..., str, "keyword_only")),
2221 int))
2222
2223 def test_signature_on_complex_args(self):
2224 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2225 pass
2226 self.assertEqual(self.signature(test),
2227 ((('a', ..., ..., "positional_or_keyword"),
2228 ('b', 10, 'foo', "positional_or_keyword"),
2229 ('args', ..., 'bar', "var_positional"),
2230 ('spam', ..., 'baz', "keyword_only"),
2231 ('ham', 123, ..., "keyword_only"),
2232 ('kwargs', ..., int, "var_keyword")),
2233 ...))
2234
Dong-hee Na378d7062017-05-18 04:00:51 +09002235 def test_signature_without_self(self):
2236 def test_args_only(*args): # NOQA
2237 pass
2238
2239 def test_args_kwargs_only(*args, **kwargs): # NOQA
2240 pass
2241
2242 class A:
2243 @classmethod
2244 def test_classmethod(*args): # NOQA
2245 pass
2246
2247 @staticmethod
2248 def test_staticmethod(*args): # NOQA
2249 pass
2250
2251 f1 = functools.partialmethod((test_classmethod), 1)
2252 f2 = functools.partialmethod((test_args_only), 1)
2253 f3 = functools.partialmethod((test_staticmethod), 1)
2254 f4 = functools.partialmethod((test_args_kwargs_only),1)
2255
2256 self.assertEqual(self.signature(test_args_only),
2257 ((('args', ..., ..., 'var_positional'),), ...))
2258 self.assertEqual(self.signature(test_args_kwargs_only),
2259 ((('args', ..., ..., 'var_positional'),
2260 ('kwargs', ..., ..., 'var_keyword')), ...))
2261 self.assertEqual(self.signature(A.f1),
2262 ((('args', ..., ..., 'var_positional'),), ...))
2263 self.assertEqual(self.signature(A.f2),
2264 ((('args', ..., ..., 'var_positional'),), ...))
2265 self.assertEqual(self.signature(A.f3),
2266 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002267 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002268 ((('args', ..., ..., 'var_positional'),
2269 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002270 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002271 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2272 "Signature information for builtins requires docstrings")
2273 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002274 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002275
Larry Hastings5c661892014-01-24 06:17:25 -08002276 def test_unbound_method(o):
2277 """Use this to test unbound methods (things that should have a self)"""
2278 signature = inspect.signature(o)
2279 self.assertTrue(isinstance(signature, inspect.Signature))
2280 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2281 return signature
2282
2283 def test_callable(o):
2284 """Use this to test bound methods or normal callables (things that don't expect self)"""
2285 signature = inspect.signature(o)
2286 self.assertTrue(isinstance(signature, inspect.Signature))
2287 if signature.parameters:
2288 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2289 return signature
2290
2291 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002292 def p(name): return signature.parameters[name].default
2293 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002294 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002295 self.assertEqual(p('d'), 3.14)
2296 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002297 self.assertEqual(p('n'), None)
2298 self.assertEqual(p('t'), True)
2299 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002300 self.assertEqual(p('local'), 3)
2301 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002302 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002303
Larry Hastings5c661892014-01-24 06:17:25 -08002304 test_callable(object)
2305
2306 # normal method
2307 # (PyMethodDescr_Type, "method_descriptor")
2308 test_unbound_method(_pickle.Pickler.dump)
2309 d = _pickle.Pickler(io.StringIO())
2310 test_callable(d.dump)
2311
2312 # static method
Serhiy Storchaka279f4462019-09-14 12:24:05 +03002313 test_callable(bytes.maketrans)
2314 test_callable(b'abc'.maketrans)
Larry Hastings5c661892014-01-24 06:17:25 -08002315
2316 # class method
2317 test_callable(dict.fromkeys)
2318 test_callable({}.fromkeys)
2319
2320 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2321 test_unbound_method(type.__call__)
2322 test_unbound_method(int.__add__)
2323 test_callable((3).__add__)
2324
2325 # _PyMethodWrapper_Type
2326 # support for 'method-wrapper'
2327 test_callable(min.__call__)
2328
Larry Hastings2623c8c2014-02-08 22:15:29 -08002329 # This doesn't work now.
2330 # (We don't have a valid signature for "type" in 3.4)
2331 with self.assertRaisesRegex(ValueError, "no signature found"):
2332 class ThisWorksNow:
2333 __call__ = type
2334 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002335
Yury Selivanov056e2652014-03-02 12:25:27 -05002336 # Regression test for issue #20786
2337 test_unbound_method(dict.__delitem__)
2338 test_unbound_method(property.__delete__)
2339
Zachary Ware8ef887c2015-04-13 18:22:35 -05002340 # Regression test for issue #20586
2341 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2342
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002343 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002344 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2345 "Signature information for builtins requires docstrings")
2346 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002347 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002348 func = _testcapi.docstring_with_signature_with_defaults
2349
2350 def decorator(func):
2351 @functools.wraps(func)
2352 def wrapper(*args, **kwargs) -> int:
2353 return func(*args, **kwargs)
2354 return wrapper
2355
2356 decorated_func = decorator(func)
2357
2358 self.assertEqual(inspect.signature(func),
2359 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002360
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002361 def wrapper_like(*args, **kwargs) -> int: pass
2362 self.assertEqual(inspect.signature(decorated_func,
2363 follow_wrapped=False),
2364 inspect.signature(wrapper_like))
2365
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002366 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002367 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002368 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002369 with self.assertRaisesRegex(ValueError,
2370 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002371 inspect.signature(_testcapi.docstring_no_signature)
2372
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002373 with self.assertRaisesRegex(ValueError,
2374 'no signature found for builtin'):
2375 inspect.signature(str)
2376
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002377 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002378 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002379 inspect.signature(42)
2380
Yury Selivanov63da7c72014-01-31 14:48:37 -05002381 def test_signature_from_functionlike_object(self):
2382 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2383 pass
2384
2385 class funclike:
2386 # Has to be callable, and have correct
2387 # __code__, __annotations__, __defaults__, __name__,
2388 # and __kwdefaults__ attributes
2389
2390 def __init__(self, func):
2391 self.__name__ = func.__name__
2392 self.__code__ = func.__code__
2393 self.__annotations__ = func.__annotations__
2394 self.__defaults__ = func.__defaults__
2395 self.__kwdefaults__ = func.__kwdefaults__
2396 self.func = func
2397
2398 def __call__(self, *args, **kwargs):
2399 return self.func(*args, **kwargs)
2400
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002401 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002402
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002403 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002404 self.assertEqual(sig_funclike, sig_func)
2405
2406 sig_funclike = inspect.signature(funclike(func))
2407 self.assertEqual(sig_funclike, sig_func)
2408
2409 # If object is not a duck type of function, then
2410 # signature will try to get a signature for its '__call__'
2411 # method
2412 fl = funclike(func)
2413 del fl.__defaults__
2414 self.assertEqual(self.signature(fl),
2415 ((('args', ..., ..., "var_positional"),
2416 ('kwargs', ..., ..., "var_keyword")),
2417 ...))
2418
Yury Selivanova773de02014-02-21 18:30:53 -05002419 # Test with cython-like builtins:
2420 _orig_isdesc = inspect.ismethoddescriptor
2421 def _isdesc(obj):
2422 if hasattr(obj, '_builtinmock'):
2423 return True
2424 return _orig_isdesc(obj)
2425
2426 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2427 builtin_func = funclike(func)
2428 # Make sure that our mock setup is working
2429 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2430 builtin_func._builtinmock = True
2431 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2432 self.assertEqual(inspect.signature(builtin_func), sig_func)
2433
Yury Selivanov63da7c72014-01-31 14:48:37 -05002434 def test_signature_functionlike_class(self):
2435 # We only want to duck type function-like objects,
2436 # not classes.
2437
2438 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2439 pass
2440
2441 class funclike:
2442 def __init__(self, marker):
2443 pass
2444
2445 __name__ = func.__name__
2446 __code__ = func.__code__
2447 __annotations__ = func.__annotations__
2448 __defaults__ = func.__defaults__
2449 __kwdefaults__ = func.__kwdefaults__
2450
Yury Selivanov63da7c72014-01-31 14:48:37 -05002451 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2452
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002453 def test_signature_on_method(self):
2454 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002455 def __init__(*args):
2456 pass
2457 def m1(self, arg1, arg2=1) -> int:
2458 pass
2459 def m2(*args):
2460 pass
2461 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002462 pass
2463
Yury Selivanov62560fb2014-01-28 12:26:24 -05002464 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002465 ((('arg1', ..., ..., "positional_or_keyword"),
2466 ('arg2', 1, ..., "positional_or_keyword")),
2467 int))
2468
Yury Selivanov62560fb2014-01-28 12:26:24 -05002469 self.assertEqual(self.signature(Test().m2),
2470 ((('args', ..., ..., "var_positional"),),
2471 ...))
2472
2473 self.assertEqual(self.signature(Test),
2474 ((('args', ..., ..., "var_positional"),),
2475 ...))
2476
2477 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2478 self.signature(Test())
2479
Yury Selivanov46c759d2015-05-27 21:56:53 -04002480 def test_signature_wrapped_bound_method(self):
2481 # Issue 24298
2482 class Test:
2483 def m1(self, arg1, arg2=1) -> int:
2484 pass
2485 @functools.wraps(Test().m1)
2486 def m1d(*args, **kwargs):
2487 pass
2488 self.assertEqual(self.signature(m1d),
2489 ((('arg1', ..., ..., "positional_or_keyword"),
2490 ('arg2', 1, ..., "positional_or_keyword")),
2491 int))
2492
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002493 def test_signature_on_classmethod(self):
2494 class Test:
2495 @classmethod
2496 def foo(cls, arg1, *, arg2=1):
2497 pass
2498
2499 meth = Test().foo
2500 self.assertEqual(self.signature(meth),
2501 ((('arg1', ..., ..., "positional_or_keyword"),
2502 ('arg2', 1, ..., "keyword_only")),
2503 ...))
2504
2505 meth = Test.foo
2506 self.assertEqual(self.signature(meth),
2507 ((('arg1', ..., ..., "positional_or_keyword"),
2508 ('arg2', 1, ..., "keyword_only")),
2509 ...))
2510
2511 def test_signature_on_staticmethod(self):
2512 class Test:
2513 @staticmethod
2514 def foo(cls, *, arg):
2515 pass
2516
2517 meth = Test().foo
2518 self.assertEqual(self.signature(meth),
2519 ((('cls', ..., ..., "positional_or_keyword"),
2520 ('arg', ..., ..., "keyword_only")),
2521 ...))
2522
2523 meth = Test.foo
2524 self.assertEqual(self.signature(meth),
2525 ((('cls', ..., ..., "positional_or_keyword"),
2526 ('arg', ..., ..., "keyword_only")),
2527 ...))
2528
2529 def test_signature_on_partial(self):
2530 from functools import partial
2531
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002532 Parameter = inspect.Parameter
2533
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002534 def test():
2535 pass
2536
2537 self.assertEqual(self.signature(partial(test)), ((), ...))
2538
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002539 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002540 inspect.signature(partial(test, 1))
2541
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002542 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002543 inspect.signature(partial(test, a=1))
2544
2545 def test(a, b, *, c, d):
2546 pass
2547
2548 self.assertEqual(self.signature(partial(test)),
2549 ((('a', ..., ..., "positional_or_keyword"),
2550 ('b', ..., ..., "positional_or_keyword"),
2551 ('c', ..., ..., "keyword_only"),
2552 ('d', ..., ..., "keyword_only")),
2553 ...))
2554
2555 self.assertEqual(self.signature(partial(test, 1)),
2556 ((('b', ..., ..., "positional_or_keyword"),
2557 ('c', ..., ..., "keyword_only"),
2558 ('d', ..., ..., "keyword_only")),
2559 ...))
2560
2561 self.assertEqual(self.signature(partial(test, 1, c=2)),
2562 ((('b', ..., ..., "positional_or_keyword"),
2563 ('c', 2, ..., "keyword_only"),
2564 ('d', ..., ..., "keyword_only")),
2565 ...))
2566
2567 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2568 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002569 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002570 ('c', 2, ..., "keyword_only"),
2571 ('d', ..., ..., "keyword_only")),
2572 ...))
2573
2574 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002575 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002576 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002577 ('d', ..., ..., "keyword_only")),
2578 ...))
2579
2580 self.assertEqual(self.signature(partial(test, a=1)),
2581 ((('a', 1, ..., "keyword_only"),
2582 ('b', ..., ..., "keyword_only"),
2583 ('c', ..., ..., "keyword_only"),
2584 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002585 ...))
2586
2587 def test(a, *args, b, **kwargs):
2588 pass
2589
2590 self.assertEqual(self.signature(partial(test, 1)),
2591 ((('args', ..., ..., "var_positional"),
2592 ('b', ..., ..., "keyword_only"),
2593 ('kwargs', ..., ..., "var_keyword")),
2594 ...))
2595
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002596 self.assertEqual(self.signature(partial(test, a=1)),
2597 ((('a', 1, ..., "keyword_only"),
2598 ('b', ..., ..., "keyword_only"),
2599 ('kwargs', ..., ..., "var_keyword")),
2600 ...))
2601
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002602 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2603 ((('args', ..., ..., "var_positional"),
2604 ('b', ..., ..., "keyword_only"),
2605 ('kwargs', ..., ..., "var_keyword")),
2606 ...))
2607
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002608 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2609 ((('args', ..., ..., "var_positional"),
2610 ('b', ..., ..., "keyword_only"),
2611 ('kwargs', ..., ..., "var_keyword")),
2612 ...))
2613
2614 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2615 ((('args', ..., ..., "var_positional"),
2616 ('b', 0, ..., "keyword_only"),
2617 ('kwargs', ..., ..., "var_keyword")),
2618 ...))
2619
2620 self.assertEqual(self.signature(partial(test, b=0)),
2621 ((('a', ..., ..., "positional_or_keyword"),
2622 ('args', ..., ..., "var_positional"),
2623 ('b', 0, ..., "keyword_only"),
2624 ('kwargs', ..., ..., "var_keyword")),
2625 ...))
2626
2627 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2628 ((('a', ..., ..., "positional_or_keyword"),
2629 ('args', ..., ..., "var_positional"),
2630 ('b', 0, ..., "keyword_only"),
2631 ('kwargs', ..., ..., "var_keyword")),
2632 ...))
2633
2634 def test(a, b, c:int) -> 42:
2635 pass
2636
2637 sig = test.__signature__ = inspect.signature(test)
2638
2639 self.assertEqual(self.signature(partial(partial(test, 1))),
2640 ((('b', ..., ..., "positional_or_keyword"),
2641 ('c', ..., int, "positional_or_keyword")),
2642 42))
2643
2644 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2645 ((('c', ..., int, "positional_or_keyword"),),
2646 42))
2647
2648 psig = inspect.signature(partial(partial(test, 1), 2))
2649
2650 def foo(a):
2651 return a
2652 _foo = partial(partial(foo, a=10), a=20)
2653 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002654 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002655 ...))
2656 # check that we don't have any side-effects in signature(),
2657 # and the partial object is still functioning
2658 self.assertEqual(_foo(), 20)
2659
2660 def foo(a, b, c):
2661 return a, b, c
2662 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002663
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002664 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002665 ((('b', 30, ..., "keyword_only"),
2666 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002667 ...))
2668 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002669
2670 def foo(a, b, c, *, d):
2671 return a, b, c, d
2672 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2673 self.assertEqual(self.signature(_foo),
2674 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002675 ('b', 10, ..., "keyword_only"),
2676 ('c', 20, ..., "keyword_only"),
2677 ('d', 30, ..., "keyword_only"),
2678 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002679 ...))
2680 ba = inspect.signature(_foo).bind(a=200, b=11)
2681 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2682
2683 def foo(a=1, b=2, c=3):
2684 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002685 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2686
2687 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002688 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002689
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002690 ba = inspect.signature(_foo).bind(11, 12)
2691 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002692
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002693 ba = inspect.signature(_foo).bind(11, b=12)
2694 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002695
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002696 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002697 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2698
2699 _foo = partial(_foo, b=10, c=20)
2700 ba = inspect.signature(_foo).bind(12)
2701 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2702
2703
2704 def foo(a, b, c, d, **kwargs):
2705 pass
2706 sig = inspect.signature(foo)
2707 params = sig.parameters.copy()
2708 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2709 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2710 foo.__signature__ = inspect.Signature(params.values())
2711 sig = inspect.signature(foo)
2712 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2713
2714 self.assertEqual(self.signature(partial(foo, 1)),
2715 ((('b', ..., ..., 'positional_only'),
2716 ('c', ..., ..., 'positional_or_keyword'),
2717 ('d', ..., ..., 'positional_or_keyword'),
2718 ('kwargs', ..., ..., 'var_keyword')),
2719 ...))
2720
2721 self.assertEqual(self.signature(partial(foo, 1, 2)),
2722 ((('c', ..., ..., 'positional_or_keyword'),
2723 ('d', ..., ..., 'positional_or_keyword'),
2724 ('kwargs', ..., ..., 'var_keyword')),
2725 ...))
2726
2727 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2728 ((('d', ..., ..., 'positional_or_keyword'),
2729 ('kwargs', ..., ..., 'var_keyword')),
2730 ...))
2731
2732 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2733 ((('c', 3, ..., 'keyword_only'),
2734 ('d', ..., ..., 'keyword_only'),
2735 ('kwargs', ..., ..., 'var_keyword')),
2736 ...))
2737
2738 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2739 ((('b', ..., ..., 'positional_only'),
2740 ('c', 3, ..., 'keyword_only'),
2741 ('d', ..., ..., 'keyword_only'),
2742 ('kwargs', ..., ..., 'var_keyword')),
2743 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002744
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002745 def test_signature_on_partialmethod(self):
2746 from functools import partialmethod
2747
2748 class Spam:
2749 def test():
2750 pass
2751 ham = partialmethod(test)
2752
2753 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2754 inspect.signature(Spam.ham)
2755
2756 class Spam:
2757 def test(it, a, *, c) -> 'spam':
2758 pass
2759 ham = partialmethod(test, c=1)
2760
2761 self.assertEqual(self.signature(Spam.ham),
2762 ((('it', ..., ..., 'positional_or_keyword'),
2763 ('a', ..., ..., 'positional_or_keyword'),
2764 ('c', 1, ..., 'keyword_only')),
2765 'spam'))
2766
2767 self.assertEqual(self.signature(Spam().ham),
2768 ((('a', ..., ..., 'positional_or_keyword'),
2769 ('c', 1, ..., 'keyword_only')),
2770 'spam'))
2771
Yury Selivanov8a387212018-03-06 12:59:45 -05002772 class Spam:
2773 def test(self: 'anno', x):
2774 pass
2775
2776 g = partialmethod(test, 1)
2777
2778 self.assertEqual(self.signature(Spam.g),
2779 ((('self', ..., 'anno', 'positional_or_keyword'),),
2780 ...))
2781
Yury Selivanov0486f812014-01-29 12:18:59 -05002782 def test_signature_on_fake_partialmethod(self):
2783 def foo(a): pass
2784 foo._partialmethod = 'spam'
2785 self.assertEqual(str(inspect.signature(foo)), '(a)')
2786
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002787 def test_signature_on_decorated(self):
2788 import functools
2789
2790 def decorator(func):
2791 @functools.wraps(func)
2792 def wrapper(*args, **kwargs) -> int:
2793 return func(*args, **kwargs)
2794 return wrapper
2795
2796 class Foo:
2797 @decorator
2798 def bar(self, a, b):
2799 pass
2800
2801 self.assertEqual(self.signature(Foo.bar),
2802 ((('self', ..., ..., "positional_or_keyword"),
2803 ('a', ..., ..., "positional_or_keyword"),
2804 ('b', ..., ..., "positional_or_keyword")),
2805 ...))
2806
2807 self.assertEqual(self.signature(Foo().bar),
2808 ((('a', ..., ..., "positional_or_keyword"),
2809 ('b', ..., ..., "positional_or_keyword")),
2810 ...))
2811
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002812 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2813 ((('args', ..., ..., "var_positional"),
2814 ('kwargs', ..., ..., "var_keyword")),
2815 ...)) # functools.wraps will copy __annotations__
2816 # from "func" to "wrapper", hence no
2817 # return_annotation
2818
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002819 # Test that we handle method wrappers correctly
2820 def decorator(func):
2821 @functools.wraps(func)
2822 def wrapper(*args, **kwargs) -> int:
2823 return func(42, *args, **kwargs)
2824 sig = inspect.signature(func)
2825 new_params = tuple(sig.parameters.values())[1:]
2826 wrapper.__signature__ = sig.replace(parameters=new_params)
2827 return wrapper
2828
2829 class Foo:
2830 @decorator
2831 def __call__(self, a, b):
2832 pass
2833
2834 self.assertEqual(self.signature(Foo.__call__),
2835 ((('a', ..., ..., "positional_or_keyword"),
2836 ('b', ..., ..., "positional_or_keyword")),
2837 ...))
2838
2839 self.assertEqual(self.signature(Foo().__call__),
2840 ((('b', ..., ..., "positional_or_keyword"),),
2841 ...))
2842
Nick Coghlane8c45d62013-07-28 20:00:01 +10002843 # Test we handle __signature__ partway down the wrapper stack
2844 def wrapped_foo_call():
2845 pass
2846 wrapped_foo_call.__wrapped__ = Foo.__call__
2847
2848 self.assertEqual(self.signature(wrapped_foo_call),
2849 ((('a', ..., ..., "positional_or_keyword"),
2850 ('b', ..., ..., "positional_or_keyword")),
2851 ...))
2852
2853
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002854 def test_signature_on_class(self):
2855 class C:
2856 def __init__(self, a):
2857 pass
2858
2859 self.assertEqual(self.signature(C),
2860 ((('a', ..., ..., "positional_or_keyword"),),
2861 ...))
2862
2863 class CM(type):
2864 def __call__(cls, a):
2865 pass
2866 class C(metaclass=CM):
2867 def __init__(self, b):
2868 pass
2869
2870 self.assertEqual(self.signature(C),
2871 ((('a', ..., ..., "positional_or_keyword"),),
2872 ...))
2873
2874 class CM(type):
2875 def __new__(mcls, name, bases, dct, *, foo=1):
2876 return super().__new__(mcls, name, bases, dct)
2877 class C(metaclass=CM):
2878 def __init__(self, b):
2879 pass
2880
2881 self.assertEqual(self.signature(C),
2882 ((('b', ..., ..., "positional_or_keyword"),),
2883 ...))
2884
2885 self.assertEqual(self.signature(CM),
2886 ((('name', ..., ..., "positional_or_keyword"),
2887 ('bases', ..., ..., "positional_or_keyword"),
2888 ('dct', ..., ..., "positional_or_keyword"),
2889 ('foo', 1, ..., "keyword_only")),
2890 ...))
2891
2892 class CMM(type):
2893 def __new__(mcls, name, bases, dct, *, foo=1):
2894 return super().__new__(mcls, name, bases, dct)
2895 def __call__(cls, nm, bs, dt):
2896 return type(nm, bs, dt)
2897 class CM(type, metaclass=CMM):
2898 def __new__(mcls, name, bases, dct, *, bar=2):
2899 return super().__new__(mcls, name, bases, dct)
2900 class C(metaclass=CM):
2901 def __init__(self, b):
2902 pass
2903
2904 self.assertEqual(self.signature(CMM),
2905 ((('name', ..., ..., "positional_or_keyword"),
2906 ('bases', ..., ..., "positional_or_keyword"),
2907 ('dct', ..., ..., "positional_or_keyword"),
2908 ('foo', 1, ..., "keyword_only")),
2909 ...))
2910
2911 self.assertEqual(self.signature(CM),
2912 ((('nm', ..., ..., "positional_or_keyword"),
2913 ('bs', ..., ..., "positional_or_keyword"),
2914 ('dt', ..., ..., "positional_or_keyword")),
2915 ...))
2916
2917 self.assertEqual(self.signature(C),
2918 ((('b', ..., ..., "positional_or_keyword"),),
2919 ...))
2920
2921 class CM(type):
2922 def __init__(cls, name, bases, dct, *, bar=2):
2923 return super().__init__(name, bases, dct)
2924 class C(metaclass=CM):
2925 def __init__(self, b):
2926 pass
2927
2928 self.assertEqual(self.signature(CM),
2929 ((('name', ..., ..., "positional_or_keyword"),
2930 ('bases', ..., ..., "positional_or_keyword"),
2931 ('dct', ..., ..., "positional_or_keyword"),
2932 ('bar', 2, ..., "keyword_only")),
2933 ...))
2934
Yury Selivanov145dff82014-02-01 13:49:29 -05002935 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2936 "Signature information for builtins requires docstrings")
2937 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002938 # Test classes without user-defined __init__ or __new__
2939 class C: pass
2940 self.assertEqual(str(inspect.signature(C)), '()')
2941 class D(C): pass
2942 self.assertEqual(str(inspect.signature(D)), '()')
2943
2944 # Test meta-classes without user-defined __init__ or __new__
2945 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002946 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002947 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2948 self.assertEqual(inspect.signature(C), None)
2949 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2950 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002951
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002952 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2953 "Signature information for builtins requires docstrings")
2954 def test_signature_on_builtin_class(self):
Antoine Pitrou91f43802019-05-26 17:10:09 +02002955 expected = ('(file, protocol=None, fix_imports=True, '
2956 'buffer_callback=None)')
2957 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002958
2959 class P(_pickle.Pickler): pass
2960 class EmptyTrait: pass
2961 class P2(EmptyTrait, P): pass
Antoine Pitrou91f43802019-05-26 17:10:09 +02002962 self.assertEqual(str(inspect.signature(P)), expected)
2963 self.assertEqual(str(inspect.signature(P2)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002964
2965 class P3(P2):
2966 def __init__(self, spam):
2967 pass
2968 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2969
2970 class MetaP(type):
2971 def __call__(cls, foo, bar):
2972 pass
2973 class P4(P2, metaclass=MetaP):
2974 pass
2975 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2976
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002977 def test_signature_on_callable_objects(self):
2978 class Foo:
2979 def __call__(self, a):
2980 pass
2981
2982 self.assertEqual(self.signature(Foo()),
2983 ((('a', ..., ..., "positional_or_keyword"),),
2984 ...))
2985
2986 class Spam:
2987 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002988 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002989 inspect.signature(Spam())
2990
2991 class Bar(Spam, Foo):
2992 pass
2993
2994 self.assertEqual(self.signature(Bar()),
2995 ((('a', ..., ..., "positional_or_keyword"),),
2996 ...))
2997
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002998 class Wrapped:
2999 pass
3000 Wrapped.__wrapped__ = lambda a: None
3001 self.assertEqual(self.signature(Wrapped),
3002 ((('a', ..., ..., "positional_or_keyword"),),
3003 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10003004 # wrapper loop:
3005 Wrapped.__wrapped__ = Wrapped
3006 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3007 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003008
3009 def test_signature_on_lambdas(self):
3010 self.assertEqual(self.signature((lambda a=10: a)),
3011 ((('a', 10, ..., "positional_or_keyword"),),
3012 ...))
3013
3014 def test_signature_equality(self):
3015 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003016 self.assertFalse(inspect.signature(foo) == 42)
3017 self.assertTrue(inspect.signature(foo) != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003018 self.assertTrue(inspect.signature(foo) == ALWAYS_EQ)
3019 self.assertFalse(inspect.signature(foo) != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003020
3021 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003022 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3023 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003024 self.assertEqual(
3025 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003026
3027 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003028 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3029 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003030 self.assertNotEqual(
3031 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003032
3033 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003034 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3035 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003036 self.assertNotEqual(
3037 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003038
3039 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003040 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3041 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003042 self.assertNotEqual(
3043 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003044
3045 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003046 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3047 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003048 self.assertNotEqual(
3049 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003050
3051 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003052 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3053 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003054 self.assertNotEqual(
3055 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003056 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003057 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3058 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003059 self.assertNotEqual(
3060 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003061
3062 def foo(*, a, b, c): pass
3063 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003064 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3065 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003066 self.assertEqual(
3067 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003068
3069 def foo(*, a=1, b, c): pass
3070 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003071 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3072 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003073 self.assertEqual(
3074 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003075
3076 def foo(pos, *, a=1, b, c): pass
3077 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003078 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3079 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003080 self.assertEqual(
3081 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003082
3083 def foo(pos, *, a, b, c): pass
3084 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003085 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3086 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003087 self.assertNotEqual(
3088 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003089
3090 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3091 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003092 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3093 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003094 self.assertEqual(
3095 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003096
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003097 def test_signature_hashable(self):
3098 S = inspect.Signature
3099 P = inspect.Parameter
3100
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003101 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003102 foo_sig = inspect.signature(foo)
3103
3104 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3105
3106 self.assertEqual(hash(foo_sig), hash(manual_sig))
3107 self.assertNotEqual(hash(foo_sig),
3108 hash(manual_sig.replace(return_annotation='spam')))
3109
3110 def bar(a) -> 1: pass
3111 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3112
3113 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003114 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003115 hash(inspect.signature(foo))
3116
3117 def foo(a) -> {}: pass
3118 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3119 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003120
3121 def test_signature_str(self):
3122 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3123 pass
3124 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003125 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003126
3127 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3128 pass
3129 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003130 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003131
3132 def foo():
3133 pass
3134 self.assertEqual(str(inspect.signature(foo)), '()')
3135
3136 def test_signature_str_positional_only(self):
3137 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003138 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003139
3140 def test(a_po, *, b, **kwargs):
3141 return a_po, kwargs
3142
3143 sig = inspect.signature(test)
3144 new_params = list(sig.parameters.values())
3145 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3146 test.__signature__ = sig.replace(parameters=new_params)
3147
3148 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003149 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003150
Yury Selivanov2393dca2014-01-27 15:07:58 -05003151 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3152 '(foo, /)')
3153
3154 self.assertEqual(str(S(parameters=[
3155 P('foo', P.POSITIONAL_ONLY),
3156 P('bar', P.VAR_KEYWORD)])),
3157 '(foo, /, **bar)')
3158
3159 self.assertEqual(str(S(parameters=[
3160 P('foo', P.POSITIONAL_ONLY),
3161 P('bar', P.VAR_POSITIONAL)])),
3162 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003163
3164 def test_signature_replace_anno(self):
3165 def test() -> 42:
3166 pass
3167
3168 sig = inspect.signature(test)
3169 sig = sig.replace(return_annotation=None)
3170 self.assertIs(sig.return_annotation, None)
3171 sig = sig.replace(return_annotation=sig.empty)
3172 self.assertIs(sig.return_annotation, sig.empty)
3173 sig = sig.replace(return_annotation=42)
3174 self.assertEqual(sig.return_annotation, 42)
3175 self.assertEqual(sig, inspect.signature(test))
3176
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003177 def test_signature_on_mangled_parameters(self):
3178 class Spam:
3179 def foo(self, __p1:1=2, *, __p2:2=3):
3180 pass
3181 class Ham(Spam):
3182 pass
3183
3184 self.assertEqual(self.signature(Spam.foo),
3185 ((('self', ..., ..., "positional_or_keyword"),
3186 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3187 ('_Spam__p2', 3, 2, "keyword_only")),
3188 ...))
3189
3190 self.assertEqual(self.signature(Spam.foo),
3191 self.signature(Ham.foo))
3192
Yury Selivanovda396452014-03-27 12:09:24 -04003193 def test_signature_from_callable_python_obj(self):
3194 class MySignature(inspect.Signature): pass
3195 def foo(a, *, b:1): pass
3196 foo_sig = MySignature.from_callable(foo)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003197 self.assertIsInstance(foo_sig, MySignature)
3198
3199 def test_signature_from_callable_class(self):
3200 # A regression test for a class inheriting its signature from `object`.
3201 class MySignature(inspect.Signature): pass
3202 class foo: pass
3203 foo_sig = MySignature.from_callable(foo)
3204 self.assertIsInstance(foo_sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003205
3206 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3207 "Signature information for builtins requires docstrings")
3208 def test_signature_from_callable_builtin_obj(self):
3209 class MySignature(inspect.Signature): pass
3210 sig = MySignature.from_callable(_pickle.Pickler)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003211 self.assertIsInstance(sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003212
larryhastingsf36ba122018-01-28 11:13:09 -08003213 def test_signature_definition_order_preserved_on_kwonly(self):
3214 for fn in signatures_with_lexicographic_keyword_only_parameters():
3215 signature = inspect.signature(fn)
3216 l = list(signature.parameters)
3217 sorted_l = sorted(l)
3218 self.assertTrue(l)
3219 self.assertEqual(l, sorted_l)
3220 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3221 l = list(signature.parameters)
3222 self.assertEqual(l, unsorted_keyword_only_parameters)
3223
Jens Reidel611836a2020-03-18 03:22:46 +01003224 def test_signater_parameters_is_ordered(self):
3225 p1 = inspect.signature(lambda x, y: None).parameters
3226 p2 = inspect.signature(lambda y, x: None).parameters
3227 self.assertNotEqual(p1, p2)
3228
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003229
3230class TestParameterObject(unittest.TestCase):
3231 def test_signature_parameter_kinds(self):
3232 P = inspect.Parameter
3233 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3234 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3235
3236 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3237 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3238
3239 def test_signature_parameter_object(self):
3240 p = inspect.Parameter('foo', default=10,
3241 kind=inspect.Parameter.POSITIONAL_ONLY)
3242 self.assertEqual(p.name, 'foo')
3243 self.assertEqual(p.default, 10)
3244 self.assertIs(p.annotation, p.empty)
3245 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3246
Dong-hee Naa9cab432018-05-30 00:04:08 +09003247 with self.assertRaisesRegex(ValueError, "value '123' is "
3248 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003249 inspect.Parameter('foo', default=10, kind='123')
3250
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003251 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003252 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3253
Yury Selivanov2393dca2014-01-27 15:07:58 -05003254 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003255 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3256
Yury Selivanov2393dca2014-01-27 15:07:58 -05003257 with self.assertRaisesRegex(ValueError,
3258 'is not a valid parameter name'):
3259 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3260
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003261 with self.assertRaisesRegex(ValueError,
3262 'is not a valid parameter name'):
3263 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3264
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003265 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003266 inspect.Parameter('a', default=42,
3267 kind=inspect.Parameter.VAR_KEYWORD)
3268
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003269 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003270 inspect.Parameter('a', default=42,
3271 kind=inspect.Parameter.VAR_POSITIONAL)
3272
3273 p = inspect.Parameter('a', default=42,
3274 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003275 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003276 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3277
3278 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003279 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003280
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003281 def test_signature_parameter_hashable(self):
3282 P = inspect.Parameter
3283 foo = P('foo', kind=P.POSITIONAL_ONLY)
3284 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3285 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3286 default=42)))
3287 self.assertNotEqual(hash(foo),
3288 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3289
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003290 def test_signature_parameter_equality(self):
3291 P = inspect.Parameter
3292 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3293
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003294 self.assertTrue(p == p)
3295 self.assertFalse(p != p)
3296 self.assertFalse(p == 42)
3297 self.assertTrue(p != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003298 self.assertTrue(p == ALWAYS_EQ)
3299 self.assertFalse(p != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003300
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003301 self.assertTrue(p == P('foo', default=42,
3302 kind=inspect.Parameter.KEYWORD_ONLY))
3303 self.assertFalse(p != P('foo', default=42,
3304 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003305
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003306 def test_signature_parameter_replace(self):
3307 p = inspect.Parameter('foo', default=42,
3308 kind=inspect.Parameter.KEYWORD_ONLY)
3309
3310 self.assertIsNot(p, p.replace())
3311 self.assertEqual(p, p.replace())
3312
3313 p2 = p.replace(annotation=1)
3314 self.assertEqual(p2.annotation, 1)
3315 p2 = p2.replace(annotation=p2.empty)
3316 self.assertEqual(p, p2)
3317
3318 p2 = p2.replace(name='bar')
3319 self.assertEqual(p2.name, 'bar')
3320 self.assertNotEqual(p2, p)
3321
Yury Selivanov2393dca2014-01-27 15:07:58 -05003322 with self.assertRaisesRegex(ValueError,
3323 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003324 p2 = p2.replace(name=p2.empty)
3325
3326 p2 = p2.replace(name='foo', default=None)
3327 self.assertIs(p2.default, None)
3328 self.assertNotEqual(p2, p)
3329
3330 p2 = p2.replace(name='foo', default=p2.empty)
3331 self.assertIs(p2.default, p2.empty)
3332
3333
3334 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3335 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3336 self.assertNotEqual(p2, p)
3337
Dong-hee Naa9cab432018-05-30 00:04:08 +09003338 with self.assertRaisesRegex(ValueError,
3339 "value <class 'inspect._empty'> "
3340 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003341 p2 = p2.replace(kind=p2.empty)
3342
3343 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3344 self.assertEqual(p2, p)
3345
3346 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003347 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3348 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003349
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003350 @cpython_only
3351 def test_signature_parameter_implicit(self):
3352 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003353 'implicit arguments must be passed as '
3354 'positional or keyword arguments, '
3355 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003356 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3357
3358 param = inspect.Parameter(
3359 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3360 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3361 self.assertEqual(param.name, 'implicit0')
3362
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003363 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003364 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003365
3366 with self.assertRaises(AttributeError):
3367 p.foo = 'bar'
3368
3369 with self.assertRaises(AttributeError):
3370 p.kind = 123
3371
3372
3373class TestSignatureBind(unittest.TestCase):
3374 @staticmethod
3375 def call(func, *args, **kwargs):
3376 sig = inspect.signature(func)
3377 ba = sig.bind(*args, **kwargs)
3378 return func(*ba.args, **ba.kwargs)
3379
3380 def test_signature_bind_empty(self):
3381 def test():
3382 return 42
3383
3384 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003385 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003386 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003387 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003388 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003389 with self.assertRaisesRegex(
3390 TypeError, "got an unexpected keyword argument 'spam'"):
3391
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003392 self.call(test, spam=1)
3393
3394 def test_signature_bind_var(self):
3395 def test(*args, **kwargs):
3396 return args, kwargs
3397
3398 self.assertEqual(self.call(test), ((), {}))
3399 self.assertEqual(self.call(test, 1), ((1,), {}))
3400 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3401 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3402 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3403 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3404 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3405 ((1, 2), {'foo': 'bar'}))
3406
3407 def test_signature_bind_just_args(self):
3408 def test(a, b, c):
3409 return a, b, c
3410
3411 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3412
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003413 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003414 self.call(test, 1, 2, 3, 4)
3415
Yury Selivanov86872752015-05-19 00:27:49 -04003416 with self.assertRaisesRegex(TypeError,
3417 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003418 self.call(test, 1)
3419
Yury Selivanov86872752015-05-19 00:27:49 -04003420 with self.assertRaisesRegex(TypeError,
3421 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003422 self.call(test)
3423
3424 def test(a, b, c=10):
3425 return a, b, c
3426 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3427 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3428
3429 def test(a=1, b=2, c=3):
3430 return a, b, c
3431 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3432 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3433 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3434
3435 def test_signature_bind_varargs_order(self):
3436 def test(*args):
3437 return args
3438
3439 self.assertEqual(self.call(test), ())
3440 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3441
3442 def test_signature_bind_args_and_varargs(self):
3443 def test(a, b, c=3, *args):
3444 return a, b, c, args
3445
3446 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3447 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3448 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3449 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3450
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003451 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003452 "multiple values for argument 'c'"):
3453 self.call(test, 1, 2, 3, c=4)
3454
3455 def test_signature_bind_just_kwargs(self):
3456 def test(**kwargs):
3457 return kwargs
3458
3459 self.assertEqual(self.call(test), {})
3460 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3461 {'foo': 'bar', 'spam': 'ham'})
3462
3463 def test_signature_bind_args_and_kwargs(self):
3464 def test(a, b, c=3, **kwargs):
3465 return a, b, c, kwargs
3466
3467 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3468 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3469 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3470 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3471 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3472 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3473 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3474 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3475 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3476 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3477 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3478 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3479 (1, 2, 4, {'foo': 'bar'}))
3480 self.assertEqual(self.call(test, c=5, a=4, b=3),
3481 (4, 3, 5, {}))
3482
3483 def test_signature_bind_kwonly(self):
3484 def test(*, foo):
3485 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003486 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003487 'too many positional arguments'):
3488 self.call(test, 1)
3489 self.assertEqual(self.call(test, foo=1), 1)
3490
3491 def test(a, *, foo=1, bar):
3492 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003493 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003494 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003495 self.call(test, 1)
3496
3497 def test(foo, *, bar):
3498 return foo, bar
3499 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3500 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3501
Yury Selivanov86872752015-05-19 00:27:49 -04003502 with self.assertRaisesRegex(
3503 TypeError, "got an unexpected keyword argument 'spam'"):
3504
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003505 self.call(test, bar=2, foo=1, spam=10)
3506
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003507 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003508 'too many positional arguments'):
3509 self.call(test, 1, 2)
3510
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003511 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003512 'too many positional arguments'):
3513 self.call(test, 1, 2, bar=2)
3514
Yury Selivanov86872752015-05-19 00:27:49 -04003515 with self.assertRaisesRegex(
3516 TypeError, "got an unexpected keyword argument 'spam'"):
3517
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003518 self.call(test, 1, bar=2, spam='ham')
3519
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003520 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003521 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003522 self.call(test, 1)
3523
3524 def test(foo, *, bar, **bin):
3525 return foo, bar, bin
3526 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3527 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3528 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3529 (1, 2, {'spam': 'ham'}))
3530 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3531 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003532 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003533 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003534 self.call(test, spam='ham', bar=2)
3535 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3536 (1, 2, {'bin': 1, 'spam': 10}))
3537
3538 def test_signature_bind_arguments(self):
3539 def test(a, *args, b, z=100, **kwargs):
3540 pass
3541 sig = inspect.signature(test)
3542 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3543 # we won't have 'z' argument in the bound arguments object, as we didn't
3544 # pass it to the 'bind'
3545 self.assertEqual(tuple(ba.arguments.items()),
3546 (('a', 10), ('args', (20,)), ('b', 30),
3547 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3548 self.assertEqual(ba.kwargs,
3549 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3550 self.assertEqual(ba.args, (10, 20))
3551
3552 def test_signature_bind_positional_only(self):
3553 P = inspect.Parameter
3554
3555 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3556 return a_po, b_po, c_po, foo, bar, kwargs
3557
3558 sig = inspect.signature(test)
3559 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3560 for name in ('a_po', 'b_po', 'c_po'):
3561 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3562 new_sig = sig.replace(parameters=new_params.values())
3563 test.__signature__ = new_sig
3564
3565 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3566 (1, 2, 4, 5, 6, {}))
3567
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003568 self.assertEqual(self.call(test, 1, 2),
3569 (1, 2, 3, 42, 50, {}))
3570
3571 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3572 (1, 2, 3, 4, 5, {}))
3573
3574 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3575 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3576
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003577 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003578 self.call(test, 1, 2, c_po=4)
3579
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003580 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003581 self.call(test, a_po=1, b_po=2)
3582
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003583 def test_signature_bind_with_self_arg(self):
3584 # Issue #17071: one of the parameters is named "self
3585 def test(a, self, b):
3586 pass
3587 sig = inspect.signature(test)
3588 ba = sig.bind(1, 2, 3)
3589 self.assertEqual(ba.args, (1, 2, 3))
3590 ba = sig.bind(1, self=2, b=3)
3591 self.assertEqual(ba.args, (1, 2, 3))
3592
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003593 def test_signature_bind_vararg_name(self):
3594 def test(a, *args):
3595 return a, args
3596 sig = inspect.signature(test)
3597
Yury Selivanov86872752015-05-19 00:27:49 -04003598 with self.assertRaisesRegex(
3599 TypeError, "got an unexpected keyword argument 'args'"):
3600
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003601 sig.bind(a=0, args=1)
3602
3603 def test(*args, **kwargs):
3604 return args, kwargs
3605 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3606
3607 sig = inspect.signature(test)
3608 ba = sig.bind(args=1)
3609 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3610
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003611 @cpython_only
3612 def test_signature_bind_implicit_arg(self):
3613 # Issue #19611: getcallargs should work with set comprehensions
3614 def make_set():
3615 return {z * z for z in range(5)}
3616 setcomp_code = make_set.__code__.co_consts[1]
3617 setcomp_func = types.FunctionType(setcomp_code, {})
3618
3619 iterator = iter(range(5))
3620 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3621
Pablo Galindof3ef06a2019-10-15 12:40:02 +01003622 def test_signature_bind_posonly_kwargs(self):
3623 def foo(bar, /, **kwargs):
3624 return bar, kwargs.get(bar)
3625
3626 sig = inspect.signature(foo)
3627 result = sig.bind("pos-only", bar="keyword")
3628
3629 self.assertEqual(result.kwargs, {"bar": "keyword"})
3630 self.assertIn(("bar", "pos-only"), result.arguments.items())
3631
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003632
3633class TestBoundArguments(unittest.TestCase):
3634 def test_signature_bound_arguments_unhashable(self):
3635 def foo(a): pass
3636 ba = inspect.signature(foo).bind(1)
3637
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003638 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003639 hash(ba)
3640
3641 def test_signature_bound_arguments_equality(self):
3642 def foo(a): pass
3643 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003644 self.assertTrue(ba == ba)
3645 self.assertFalse(ba != ba)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003646 self.assertTrue(ba == ALWAYS_EQ)
3647 self.assertFalse(ba != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003648
3649 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003650 self.assertTrue(ba == ba2)
3651 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003652
3653 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003654 self.assertFalse(ba == ba3)
3655 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003656 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003657 self.assertTrue(ba == ba3)
3658 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003659
3660 def bar(b): pass
3661 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003662 self.assertFalse(ba == ba4)
3663 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003664
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003665 def foo(*, a, b): pass
3666 sig = inspect.signature(foo)
3667 ba1 = sig.bind(a=1, b=2)
3668 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003669 self.assertTrue(ba1 == ba2)
3670 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003671
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003672 def test_signature_bound_arguments_pickle(self):
3673 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3674 sig = inspect.signature(foo)
3675 ba = sig.bind(20, 30, z={})
3676
3677 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3678 with self.subTest(pickle_ver=ver):
3679 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3680 self.assertEqual(ba, ba_pickled)
3681
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003682 def test_signature_bound_arguments_repr(self):
3683 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3684 sig = inspect.signature(foo)
3685 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003686 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003687
Yury Selivanovb907a512015-05-16 13:45:09 -04003688 def test_signature_bound_arguments_apply_defaults(self):
3689 def foo(a, b=1, *args, c:1={}, **kw): pass
3690 sig = inspect.signature(foo)
3691
3692 ba = sig.bind(20)
3693 ba.apply_defaults()
3694 self.assertEqual(
3695 list(ba.arguments.items()),
3696 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3697
3698 # Make sure that we preserve the order:
3699 # i.e. 'c' should be *before* 'kw'.
3700 ba = sig.bind(10, 20, 30, d=1)
3701 ba.apply_defaults()
3702 self.assertEqual(
3703 list(ba.arguments.items()),
3704 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3705
3706 # Make sure that BoundArguments produced by bind_partial()
3707 # are supported.
3708 def foo(a, b): pass
3709 sig = inspect.signature(foo)
3710 ba = sig.bind_partial(20)
3711 ba.apply_defaults()
3712 self.assertEqual(
3713 list(ba.arguments.items()),
3714 [('a', 20)])
3715
3716 # Test no args
3717 def foo(): pass
3718 sig = inspect.signature(foo)
3719 ba = sig.bind()
3720 ba.apply_defaults()
3721 self.assertEqual(list(ba.arguments.items()), [])
3722
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003723 # Make sure a no-args binding still acquires proper defaults.
3724 def foo(a='spam'): pass
3725 sig = inspect.signature(foo)
3726 ba = sig.bind()
3727 ba.apply_defaults()
3728 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3729
Rémi Lapeyre2cca8ef2020-01-28 13:47:03 +01003730 def test_signature_bound_arguments_arguments_type(self):
3731 def foo(a): pass
3732 ba = inspect.signature(foo).bind(1)
3733 self.assertIs(type(ba.arguments), dict)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003734
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003735class TestSignaturePrivateHelpers(unittest.TestCase):
3736 def test_signature_get_bound_param(self):
3737 getter = inspect._signature_get_bound_param
3738
3739 self.assertEqual(getter('($self)'), 'self')
3740 self.assertEqual(getter('($self, obj)'), 'self')
3741 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3742
Larry Hastings2623c8c2014-02-08 22:15:29 -08003743 def _strip_non_python_syntax(self, input,
3744 clean_signature, self_parameter, last_positional_only):
3745 computed_clean_signature, \
3746 computed_self_parameter, \
3747 computed_last_positional_only = \
3748 inspect._signature_strip_non_python_syntax(input)
3749 self.assertEqual(computed_clean_signature, clean_signature)
3750 self.assertEqual(computed_self_parameter, self_parameter)
3751 self.assertEqual(computed_last_positional_only, last_positional_only)
3752
3753 def test_signature_strip_non_python_syntax(self):
3754 self._strip_non_python_syntax(
3755 "($module, /, path, mode, *, dir_fd=None, " +
3756 "effective_ids=False,\n follow_symlinks=True)",
3757 "(module, path, mode, *, dir_fd=None, " +
3758 "effective_ids=False, follow_symlinks=True)",
3759 0,
3760 0)
3761
3762 self._strip_non_python_syntax(
3763 "($module, word, salt, /)",
3764 "(module, word, salt)",
3765 0,
3766 2)
3767
3768 self._strip_non_python_syntax(
3769 "(x, y=None, z=None, /)",
3770 "(x, y=None, z=None)",
3771 None,
3772 2)
3773
3774 self._strip_non_python_syntax(
3775 "(x, y=None, z=None)",
3776 "(x, y=None, z=None)",
3777 None,
3778 None)
3779
3780 self._strip_non_python_syntax(
3781 "(x,\n y=None,\n z = None )",
3782 "(x, y=None, z=None)",
3783 None,
3784 None)
3785
3786 self._strip_non_python_syntax(
3787 "",
3788 "",
3789 None,
3790 None)
3791
3792 self._strip_non_python_syntax(
3793 None,
3794 None,
3795 None,
3796 None)
3797
Nick Coghlan9c680b02015-04-13 12:54:54 -04003798class TestSignatureDefinitions(unittest.TestCase):
3799 # This test case provides a home for checking that particular APIs
3800 # have signatures available for introspection
3801
3802 @cpython_only
3803 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3804 "Signature information for builtins requires docstrings")
3805 def test_builtins_have_signatures(self):
3806 # This checks all builtin callables in CPython have signatures
3807 # A few have signatures Signature can't yet handle, so we skip those
3808 # since they will have to wait until PEP 457 adds the required
3809 # introspection support to the inspect module
3810 # Some others also haven't been converted yet for various other
3811 # reasons, so we also skip those for the time being, but design
3812 # the test to fail in order to indicate when it needs to be
3813 # updated.
3814 no_signature = set()
3815 # These need PEP 457 groups
3816 needs_groups = {"range", "slice", "dir", "getattr",
3817 "next", "iter", "vars"}
3818 no_signature |= needs_groups
3819 # These need PEP 457 groups or a signature change to accept None
3820 needs_semantic_update = {"round"}
3821 no_signature |= needs_semantic_update
3822 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003823 needs_varargs = {"breakpoint", "min", "max", "print",
3824 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003825 no_signature |= needs_varargs
3826 # These simply weren't covered in the initial AC conversion
3827 # for builtin callables
3828 not_converted_yet = {"open", "__import__"}
3829 no_signature |= not_converted_yet
3830 # These builtin types are expected to provide introspection info
3831 types_with_signatures = set()
3832 # Check the signatures we expect to be there
3833 ns = vars(builtins)
3834 for name, obj in sorted(ns.items()):
3835 if not callable(obj):
3836 continue
3837 # The builtin types haven't been converted to AC yet
3838 if isinstance(obj, type) and (name not in types_with_signatures):
3839 # Note that this also skips all the exception types
3840 no_signature.add(name)
3841 if (name in no_signature):
3842 # Not yet converted
3843 continue
3844 with self.subTest(builtin=name):
3845 self.assertIsNotNone(inspect.signature(obj))
3846 # Check callables that haven't been converted don't claim a signature
3847 # This ensures this test will start failing as more signatures are
3848 # added, so the affected items can be moved into the scope of the
3849 # regression test above
3850 for name in no_signature:
3851 with self.subTest(builtin=name):
3852 self.assertIsNone(obj.__text_signature__)
3853
Serhiy Storchakad53cf992019-05-06 22:40:27 +03003854 def test_python_function_override_signature(self):
3855 def func(*args, **kwargs):
3856 pass
3857 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
3858 sig = inspect.signature(func)
3859 self.assertIsNotNone(sig)
3860 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
3861 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
3862 sig = inspect.signature(func)
3863 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
3864
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003865
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003866class NTimesUnwrappable:
3867 def __init__(self, n):
3868 self.n = n
3869 self._next = None
3870
3871 @property
3872 def __wrapped__(self):
3873 if self.n <= 0:
3874 raise Exception("Unwrapped too many times")
3875 if self._next is None:
3876 self._next = NTimesUnwrappable(self.n - 1)
3877 return self._next
3878
Nick Coghlane8c45d62013-07-28 20:00:01 +10003879class TestUnwrap(unittest.TestCase):
3880
3881 def test_unwrap_one(self):
3882 def func(a, b):
3883 return a + b
3884 wrapper = functools.lru_cache(maxsize=20)(func)
3885 self.assertIs(inspect.unwrap(wrapper), func)
3886
3887 def test_unwrap_several(self):
3888 def func(a, b):
3889 return a + b
3890 wrapper = func
3891 for __ in range(10):
3892 @functools.wraps(wrapper)
3893 def wrapper():
3894 pass
3895 self.assertIsNot(wrapper.__wrapped__, func)
3896 self.assertIs(inspect.unwrap(wrapper), func)
3897
3898 def test_stop(self):
3899 def func1(a, b):
3900 return a + b
3901 @functools.wraps(func1)
3902 def func2():
3903 pass
3904 @functools.wraps(func2)
3905 def wrapper():
3906 pass
3907 func2.stop_here = 1
3908 unwrapped = inspect.unwrap(wrapper,
3909 stop=(lambda f: hasattr(f, "stop_here")))
3910 self.assertIs(unwrapped, func2)
3911
3912 def test_cycle(self):
3913 def func1(): pass
3914 func1.__wrapped__ = func1
3915 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3916 inspect.unwrap(func1)
3917
3918 def func2(): pass
3919 func2.__wrapped__ = func1
3920 func1.__wrapped__ = func2
3921 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3922 inspect.unwrap(func1)
3923 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3924 inspect.unwrap(func2)
3925
3926 def test_unhashable(self):
3927 def func(): pass
3928 func.__wrapped__ = None
3929 class C:
3930 __hash__ = None
3931 __wrapped__ = func
3932 self.assertIsNone(inspect.unwrap(C()))
3933
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003934 def test_recursion_limit(self):
3935 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3936 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3937 inspect.unwrap(obj)
3938
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003939class TestMain(unittest.TestCase):
3940 def test_only_source(self):
3941 module = importlib.import_module('unittest')
3942 rc, out, err = assert_python_ok('-m', 'inspect',
3943 'unittest')
3944 lines = out.decode().splitlines()
3945 # ignore the final newline
3946 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3947 self.assertEqual(err, b'')
3948
Yury Selivanov42407ab2014-06-23 10:23:50 -07003949 def test_custom_getattr(self):
3950 def foo():
3951 pass
3952 foo.__signature__ = 42
3953 with self.assertRaises(TypeError):
3954 inspect.signature(foo)
3955
Brett Cannon634a8fc2013-10-02 10:25:42 -04003956 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003957 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003958 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003959 rc, out, err = assert_python_ok('-m', 'inspect',
3960 'concurrent.futures:ThreadPoolExecutor')
3961 lines = out.decode().splitlines()
3962 # ignore the final newline
3963 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003964 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003965 self.assertEqual(err, b'')
3966
3967 def test_builtins(self):
3968 module = importlib.import_module('unittest')
3969 _, out, err = assert_python_failure('-m', 'inspect',
3970 'sys')
3971 lines = err.decode().splitlines()
3972 self.assertEqual(lines, ["Can't get info for builtin modules."])
3973
3974 def test_details(self):
3975 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003976 args = support.optim_args_from_interpreter_flags()
3977 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003978 'unittest', '--details')
3979 output = out.decode()
3980 # Just a quick sanity check on the output
3981 self.assertIn(module.__name__, output)
3982 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003983 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003984 self.assertEqual(err, b'')
3985
3986
Yury Selivanovef1e7502014-12-08 16:05:34 -05003987class TestReload(unittest.TestCase):
3988
3989 src_before = textwrap.dedent("""\
3990def foo():
3991 print("Bla")
3992 """)
3993
3994 src_after = textwrap.dedent("""\
3995def foo():
3996 print("Oh no!")
3997 """)
3998
3999 def assertInspectEqual(self, path, source):
4000 inspected_src = inspect.getsource(source)
4001 with open(path) as src:
4002 self.assertEqual(
4003 src.read().splitlines(True),
4004 inspected_src.splitlines(True)
4005 )
4006
4007 def test_getsource_reload(self):
4008 # see issue 1218234
4009 with _ready_to_import('reload_bug', self.src_before) as (name, path):
4010 module = importlib.import_module(name)
4011 self.assertInspectEqual(path, module)
4012 with open(path, 'w') as src:
4013 src.write(self.src_after)
4014 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004015
Nick Coghlane8c45d62013-07-28 20:00:01 +10004016
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004017def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00004018 run_unittest(
4019 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
4020 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
4021 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00004022 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07004023 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04004024 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04004025 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04004026 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07004027 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00004028 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00004029
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004030if __name__ == "__main__":
4031 test_main()