blob: b3aae3a18ecfae6e7662cee0e7a83968392c2919 [file] [log] [blame]
Nick Coghlanf9e227e2014-08-17 14:01:19 +10001import builtins
Guido van Rossum813b0e52007-05-21 18:11:34 +00002import collections
Larry Hastings5c661892014-01-24 06:17:25 -08003import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10004import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10005import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08006import inspect
7import io
8import linecache
9import os
Christian Heimesa3538eb2007-11-06 11:44:48 +000010from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080011import _pickle
Yury Selivanova5d63dd2014-03-27 11:31:43 -040012import pickle
Larry Hastings5c661892014-01-24 06:17:25 -080013import shutil
14import sys
15import types
Yury Selivanovef1e7502014-12-08 16:05:34 -050016import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080017import unicodedata
18import unittest
Yury Selivanova773de02014-02-21 18:30:53 -050019import unittest.mock
Yury Selivanov75445082015-05-11 22:57:16 -040020import warnings
Larry Hastings5c661892014-01-24 06:17:25 -080021
Brett Cannon634a8fc2013-10-02 10:25:42 -040022try:
23 from concurrent.futures import ThreadPoolExecutor
24except ImportError:
25 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000026
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020027from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Nick Coghlanf9e227e2014-08-17 14:01:19 +100028from test.support import MISSING_C_DOCSTRINGS, cpython_only
Berker Peksagce643912015-05-06 06:33:17 +030029from test.support.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000030from test import inspect_fodder as mod
31from test import inspect_fodder2 as mod2
Victor Stinner9def2842016-01-18 12:15:08 +010032from test import support
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000033
Yury Selivanovef1e7502014-12-08 16:05:34 -050034from test.test_import import _ready_to_import
35
R. David Murray74b89242009-05-13 17:33:03 +000036
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000037# Functions tested in this suite:
38# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000039# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
40# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
Berker Peksagfa3922c2015-07-31 04:11:29 +030041# getclasstree, getargvalues, formatargspec, formatargvalues,
Christian Heimes7131fd92008-02-19 14:21:46 +000042# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000043
Nick Coghlanf088e5e2008-12-14 11:50:48 +000044# NOTE: There are some additional tests relating to interaction with
45# zipimport in the test_zipimport_support test module.
46
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000047modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000048if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000049 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000050
Christian Heimesa3538eb2007-11-06 11:44:48 +000051# Normalize file names: on Windows, the case of file names of compiled
52# modules depends on the path used to start the python executable.
53modfile = normcase(modfile)
54
55def revise(filename, *args):
56 return (normcase(filename),) + args
57
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000058git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000059
larryhastingsf36ba122018-01-28 11:13:09 -080060
61def signatures_with_lexicographic_keyword_only_parameters():
62 """
63 Yields a whole bunch of functions with only keyword-only parameters,
64 where those parameters are always in lexicographically sorted order.
65 """
66 parameters = ['a', 'bar', 'c', 'delta', 'ephraim', 'magical', 'yoyo', 'z']
67 for i in range(1, 2**len(parameters)):
68 p = []
69 bit = 1
70 for j in range(len(parameters)):
71 if i & (bit << j):
72 p.append(parameters[j])
73 fn_text = "def foo(*, " + ", ".join(p) + "): pass"
74 symbols = {}
75 exec(fn_text, symbols, symbols)
76 yield symbols['foo']
77
78
79def unsorted_keyword_only_parameters_fn(*, throw, out, the, baby, with_,
80 the_, bathwater):
81 pass
82
83unsorted_keyword_only_parameters = 'throw out the baby with_ the_ bathwater'.split()
84
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000085class IsTestBase(unittest.TestCase):
86 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
87 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000088 inspect.ismodule, inspect.istraceback,
Yury Selivanov75445082015-05-11 22:57:16 -040089 inspect.isgenerator, inspect.isgeneratorfunction,
Yury Selivanoveb636452016-09-08 22:01:51 -070090 inspect.iscoroutine, inspect.iscoroutinefunction,
91 inspect.isasyncgen, inspect.isasyncgenfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000092
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000093 def istest(self, predicate, exp):
94 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000095 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000096
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000097 for other in self.predicates - set([predicate]):
Yury Selivanov75445082015-05-11 22:57:16 -040098 if (predicate == inspect.isgeneratorfunction or \
Yury Selivanoveb636452016-09-08 22:01:51 -070099 predicate == inspect.isasyncgenfunction or \
Yury Selivanov75445082015-05-11 22:57:16 -0400100 predicate == inspect.iscoroutinefunction) and \
Christian Heimes7131fd92008-02-19 14:21:46 +0000101 other == inspect.isfunction:
102 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000103 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000104
Christian Heimes7131fd92008-02-19 14:21:46 +0000105def generator_function_example(self):
106 for i in range(2):
107 yield i
108
Yury Selivanoveb636452016-09-08 22:01:51 -0700109async def async_generator_function_example(self):
110 async for i in range(2):
111 yield i
112
Yury Selivanov75445082015-05-11 22:57:16 -0400113async def coroutine_function_example(self):
114 return 'spam'
115
116@types.coroutine
117def gen_coroutine_function_example(self):
118 yield
119 return 'spam'
120
Serhiy Storchaka3018cc42015-07-18 23:19:05 +0300121class EqualsToAll:
122 def __eq__(self, other):
123 return True
Yury Selivanova5d63dd2014-03-27 11:31:43 -0400124
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000125class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +0000126
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000127 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200128 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000129 self.istest(inspect.isbuiltin, 'sys.exit')
130 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +0000131 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200132 try:
133 1/0
134 except:
135 tb = sys.exc_info()[2]
136 self.istest(inspect.isframe, 'tb.tb_frame')
137 self.istest(inspect.istraceback, 'tb')
138 if hasattr(types, 'GetSetDescriptorType'):
139 self.istest(inspect.isgetsetdescriptor,
140 'type(tb.tb_frame).f_locals')
141 else:
142 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
143 finally:
144 # Clear traceback and all the frames and local variables hanging to it.
145 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000146 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000147 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000148 self.istest(inspect.ismethod, 'git.argue')
Jeroen Demeyerfcef60f2019-04-02 16:03:42 +0200149 self.istest(inspect.ismethod, 'mod.custom_method')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000150 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000151 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000152 self.istest(inspect.isgenerator, '(x for x in range(2))')
153 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanoveb636452016-09-08 22:01:51 -0700154 self.istest(inspect.isasyncgen,
155 'async_generator_function_example(1)')
156 self.istest(inspect.isasyncgenfunction,
157 'async_generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400158
159 with warnings.catch_warnings():
160 warnings.simplefilter("ignore")
161 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
162 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
163
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000164 if hasattr(types, 'MemberDescriptorType'):
165 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
166 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000167 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000168
Yury Selivanov75445082015-05-11 22:57:16 -0400169 def test_iscoroutine(self):
Pablo Galindo7cd25432018-10-26 12:19:14 +0100170 async_gen_coro = async_generator_function_example(1)
Yury Selivanov75445082015-05-11 22:57:16 -0400171 gen_coro = gen_coroutine_function_example(1)
172 coro = coroutine_function_example(1)
173
Yury Selivanov5376ba92015-06-22 12:19:30 -0400174 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400175 inspect.iscoroutinefunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100176 self.assertFalse(
177 inspect.iscoroutinefunction(
178 functools.partial(functools.partial(
179 gen_coroutine_function_example))))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400180 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400181
182 self.assertTrue(
183 inspect.isgeneratorfunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100184 self.assertTrue(
185 inspect.isgeneratorfunction(
186 functools.partial(functools.partial(
187 gen_coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400188 self.assertTrue(inspect.isgenerator(gen_coro))
189
190 self.assertTrue(
191 inspect.iscoroutinefunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100192 self.assertTrue(
193 inspect.iscoroutinefunction(
194 functools.partial(functools.partial(
195 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400196 self.assertTrue(inspect.iscoroutine(coro))
197
198 self.assertFalse(
199 inspect.isgeneratorfunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100200 self.assertFalse(
201 inspect.isgeneratorfunction(
202 functools.partial(functools.partial(
203 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400204 self.assertFalse(inspect.isgenerator(coro))
205
Pablo Galindo7cd25432018-10-26 12:19:14 +0100206 self.assertTrue(
207 inspect.isasyncgenfunction(async_generator_function_example))
208 self.assertTrue(
209 inspect.isasyncgenfunction(
210 functools.partial(functools.partial(
211 async_generator_function_example))))
212 self.assertTrue(inspect.isasyncgen(async_gen_coro))
213
214 coro.close(); gen_coro.close(); # silence warnings
Yury Selivanov75445082015-05-11 22:57:16 -0400215
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400216 def test_isawaitable(self):
217 def gen(): yield
218 self.assertFalse(inspect.isawaitable(gen()))
219
220 coro = coroutine_function_example(1)
221 gen_coro = gen_coroutine_function_example(1)
222
223 self.assertTrue(inspect.isawaitable(coro))
224 self.assertTrue(inspect.isawaitable(gen_coro))
225
226 class Future:
227 def __await__():
228 pass
229 self.assertTrue(inspect.isawaitable(Future()))
230 self.assertFalse(inspect.isawaitable(Future))
231
232 class NotFuture: pass
233 not_fut = NotFuture()
234 not_fut.__await__ = lambda: None
235 self.assertFalse(inspect.isawaitable(not_fut))
236
237 coro.close(); gen_coro.close() # silence warnings
238
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000239 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000240 self.assertTrue(inspect.isroutine(mod.spam))
241 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000242
Benjamin Petersonc4656002009-01-17 22:41:18 +0000243 def test_isclass(self):
244 self.istest(inspect.isclass, 'mod.StupidGit')
245 self.assertTrue(inspect.isclass(list))
246
247 class CustomGetattr(object):
248 def __getattr__(self, attr):
249 return None
250 self.assertFalse(inspect.isclass(CustomGetattr()))
251
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000252 def test_get_slot_members(self):
253 class C(object):
254 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000255 x = C()
256 x.a = 42
257 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000258 self.assertIn('a', members)
259 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000260
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000261 def test_isabstract(self):
262 from abc import ABCMeta, abstractmethod
263
264 class AbstractClassExample(metaclass=ABCMeta):
265
266 @abstractmethod
267 def foo(self):
268 pass
269
270 class ClassExample(AbstractClassExample):
271 def foo(self):
272 pass
273
274 a = ClassExample()
275
276 # Test general behaviour.
277 self.assertTrue(inspect.isabstract(AbstractClassExample))
278 self.assertFalse(inspect.isabstract(ClassExample))
279 self.assertFalse(inspect.isabstract(a))
280 self.assertFalse(inspect.isabstract(int))
281 self.assertFalse(inspect.isabstract(5))
282
Natefcfe80e2017-04-24 10:06:15 -0700283 def test_isabstract_during_init_subclass(self):
284 from abc import ABCMeta, abstractmethod
285 isabstract_checks = []
286 class AbstractChecker(metaclass=ABCMeta):
287 def __init_subclass__(cls):
288 isabstract_checks.append(inspect.isabstract(cls))
289 class AbstractClassExample(AbstractChecker):
290 @abstractmethod
291 def foo(self):
292 pass
293 class ClassExample(AbstractClassExample):
294 def foo(self):
295 pass
296 self.assertEqual(isabstract_checks, [True, False])
297
298 isabstract_checks.clear()
299 class AbstractChild(AbstractClassExample):
300 pass
301 class AbstractGrandchild(AbstractChild):
302 pass
303 class ConcreteGrandchild(ClassExample):
304 pass
305 self.assertEqual(isabstract_checks, [True, True, False])
306
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000307
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000308class TestInterpreterStack(IsTestBase):
309 def __init__(self, *args, **kwargs):
310 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000311
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000312 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000313
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000314 def test_abuse_done(self):
315 self.istest(inspect.istraceback, 'git.ex[2]')
316 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000317
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000318 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000319 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000320 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000321 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000322 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000323 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000324 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000325 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000326 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000327 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400328 # Test named tuple fields
329 record = mod.st[0]
330 self.assertIs(record.frame, mod.fr)
331 self.assertEqual(record.lineno, 16)
332 self.assertEqual(record.filename, mod.__file__)
333 self.assertEqual(record.function, 'eggs')
334 self.assertIn('inspect.stack()', record.code_context[0])
335 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000336
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000337 def test_trace(self):
338 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000339 self.assertEqual(revise(*git.tr[0][1:]),
340 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
341 self.assertEqual(revise(*git.tr[1][1:]),
342 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
343 self.assertEqual(revise(*git.tr[2][1:]),
344 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000345
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000346 def test_frame(self):
347 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
348 self.assertEqual(args, ['x', 'y'])
349 self.assertEqual(varargs, None)
350 self.assertEqual(varkw, None)
351 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
352 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
353 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000354
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000355 def test_previous_frame(self):
356 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000357 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000358 self.assertEqual(varargs, 'g')
359 self.assertEqual(varkw, 'h')
360 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000361 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000362
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000363class GetSourceBase(unittest.TestCase):
364 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000365 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000366
Yury Selivanov6738b112015-05-16 10:10:21 -0400367 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000368 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000369 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000370
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000371 def sourcerange(self, top, bottom):
372 lines = self.source.split("\n")
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700373 return "\n".join(lines[top-1:bottom]) + ("\n" if bottom else "")
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000374
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000375 def assertSourceEqual(self, obj, top, bottom):
376 self.assertEqual(inspect.getsource(obj),
377 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000378
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700379class SlotUser:
380 'Docstrings for __slots__'
381 __slots__ = {'power': 'measured in kilowatts',
382 'distance': 'measured in kilometers'}
383
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000384class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000385 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000386
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000387 def test_getclasses(self):
388 classes = inspect.getmembers(mod, inspect.isclass)
389 self.assertEqual(classes,
390 [('FesteringGob', mod.FesteringGob),
391 ('MalodorousPervert', mod.MalodorousPervert),
392 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300393 ('StupidGit', mod.StupidGit),
394 ('Tit', mod.MalodorousPervert),
395 ])
396 tree = inspect.getclasstree([cls[1] for cls in classes])
397 self.assertEqual(tree,
398 [(object, ()),
399 [(mod.ParrotDroppings, (object,)),
400 [(mod.FesteringGob, (mod.MalodorousPervert,
401 mod.ParrotDroppings))
402 ],
403 (mod.StupidGit, (object,)),
404 [(mod.MalodorousPervert, (mod.StupidGit,)),
405 [(mod.FesteringGob, (mod.MalodorousPervert,
406 mod.ParrotDroppings))
407 ]
408 ]
409 ]
410 ])
411 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000412 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000413 [(object, ()),
414 [(mod.ParrotDroppings, (object,)),
415 (mod.StupidGit, (object,)),
416 [(mod.MalodorousPervert, (mod.StupidGit,)),
417 [(mod.FesteringGob, (mod.MalodorousPervert,
418 mod.ParrotDroppings))
419 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000420 ]
421 ]
422 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000423
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000424 def test_getfunctions(self):
425 functions = inspect.getmembers(mod, inspect.isfunction)
426 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300427 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000428 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000429
R. David Murray378c0cf2010-02-24 01:46:21 +0000430 @unittest.skipIf(sys.flags.optimize >= 2,
431 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000432 def test_getdoc(self):
433 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
434 self.assertEqual(inspect.getdoc(mod.StupidGit),
435 'A longer,\n\nindented\n\ndocstring.')
436 self.assertEqual(inspect.getdoc(git.abuse),
437 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700438 self.assertEqual(inspect.getdoc(SlotUser.power),
439 'measured in kilowatts')
440 self.assertEqual(inspect.getdoc(SlotUser.distance),
441 'measured in kilometers')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000442
Serhiy Storchaka5cf2b7252015-04-03 22:38:53 +0300443 @unittest.skipIf(sys.flags.optimize >= 2,
444 "Docstrings are omitted with -O2 and above")
445 def test_getdoc_inherited(self):
446 self.assertEqual(inspect.getdoc(mod.FesteringGob),
447 'A longer,\n\nindented\n\ndocstring.')
448 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
449 'Another\n\ndocstring\n\ncontaining\n\ntabs')
450 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
451 'Another\n\ndocstring\n\ncontaining\n\ntabs')
452 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
453 'The automatic gainsaying.')
454
455 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
456 def test_finddoc(self):
457 finddoc = inspect._finddoc
458 self.assertEqual(finddoc(int), int.__doc__)
459 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
460 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
461 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
462 self.assertEqual(finddoc(int.real), int.real.__doc__)
463
Georg Brandl0c77a822008-06-10 16:37:50 +0000464 def test_cleandoc(self):
465 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
466 'An\nindented\ndocstring.')
467
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000468 def test_getcomments(self):
469 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
470 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Marco Buttu3f2155f2017-03-17 09:50:23 +0100471 # If the object source file is not available, return None.
472 co = compile('x=1', '_non_existing_filename.py', 'exec')
473 self.assertIsNone(inspect.getcomments(co))
474 # If the object has been defined in C, return None.
475 self.assertIsNone(inspect.getcomments(list))
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000476
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000477 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000478 # Check actual module
479 self.assertEqual(inspect.getmodule(mod), mod)
480 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000481 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000482 # Check a method (no __module__ attribute, falls back to filename)
483 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
484 # Do it again (check the caching isn't broken)
485 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
486 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000487 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000488 # Check filename override
489 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000490
Berker Peksagff0e3b72017-01-02 06:57:43 +0300491 def test_getframeinfo_get_first_line(self):
492 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
493 self.assertEqual(frame_info.code_context[0], "# line 1\n")
494 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
495
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000496 def test_getsource(self):
497 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200498 self.assertSourceEqual(mod.StupidGit, 21, 51)
499 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000500
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000501 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000502 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
503 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000504 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100505 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000506 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000507 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200508 try:
509 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
510 finally:
511 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000512
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000513 def test_getfile(self):
514 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000515
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500516 def test_getfile_class_without_module(self):
517 class CM(type):
518 @property
519 def __module__(cls):
520 raise AttributeError
521 class C(metaclass=CM):
522 pass
523 with self.assertRaises(TypeError):
524 inspect.getfile(C)
525
Thomas Kluyvere968bc732017-10-24 13:42:36 +0100526 def test_getfile_broken_repr(self):
527 class ErrorRepr:
528 def __repr__(self):
529 raise Exception('xyz')
530 er = ErrorRepr()
531 with self.assertRaises(TypeError):
532 inspect.getfile(er)
533
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000534 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000535 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000536 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000537 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000538 m.__file__ = "<string>" # hopefully not a real filename...
539 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000540 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000541 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000542 del sys.modules[name]
543 inspect.getmodule(compile('a=10','','single'))
544
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500545 def test_proceed_with_fake_filename(self):
546 '''doctest monkeypatches linecache to enable inspection'''
547 fn, source = '<test>', 'def x(): pass\n'
548 getlines = linecache.getlines
549 def monkey(filename, module_globals=None):
550 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300551 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500552 else:
553 return getlines(filename, module_globals)
554 linecache.getlines = monkey
555 try:
556 ns = {}
557 exec(compile(source, fn, 'single'), ns)
558 inspect.getsource(ns["x"])
559 finally:
560 linecache.getlines = getlines
561
Antoine Pitroua8723a02015-04-15 00:41:29 +0200562 def test_getsource_on_code_object(self):
563 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
564
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700565class TestGettingSourceOfToplevelFrames(GetSourceBase):
566 fodderModule = mod
567
568 def test_range_toplevel_frame(self):
569 self.maxDiff = None
570 self.assertSourceEqual(mod.currentframe, 1, None)
571
572 def test_range_traceback_toplevel_frame(self):
573 self.assertSourceEqual(mod.tb, 1, None)
574
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000575class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000576 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000577
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000578 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000579 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000580
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000581 def test_replacing_decorator(self):
582 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000583
Yury Selivanov081bbf62014-09-26 17:34:54 -0400584 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200585 self.assertSourceEqual(mod2.real, 130, 132)
586
587 def test_decorator_with_lambda(self):
588 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400589
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000590class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000591 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000592 def test_oneline_lambda(self):
593 # Test inspect.getsource with a one-line lambda function.
594 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000595
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000596 def test_threeline_lambda(self):
597 # Test inspect.getsource with a three-line lambda function,
598 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000599 self.assertSourceEqual(mod2.tll, 28, 30)
600
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000601 def test_twoline_indented_lambda(self):
602 # Test inspect.getsource with a two-line lambda function,
603 # where the second line _is_ indented.
604 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000605
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000606 def test_onelinefunc(self):
607 # Test inspect.getsource with a regular one-line function.
608 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000609
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000610 def test_manyargs(self):
611 # Test inspect.getsource with a regular function where
612 # the arguments are on two lines and _not_ indented and
613 # the body on the second line with the last arguments.
614 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000615
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000616 def test_twolinefunc(self):
617 # Test inspect.getsource with a regular function where
618 # the body is on two lines, following the argument list and
619 # continued on the next line by a \\.
620 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000621
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000622 def test_lambda_in_list(self):
623 # Test inspect.getsource with a one-line lambda function
624 # defined in a list, indented.
625 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000626
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000627 def test_anonymous(self):
628 # Test inspect.getsource with a lambda function defined
629 # as argument to another function.
630 self.assertSourceEqual(mod2.anonymous, 55, 55)
631
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000632class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000633 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000634
635 def test_with_comment(self):
636 self.assertSourceEqual(mod2.with_comment, 58, 59)
637
638 def test_multiline_sig(self):
639 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
640
Armin Rigodd5c0232005-09-25 11:45:45 +0000641 def test_nested_class(self):
642 self.assertSourceEqual(mod2.func69().func71, 71, 72)
643
644 def test_one_liner_followed_by_non_name(self):
645 self.assertSourceEqual(mod2.func77, 77, 77)
646
647 def test_one_liner_dedent_non_name(self):
648 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
649
650 def test_with_comment_instead_of_docstring(self):
651 self.assertSourceEqual(mod2.func88, 88, 90)
652
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000653 def test_method_in_dynamic_class(self):
654 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
655
R David Murray32562d72014-10-03 11:15:38 -0400656 # This should not skip for CPython, but might on a repackaged python where
657 # unicodedata is not an external module, or on pypy.
658 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
659 unicodedata.__file__.endswith('.py'),
660 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000661 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200662 self.assertRaises(OSError, inspect.getsource, unicodedata)
663 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000664
R. David Murraya1b37402010-06-17 02:04:29 +0000665 def test_findsource_code_in_linecache(self):
666 lines = ["x=1"]
667 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200668 self.assertRaises(OSError, inspect.findsource, co)
669 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000670 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200671 try:
672 self.assertEqual(inspect.findsource(co), (lines,0))
673 self.assertEqual(inspect.getsource(co), lines[0])
674 finally:
675 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000676
Ezio Melotti1b145922013-03-30 05:17:24 +0200677 def test_findsource_without_filename(self):
678 for fname in ['', '<string>']:
679 co = compile('x=1', fname, "exec")
680 self.assertRaises(IOError, inspect.findsource, co)
681 self.assertRaises(IOError, inspect.getsource, co)
682
Antoine Pitroua8723a02015-04-15 00:41:29 +0200683 def test_getsource_on_method(self):
684 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
685
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300686 def test_nested_func(self):
687 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
688
689
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000690class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400691 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000692 self.tempdir = TESTFN + '_dir'
693 os.mkdir(self.tempdir)
694 with open(os.path.join(self.tempdir,
695 'inspect_fodder3%spy' % os.extsep), 'w') as f:
696 f.write("class X:\n pass # No EOL")
697 with DirsOnSysPath(self.tempdir):
698 import inspect_fodder3 as mod3
699 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400700 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000701
702 def tearDown(self):
703 shutil.rmtree(self.tempdir)
704
705 def test_class(self):
706 self.assertSourceEqual(self.fodderModule.X, 1, 2)
707
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100708
709class _BrokenDataDescriptor(object):
710 """
711 A broken data descriptor. See bug #1785.
712 """
713 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700714 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100715
716 def __set__(*args):
717 raise RuntimeError
718
719 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700720 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100721
722
723class _BrokenMethodDescriptor(object):
724 """
725 A broken method descriptor. See bug #1785.
726 """
727 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700728 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100729
730 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700731 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100732
733
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000734# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000735def attrs_wo_objs(cls):
736 return [t[:3] for t in inspect.classify_class_attrs(cls)]
737
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100738
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000739class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000740 def test_newstyle_mro(self):
741 # The same w/ new-class MRO.
742 class A(object): pass
743 class B(A): pass
744 class C(A): pass
745 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000746
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000747 expected = (D, B, C, A, object)
748 got = inspect.getmro(D)
749 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000750
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500751 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
752 varkw_e=None, defaults_e=None, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100753 args, varargs, varkw, defaults = inspect.getargspec(routine)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500754 self.assertEqual(args, args_e)
755 self.assertEqual(varargs, varargs_e)
756 self.assertEqual(varkw, varkw_e)
757 self.assertEqual(defaults, defaults_e)
758 if formatted is not None:
Pablo Galindoaee19f52019-05-16 21:08:15 +0100759 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
760 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500761
Christian Heimes3795b532007-11-08 13:48:53 +0000762 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
763 varkw_e=None, defaults_e=None,
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100764 posonlyargs_e=[], kwonlyargs_e=[],
765 kwonlydefaults_e=None,
Christian Heimes3795b532007-11-08 13:48:53 +0000766 ann_e={}, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100767 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
768 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000769 self.assertEqual(args, args_e)
770 self.assertEqual(varargs, varargs_e)
771 self.assertEqual(varkw, varkw_e)
772 self.assertEqual(defaults, defaults_e)
773 self.assertEqual(kwonlyargs, kwonlyargs_e)
774 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
775 self.assertEqual(ann, ann_e)
776 if formatted is not None:
Pablo Galindoaee19f52019-05-16 21:08:15 +0100777 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
778 kwonlyargs, kwonlydefaults, ann),
Christian Heimes3795b532007-11-08 13:48:53 +0000779 formatted)
780
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500781 def test_getargspec(self):
782 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
783
Pablo Galindod5d2b452019-04-30 02:01:14 +0100784 self.assertArgSpecEquals(mod.spam,
785 ['a', 'b', 'c', 'd', 'e', 'f'],
786 'g', 'h', (3, 4, 5),
787 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500788
789 self.assertRaises(ValueError, self.assertArgSpecEquals,
790 mod2.keyworded, [])
791
792 self.assertRaises(ValueError, self.assertArgSpecEquals,
793 mod2.annotated, [])
794 self.assertRaises(ValueError, self.assertArgSpecEquals,
795 mod2.keyword_only_arg, [])
796
797
Christian Heimes3795b532007-11-08 13:48:53 +0000798 def test_getfullargspec(self):
799 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
800 kwonlyargs_e=['arg2'],
801 kwonlydefaults_e={'arg2':1},
802 formatted='(*arg1, arg2=1)')
803
804 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000805 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000806 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000807 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
808 kwonlyargs_e=['arg'],
809 formatted='(*, arg)')
810
Pablo Galindod5d2b452019-04-30 02:01:14 +0100811 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100812 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100813 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100814
815 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100816 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100817 varargs_e='args',
818 varkw_e='kwargs',
819 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100820 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100821
Pablo Galindod5d2b452019-04-30 02:01:14 +0100822 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100823 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100824 kwonlyargs_e=['e', 'f'],
825 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100826 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100827
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500828 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500829 # Issue 20684: low level introspection API must ignore __wrapped__
830 @functools.wraps(mod.spam)
831 def ham(x, y):
832 pass
833 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500834 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500835 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
836 self.assertFullArgSpecEquals(functools.partial(ham),
837 ['x', 'y'], formatted='(x, y)')
838 # Other variants
839 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500840 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
841 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500842 class C:
843 @functools.wraps(mod.spam)
844 def ham(self, x, y):
845 pass
846 pham = functools.partialmethod(ham)
847 @functools.wraps(mod.spam)
848 def __call__(self, x, y):
849 pass
850 check_method(C())
851 check_method(C.ham)
852 check_method(C().ham)
853 check_method(C.pham)
854 check_method(C().pham)
855
856 class C_new:
857 @functools.wraps(mod.spam)
858 def __new__(self, x, y):
859 pass
860 check_method(C_new)
861
862 class C_init:
863 @functools.wraps(mod.spam)
864 def __init__(self, x, y):
865 pass
866 check_method(C_init)
867
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500868 def test_getfullargspec_signature_attr(self):
869 def test():
870 pass
871 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
872 test.__signature__ = inspect.Signature(parameters=(spam_param,))
873
Pablo Galindod5d2b452019-04-30 02:01:14 +0100874 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500875
Yury Selivanov4cb93912014-01-29 11:54:12 -0500876 def test_getfullargspec_signature_annos(self):
877 def test(a:'spam') -> 'ham': pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100878 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500879 self.assertEqual(test.__annotations__, spec.annotations)
880
881 def test(): pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100882 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500883 self.assertEqual(test.__annotations__, spec.annotations)
884
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500885 @unittest.skipIf(MISSING_C_DOCSTRINGS,
886 "Signature information for builtins requires docstrings")
887 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100888 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
889 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500890
Pablo Galindod5d2b452019-04-30 02:01:14 +0100891 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
892 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500893
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500894 self.assertFullArgSpecEquals(
895 os.stat,
896 args_e=['path'],
897 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
898 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
899 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
900
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200901 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500902 @unittest.skipIf(MISSING_C_DOCSTRINGS,
903 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800904 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200905 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500906 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindoaee19f52019-05-16 21:08:15 +0100907 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500908 self.assertEqual(spec.defaults[0], 'avocado')
909
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200910 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500911 @unittest.skipIf(MISSING_C_DOCSTRINGS,
912 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800913 def test_getfullargspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200914 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500915 builtin = _testcapi.docstring_no_signature
Pablo Galindoaee19f52019-05-16 21:08:15 +0100916 with self.assertRaises(TypeError):
917 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000918
larryhastingsf36ba122018-01-28 11:13:09 -0800919 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
920 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindoaee19f52019-05-16 21:08:15 +0100921 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800922 l = list(signature.kwonlyargs)
923 sorted_l = sorted(l)
924 self.assertTrue(l)
925 self.assertEqual(l, sorted_l)
Pablo Galindoaee19f52019-05-16 21:08:15 +0100926 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800927 l = list(signature.kwonlyargs)
928 self.assertEqual(l, unsorted_keyword_only_parameters)
929
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500930 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000931 class A(object):
932 def m(self):
933 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500934 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000935
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000936 def test_classify_newstyle(self):
937 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000938
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000939 def s(): pass
940 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000941
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000942 def c(cls): pass
943 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000944
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000945 def getp(self): pass
946 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000947
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000948 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000949
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000950 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000951
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000952 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000953
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100954 dd = _BrokenDataDescriptor()
955 md = _BrokenMethodDescriptor()
956
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000957 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500958
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +0200959 self.assertIn(('__new__', 'static method', object), attrs,
960 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500961 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
962
Benjamin Peterson577473f2010-01-19 00:09:57 +0000963 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
964 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
965 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000966 self.assertIn(('m', 'method', A), attrs,
967 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000968 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
969 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100970 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
971 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000972
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000973 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000974
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000975 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000976
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000977 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000978 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
979 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
980 self.assertIn(('p', 'property', A), attrs, 'missing property')
981 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
982 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
983 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100984 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
985 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000986
987
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000988 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000989
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000990 def m(self): pass
991 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000992
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000993 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000994 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
995 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
996 self.assertIn(('p', 'property', A), attrs, 'missing property')
997 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
998 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
999 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001000 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1001 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001002
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001003 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001004
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001005 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001006
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001007 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001008 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1009 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1010 self.assertIn(('p', 'property', A), attrs, 'missing property')
1011 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1012 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1013 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001014 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1015 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1016
1017 def test_classify_builtin_types(self):
1018 # Simple sanity check that all built-in types can have their
1019 # attributes classified.
1020 for name in dir(__builtins__):
1021 builtin = getattr(__builtins__, name)
1022 if isinstance(builtin, type):
1023 inspect.classify_class_attrs(builtin)
1024
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001025 attrs = attrs_wo_objs(bool)
1026 self.assertIn(('__new__', 'static method', bool), attrs,
1027 'missing __new__')
1028 self.assertIn(('from_bytes', 'class method', int), attrs,
1029 'missing class method')
1030 self.assertIn(('to_bytes', 'method', int), attrs,
1031 'missing plain method')
1032 self.assertIn(('__add__', 'method', int), attrs,
1033 'missing plain method')
1034 self.assertIn(('__and__', 'method', bool), attrs,
1035 'missing plain method')
1036
Ethan Furman63c141c2013-10-18 00:27:39 -07001037 def test_classify_DynamicClassAttribute(self):
1038 class Meta(type):
1039 def __getattr__(self, name):
1040 if name == 'ham':
1041 return 'spam'
1042 return super().__getattr__(name)
1043 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001044 @types.DynamicClassAttribute
1045 def ham(self):
1046 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001047 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1048 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001049 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001050 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1051
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001052 def test_classify_overrides_bool(self):
1053 class NoBool(object):
1054 def __eq__(self, other):
1055 return NoBool()
1056
1057 def __bool__(self):
1058 raise NotImplementedError(
1059 "This object does not specify a boolean value")
1060
1061 class HasNB(object):
1062 dd = NoBool()
1063
1064 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1065 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1066
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001067 def test_classify_metaclass_class_attribute(self):
1068 class Meta(type):
1069 fish = 'slap'
1070 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001071 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001072 class Class(metaclass=Meta):
1073 pass
1074 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1075 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1076
Ethan Furman63c141c2013-10-18 00:27:39 -07001077 def test_classify_VirtualAttribute(self):
1078 class Meta(type):
1079 def __dir__(cls):
1080 return ['__class__', '__module__', '__name__', 'BOOM']
1081 def __getattr__(self, name):
1082 if name =='BOOM':
1083 return 42
1084 return super().__getattr(name)
1085 class Class(metaclass=Meta):
1086 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001087 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001088 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1089
1090 def test_classify_VirtualAttribute_multi_classes(self):
1091 class Meta1(type):
1092 def __dir__(cls):
1093 return ['__class__', '__module__', '__name__', 'one']
1094 def __getattr__(self, name):
1095 if name =='one':
1096 return 1
1097 return super().__getattr__(name)
1098 class Meta2(type):
1099 def __dir__(cls):
1100 return ['__class__', '__module__', '__name__', 'two']
1101 def __getattr__(self, name):
1102 if name =='two':
1103 return 2
1104 return super().__getattr__(name)
1105 class Meta3(Meta1, Meta2):
1106 def __dir__(cls):
1107 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1108 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1109 def __getattr__(self, name):
1110 if name =='three':
1111 return 3
1112 return super().__getattr__(name)
1113 class Class1(metaclass=Meta1):
1114 pass
1115 class Class2(Class1, metaclass=Meta3):
1116 pass
1117
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001118 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1119 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1120 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001121 cca = inspect.classify_class_attrs(Class2)
1122 for sf in (should_find1, should_find2, should_find3):
1123 self.assertIn(sf, cca)
1124
1125 def test_classify_class_attrs_with_buggy_dir(self):
1126 class M(type):
1127 def __dir__(cls):
1128 return ['__class__', '__name__', 'missing']
1129 class C(metaclass=M):
1130 pass
1131 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1132 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001133
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001134 def test_getmembers_descriptors(self):
1135 class A(object):
1136 dd = _BrokenDataDescriptor()
1137 md = _BrokenMethodDescriptor()
1138
1139 def pred_wrapper(pred):
1140 # A quick'n'dirty way to discard standard attributes of new-style
1141 # classes.
1142 class Empty(object):
1143 pass
1144 def wrapped(x):
1145 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1146 return False
1147 return pred(x)
1148 return wrapped
1149
1150 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1151 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1152
1153 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1154 [('md', A.__dict__['md'])])
1155 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1156 [('dd', A.__dict__['dd'])])
1157
1158 class B(A):
1159 pass
1160
1161 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1162 [('md', A.__dict__['md'])])
1163 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1164 [('dd', A.__dict__['dd'])])
1165
Antoine Pitrou0c603812012-01-18 17:40:18 +01001166 def test_getmembers_method(self):
1167 class B:
1168 def f(self):
1169 pass
1170
1171 self.assertIn(('f', B.f), inspect.getmembers(B))
1172 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1173 b = B()
1174 self.assertIn(('f', b.f), inspect.getmembers(b))
1175 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1176
Ethan Furmane03ea372013-09-25 07:14:41 -07001177 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001178 class M(type):
1179 def __getattr__(cls, name):
1180 if name == 'eggs':
1181 return 'scrambled'
1182 return super().__getattr__(name)
1183 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001184 @types.DynamicClassAttribute
1185 def eggs(self):
1186 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001187 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1188 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1189
1190 def test_getmembers_with_buggy_dir(self):
1191 class M(type):
1192 def __dir__(cls):
1193 return ['__class__', '__name__', 'missing']
1194 class C(metaclass=M):
1195 pass
1196 attrs = [a[0] for a in inspect.getmembers(C)]
1197 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001198
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001199class TestIsDataDescriptor(unittest.TestCase):
1200
1201 def test_custom_descriptors(self):
1202 class NonDataDescriptor:
1203 def __get__(self, value, type=None): pass
1204 class DataDescriptor0:
1205 def __set__(self, name, value): pass
1206 class DataDescriptor1:
1207 def __delete__(self, name): pass
1208 class DataDescriptor2:
1209 __set__ = None
1210 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1211 'class with only __get__ not a data descriptor')
1212 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1213 'class with __set__ is a data descriptor')
1214 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1215 'class with __delete__ is a data descriptor')
1216 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1217 'class with __set__ = None is a data descriptor')
1218
1219 def test_slot(self):
1220 class Slotted:
1221 __slots__ = 'foo',
1222 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1223 'a slot is a data descriptor')
1224
1225 def test_property(self):
1226 class Propertied:
1227 @property
1228 def a_property(self):
1229 pass
1230 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1231 'a property is a data descriptor')
1232
1233 def test_functions(self):
1234 class Test(object):
1235 def instance_method(self): pass
1236 @classmethod
1237 def class_method(cls): pass
1238 @staticmethod
1239 def static_method(): pass
1240 def function():
1241 pass
1242 a_lambda = lambda: None
1243 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1244 'a instance method is not a data descriptor')
1245 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1246 'a class method is not a data descriptor')
1247 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1248 'a static method is not a data descriptor')
1249 self.assertFalse(inspect.isdatadescriptor(function),
1250 'a function is not a data descriptor')
1251 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1252 'a lambda is not a data descriptor')
1253
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001254
Nick Coghlan2f92e542012-06-23 19:39:55 +10001255_global_ref = object()
1256class TestGetClosureVars(unittest.TestCase):
1257
1258 def test_name_resolution(self):
1259 # Basic test of the 4 different resolution mechanisms
1260 def f(nonlocal_ref):
1261 def g(local_ref):
1262 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1263 return g
1264 _arg = object()
1265 nonlocal_vars = {"nonlocal_ref": _arg}
1266 global_vars = {"_global_ref": _global_ref}
1267 builtin_vars = {"print": print}
1268 unbound_names = {"unbound_ref"}
1269 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1270 builtin_vars, unbound_names)
1271 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1272
1273 def test_generator_closure(self):
1274 def f(nonlocal_ref):
1275 def g(local_ref):
1276 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1277 yield
1278 return g
1279 _arg = object()
1280 nonlocal_vars = {"nonlocal_ref": _arg}
1281 global_vars = {"_global_ref": _global_ref}
1282 builtin_vars = {"print": print}
1283 unbound_names = {"unbound_ref"}
1284 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1285 builtin_vars, unbound_names)
1286 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1287
1288 def test_method_closure(self):
1289 class C:
1290 def f(self, nonlocal_ref):
1291 def g(local_ref):
1292 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1293 return g
1294 _arg = object()
1295 nonlocal_vars = {"nonlocal_ref": _arg}
1296 global_vars = {"_global_ref": _global_ref}
1297 builtin_vars = {"print": print}
1298 unbound_names = {"unbound_ref"}
1299 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1300 builtin_vars, unbound_names)
1301 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1302
1303 def test_nonlocal_vars(self):
1304 # More complex tests of nonlocal resolution
1305 def _nonlocal_vars(f):
1306 return inspect.getclosurevars(f).nonlocals
1307
1308 def make_adder(x):
1309 def add(y):
1310 return x + y
1311 return add
1312
1313 def curry(func, arg1):
1314 return lambda arg2: func(arg1, arg2)
1315
1316 def less_than(a, b):
1317 return a < b
1318
1319 # The infamous Y combinator.
1320 def Y(le):
1321 def g(f):
1322 return le(lambda x: f(f)(x))
1323 Y.g_ref = g
1324 return g(g)
1325
1326 def check_y_combinator(func):
1327 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1328
1329 inc = make_adder(1)
1330 add_two = make_adder(2)
1331 greater_than_five = curry(less_than, 5)
1332
1333 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1334 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1335 self.assertEqual(_nonlocal_vars(greater_than_five),
1336 {'arg1': 5, 'func': less_than})
1337 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1338 {'x': 3})
1339 Y(check_y_combinator)
1340
1341 def test_getclosurevars_empty(self):
1342 def foo(): pass
1343 _empty = inspect.ClosureVars({}, {}, {}, set())
1344 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1345 self.assertEqual(inspect.getclosurevars(foo), _empty)
1346
1347 def test_getclosurevars_error(self):
1348 class T: pass
1349 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1350 self.assertRaises(TypeError, inspect.getclosurevars, list)
1351 self.assertRaises(TypeError, inspect.getclosurevars, {})
1352
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001353 def _private_globals(self):
1354 code = """def f(): print(path)"""
1355 ns = {}
1356 exec(code, ns)
1357 return ns["f"], ns
1358
1359 def test_builtins_fallback(self):
1360 f, ns = self._private_globals()
1361 ns.pop("__builtins__", None)
1362 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1363 self.assertEqual(inspect.getclosurevars(f), expected)
1364
1365 def test_builtins_as_dict(self):
1366 f, ns = self._private_globals()
1367 ns["__builtins__"] = {"path":1}
1368 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1369 self.assertEqual(inspect.getclosurevars(f), expected)
1370
1371 def test_builtins_as_module(self):
1372 f, ns = self._private_globals()
1373 ns["__builtins__"] = os
1374 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1375 self.assertEqual(inspect.getclosurevars(f), expected)
1376
Nick Coghlan2f92e542012-06-23 19:39:55 +10001377
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001378class TestGetcallargsFunctions(unittest.TestCase):
1379
1380 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1381 locs = dict(locs or {}, func=func)
1382 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001383 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1384 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001385 self.assertEqual(r1, r2)
1386
1387 def assertEqualException(self, func, call_param_string, locs=None):
1388 locs = dict(locs or {}, func=func)
1389 try:
1390 eval('func(%s)' % call_param_string, None, locs)
1391 except Exception as e:
1392 ex1 = e
1393 else:
1394 self.fail('Exception not raised')
1395 try:
Pablo Galindoaee19f52019-05-16 21:08:15 +01001396 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1397 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001398 except Exception as e:
1399 ex2 = e
1400 else:
1401 self.fail('Exception not raised')
1402 self.assertIs(type(ex1), type(ex2))
1403 self.assertEqual(str(ex1), str(ex2))
1404 del ex1, ex2
1405
1406 def makeCallable(self, signature):
1407 """Create a function that returns its locals()"""
1408 code = "lambda %s: locals()"
1409 return eval(code % signature)
1410
1411 def test_plain(self):
1412 f = self.makeCallable('a, b=1')
1413 self.assertEqualCallArgs(f, '2')
1414 self.assertEqualCallArgs(f, '2, 3')
1415 self.assertEqualCallArgs(f, 'a=2')
1416 self.assertEqualCallArgs(f, 'b=3, a=2')
1417 self.assertEqualCallArgs(f, '2, b=3')
1418 # expand *iterable / **mapping
1419 self.assertEqualCallArgs(f, '*(2,)')
1420 self.assertEqualCallArgs(f, '*[2]')
1421 self.assertEqualCallArgs(f, '*(2, 3)')
1422 self.assertEqualCallArgs(f, '*[2, 3]')
1423 self.assertEqualCallArgs(f, '**{"a":2}')
1424 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1425 self.assertEqualCallArgs(f, '2, **{"b":3}')
1426 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1427 # expand UserList / UserDict
1428 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1429 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1430 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1431 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1432 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1433
1434 def test_varargs(self):
1435 f = self.makeCallable('a, b=1, *c')
1436 self.assertEqualCallArgs(f, '2')
1437 self.assertEqualCallArgs(f, '2, 3')
1438 self.assertEqualCallArgs(f, '2, 3, 4')
1439 self.assertEqualCallArgs(f, '*(2,3,4)')
1440 self.assertEqualCallArgs(f, '2, *[3,4]')
1441 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1442
1443 def test_varkw(self):
1444 f = self.makeCallable('a, b=1, **c')
1445 self.assertEqualCallArgs(f, 'a=2')
1446 self.assertEqualCallArgs(f, '2, b=3, c=4')
1447 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1448 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1449 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1450 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1451 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1452 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1453 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1454
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001455 def test_varkw_only(self):
1456 # issue11256:
1457 f = self.makeCallable('**c')
1458 self.assertEqualCallArgs(f, '')
1459 self.assertEqualCallArgs(f, 'a=1')
1460 self.assertEqualCallArgs(f, 'a=1, b=2')
1461 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1462 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1463 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1464
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001465 def test_keyword_only(self):
1466 f = self.makeCallable('a=3, *, c, d=2')
1467 self.assertEqualCallArgs(f, 'c=3')
1468 self.assertEqualCallArgs(f, 'c=3, a=3')
1469 self.assertEqualCallArgs(f, 'a=2, c=4')
1470 self.assertEqualCallArgs(f, '4, c=4')
1471 self.assertEqualException(f, '')
1472 self.assertEqualException(f, '3')
1473 self.assertEqualException(f, 'a=3')
1474 self.assertEqualException(f, 'd=4')
1475
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001476 f = self.makeCallable('*, c, d=2')
1477 self.assertEqualCallArgs(f, 'c=3')
1478 self.assertEqualCallArgs(f, 'c=3, d=4')
1479 self.assertEqualCallArgs(f, 'd=4, c=3')
1480
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001481 def test_multiple_features(self):
1482 f = self.makeCallable('a, b=2, *f, **g')
1483 self.assertEqualCallArgs(f, '2, 3, 7')
1484 self.assertEqualCallArgs(f, '2, 3, x=8')
1485 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1486 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1487 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1488 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1489 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1490 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1491 '(4,[5,6])]), **collections.UserDict('
1492 'y=9, z=10)')
1493
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001494 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1495 self.assertEqualCallArgs(f, '2, 3, x=8')
1496 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1497 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1498 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1499 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1500 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1501 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1502 '(4,[5,6])]), q=0, **collections.UserDict('
1503 'y=9, z=10)')
1504
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001505 def test_errors(self):
1506 f0 = self.makeCallable('')
1507 f1 = self.makeCallable('a, b')
1508 f2 = self.makeCallable('a, b=1')
1509 # f0 takes no arguments
1510 self.assertEqualException(f0, '1')
1511 self.assertEqualException(f0, 'x=1')
1512 self.assertEqualException(f0, '1,x=1')
1513 # f1 takes exactly 2 arguments
1514 self.assertEqualException(f1, '')
1515 self.assertEqualException(f1, '1')
1516 self.assertEqualException(f1, 'a=2')
1517 self.assertEqualException(f1, 'b=3')
1518 # f2 takes at least 1 argument
1519 self.assertEqualException(f2, '')
1520 self.assertEqualException(f2, 'b=3')
1521 for f in f1, f2:
1522 # f1/f2 takes exactly/at most 2 arguments
1523 self.assertEqualException(f, '2, 3, 4')
1524 self.assertEqualException(f, '1, 2, 3, a=1')
1525 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001526 # XXX: success of this one depends on dict order
1527 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001528 # f got an unexpected keyword argument
1529 self.assertEqualException(f, 'c=2')
1530 self.assertEqualException(f, '2, c=3')
1531 self.assertEqualException(f, '2, 3, c=4')
1532 self.assertEqualException(f, '2, c=4, b=3')
1533 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1534 # f got multiple values for keyword argument
1535 self.assertEqualException(f, '1, a=2')
1536 self.assertEqualException(f, '1, **{"a":2}')
1537 self.assertEqualException(f, '1, 2, b=3')
1538 # XXX: Python inconsistency
1539 # - for functions and bound methods: unexpected keyword 'c'
1540 # - for unbound methods: multiple values for keyword 'a'
1541 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001542 # issue11256:
1543 f3 = self.makeCallable('**c')
1544 self.assertEqualException(f3, '1, 2')
1545 self.assertEqualException(f3, '1, 2, a=1, b=2')
1546 f4 = self.makeCallable('*, a, b=0')
1547 self.assertEqualException(f3, '1, 2')
1548 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001549
Yury Selivanov875df202014-03-27 18:23:03 -04001550 # issue #20816: getcallargs() fails to iterate over non-existent
1551 # kwonlydefaults and raises a wrong TypeError
1552 def f5(*, a): pass
1553 with self.assertRaisesRegex(TypeError,
1554 'missing 1 required keyword-only'):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001555 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001556
1557
Yury Selivanovdccfa132014-03-27 18:42:52 -04001558 # issue20817:
1559 def f6(a, b, c):
1560 pass
1561 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001562 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001563
Dong-hee Naa9cab432018-05-30 00:04:08 +09001564 # bpo-33197
1565 with self.assertRaisesRegex(ValueError,
1566 'variadic keyword parameters cannot'
1567 ' have default values'):
1568 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1569 default=42)
1570 with self.assertRaisesRegex(ValueError,
1571 "value 5 is not a valid Parameter.kind"):
1572 inspect.Parameter("bar", kind=5, default=42)
1573
1574 with self.assertRaisesRegex(TypeError,
1575 'name must be a str, not a int'):
1576 inspect.Parameter(123, kind=4)
1577
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001578class TestGetcallargsMethods(TestGetcallargsFunctions):
1579
1580 def setUp(self):
1581 class Foo(object):
1582 pass
1583 self.cls = Foo
1584 self.inst = Foo()
1585
1586 def makeCallable(self, signature):
1587 assert 'self' not in signature
1588 mk = super(TestGetcallargsMethods, self).makeCallable
1589 self.cls.method = mk('self, ' + signature)
1590 return self.inst.method
1591
1592class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1593
1594 def makeCallable(self, signature):
1595 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1596 return self.cls.method
1597
1598 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1599 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1600 *self._getAssertEqualParams(func, call_params_string, locs))
1601
1602 def assertEqualException(self, func, call_params_string, locs=None):
1603 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1604 *self._getAssertEqualParams(func, call_params_string, locs))
1605
1606 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1607 assert 'inst' not in call_params_string
1608 locs = dict(locs or {}, inst=self.inst)
1609 return (func, 'inst,' + call_params_string, locs)
1610
Michael Foord95fc51d2010-11-20 15:07:30 +00001611
1612class TestGetattrStatic(unittest.TestCase):
1613
1614 def test_basic(self):
1615 class Thing(object):
1616 x = object()
1617
1618 thing = Thing()
1619 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1620 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1621 with self.assertRaises(AttributeError):
1622 inspect.getattr_static(thing, 'y')
1623
1624 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1625
1626 def test_inherited(self):
1627 class Thing(object):
1628 x = object()
1629 class OtherThing(Thing):
1630 pass
1631
1632 something = OtherThing()
1633 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1634
1635 def test_instance_attr(self):
1636 class Thing(object):
1637 x = 2
1638 def __init__(self, x):
1639 self.x = x
1640 thing = Thing(3)
1641 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1642 del thing.x
1643 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1644
1645 def test_property(self):
1646 class Thing(object):
1647 @property
1648 def x(self):
1649 raise AttributeError("I'm pretending not to exist")
1650 thing = Thing()
1651 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1652
Ezio Melotti75cbd732011-04-28 00:59:29 +03001653 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001654 class descriptor(object):
1655 def __get__(*_):
1656 raise AttributeError("I'm pretending not to exist")
1657 desc = descriptor()
1658 class Thing(object):
1659 x = desc
1660 thing = Thing()
1661 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1662
1663 def test_classAttribute(self):
1664 class Thing(object):
1665 x = object()
1666
1667 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1668
Ethan Furmane03ea372013-09-25 07:14:41 -07001669 def test_classVirtualAttribute(self):
1670 class Thing(object):
1671 @types.DynamicClassAttribute
1672 def x(self):
1673 return self._x
1674 _x = object()
1675
1676 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1677
Michael Foord95fc51d2010-11-20 15:07:30 +00001678 def test_inherited_classattribute(self):
1679 class Thing(object):
1680 x = object()
1681 class OtherThing(Thing):
1682 pass
1683
1684 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1685
1686 def test_slots(self):
1687 class Thing(object):
1688 y = 'bar'
1689 __slots__ = ['x']
1690 def __init__(self):
1691 self.x = 'foo'
1692 thing = Thing()
1693 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1694 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1695
1696 del thing.x
1697 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1698
1699 def test_metaclass(self):
1700 class meta(type):
1701 attr = 'foo'
1702 class Thing(object, metaclass=meta):
1703 pass
1704 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1705
1706 class sub(meta):
1707 pass
1708 class OtherThing(object, metaclass=sub):
1709 x = 3
1710 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1711
1712 class OtherOtherThing(OtherThing):
1713 pass
1714 # this test is odd, but it was added as it exposed a bug
1715 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1716
1717 def test_no_dict_no_slots(self):
1718 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1719 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1720
1721 def test_no_dict_no_slots_instance_member(self):
1722 # returns descriptor
1723 with open(__file__) as handle:
1724 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1725
1726 def test_inherited_slots(self):
1727 # returns descriptor
1728 class Thing(object):
1729 __slots__ = ['x']
1730 def __init__(self):
1731 self.x = 'foo'
1732
1733 class OtherThing(Thing):
1734 pass
1735 # it would be nice if this worked...
1736 # we get the descriptor instead of the instance attribute
1737 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1738
1739 def test_descriptor(self):
1740 class descriptor(object):
1741 def __get__(self, instance, owner):
1742 return 3
1743 class Foo(object):
1744 d = descriptor()
1745
1746 foo = Foo()
1747
1748 # for a non data descriptor we return the instance attribute
1749 foo.__dict__['d'] = 1
1750 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1751
Mike53f7a7c2017-12-14 14:04:53 +03001752 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001753 # descriptor
1754 descriptor.__set__ = lambda s, i, v: None
1755 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1756
1757
1758 def test_metaclass_with_descriptor(self):
1759 class descriptor(object):
1760 def __get__(self, instance, owner):
1761 return 3
1762 class meta(type):
1763 d = descriptor()
1764 class Thing(object, metaclass=meta):
1765 pass
1766 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1767
1768
Michael Foordcc7ebb82010-11-20 16:20:16 +00001769 def test_class_as_property(self):
1770 class Base(object):
1771 foo = 3
1772
1773 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001774 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001775 @property
1776 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001777 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001778 return object
1779
Michael Foord35184ed2010-11-20 16:58:30 +00001780 instance = Something()
1781 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1782 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001783 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1784
Michael Foorde5162652010-11-20 16:40:44 +00001785 def test_mro_as_property(self):
1786 class Meta(type):
1787 @property
1788 def __mro__(self):
1789 return (object,)
1790
1791 class Base(object):
1792 foo = 3
1793
1794 class Something(Base, metaclass=Meta):
1795 pass
1796
1797 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1798 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1799
Michael Foorddcebe0f2011-03-15 19:20:44 -04001800 def test_dict_as_property(self):
1801 test = self
1802 test.called = False
1803
1804 class Foo(dict):
1805 a = 3
1806 @property
1807 def __dict__(self):
1808 test.called = True
1809 return {}
1810
1811 foo = Foo()
1812 foo.a = 4
1813 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1814 self.assertFalse(test.called)
1815
1816 def test_custom_object_dict(self):
1817 test = self
1818 test.called = False
1819
1820 class Custom(dict):
1821 def get(self, key, default=None):
1822 test.called = True
1823 super().get(key, default)
1824
1825 class Foo(object):
1826 a = 3
1827 foo = Foo()
1828 foo.__dict__ = Custom()
1829 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1830 self.assertFalse(test.called)
1831
1832 def test_metaclass_dict_as_property(self):
1833 class Meta(type):
1834 @property
1835 def __dict__(self):
1836 self.executed = True
1837
1838 class Thing(metaclass=Meta):
1839 executed = False
1840
1841 def __init__(self):
1842 self.spam = 42
1843
1844 instance = Thing()
1845 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1846 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001847
Michael Foorda51623b2011-12-18 22:01:40 +00001848 def test_module(self):
1849 sentinel = object()
1850 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1851 sentinel)
1852
Michael Foord3ba95f82011-12-22 01:13:37 +00001853 def test_metaclass_with_metaclass_with_dict_as_property(self):
1854 class MetaMeta(type):
1855 @property
1856 def __dict__(self):
1857 self.executed = True
1858 return dict(spam=42)
1859
1860 class Meta(type, metaclass=MetaMeta):
1861 executed = False
1862
1863 class Thing(metaclass=Meta):
1864 pass
1865
1866 with self.assertRaises(AttributeError):
1867 inspect.getattr_static(Thing, "spam")
1868 self.assertFalse(Thing.executed)
1869
Nick Coghlane0f04652010-11-21 03:44:04 +00001870class TestGetGeneratorState(unittest.TestCase):
1871
1872 def setUp(self):
1873 def number_generator():
1874 for number in range(5):
1875 yield number
1876 self.generator = number_generator()
1877
1878 def _generatorstate(self):
1879 return inspect.getgeneratorstate(self.generator)
1880
1881 def test_created(self):
1882 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1883
1884 def test_suspended(self):
1885 next(self.generator)
1886 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1887
1888 def test_closed_after_exhaustion(self):
1889 for i in self.generator:
1890 pass
1891 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1892
1893 def test_closed_after_immediate_exception(self):
1894 with self.assertRaises(RuntimeError):
1895 self.generator.throw(RuntimeError)
1896 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1897
1898 def test_running(self):
1899 # As mentioned on issue #10220, checking for the RUNNING state only
1900 # makes sense inside the generator itself.
1901 # The following generator checks for this by using the closure's
1902 # reference to self and the generator state checking helper method
1903 def running_check_generator():
1904 for number in range(5):
1905 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1906 yield number
1907 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1908 self.generator = running_check_generator()
1909 # Running up to the first yield
1910 next(self.generator)
1911 # Running after the first yield
1912 next(self.generator)
1913
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001914 def test_easy_debugging(self):
1915 # repr() and str() of a generator state should contain the state name
1916 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1917 for name in names:
1918 state = getattr(inspect, name)
1919 self.assertIn(name, repr(state))
1920 self.assertIn(name, str(state))
1921
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001922 def test_getgeneratorlocals(self):
1923 def each(lst, a=None):
1924 b=(1, 2, 3)
1925 for v in lst:
1926 if v == 3:
1927 c = 12
1928 yield v
1929
1930 numbers = each([1, 2, 3])
1931 self.assertEqual(inspect.getgeneratorlocals(numbers),
1932 {'a': None, 'lst': [1, 2, 3]})
1933 next(numbers)
1934 self.assertEqual(inspect.getgeneratorlocals(numbers),
1935 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1936 'b': (1, 2, 3)})
1937 next(numbers)
1938 self.assertEqual(inspect.getgeneratorlocals(numbers),
1939 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1940 'b': (1, 2, 3)})
1941 next(numbers)
1942 self.assertEqual(inspect.getgeneratorlocals(numbers),
1943 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1944 'b': (1, 2, 3), 'c': 12})
1945 try:
1946 next(numbers)
1947 except StopIteration:
1948 pass
1949 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1950
1951 def test_getgeneratorlocals_empty(self):
1952 def yield_one():
1953 yield 1
1954 one = yield_one()
1955 self.assertEqual(inspect.getgeneratorlocals(one), {})
1956 try:
1957 next(one)
1958 except StopIteration:
1959 pass
1960 self.assertEqual(inspect.getgeneratorlocals(one), {})
1961
1962 def test_getgeneratorlocals_error(self):
1963 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1964 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1965 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1966 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1967
Nick Coghlane0f04652010-11-21 03:44:04 +00001968
Yury Selivanov5376ba92015-06-22 12:19:30 -04001969class TestGetCoroutineState(unittest.TestCase):
1970
1971 def setUp(self):
1972 @types.coroutine
1973 def number_coroutine():
1974 for number in range(5):
1975 yield number
1976 async def coroutine():
1977 await number_coroutine()
1978 self.coroutine = coroutine()
1979
1980 def tearDown(self):
1981 self.coroutine.close()
1982
1983 def _coroutinestate(self):
1984 return inspect.getcoroutinestate(self.coroutine)
1985
1986 def test_created(self):
1987 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1988
1989 def test_suspended(self):
1990 self.coroutine.send(None)
1991 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1992
1993 def test_closed_after_exhaustion(self):
1994 while True:
1995 try:
1996 self.coroutine.send(None)
1997 except StopIteration:
1998 break
1999
2000 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2001
2002 def test_closed_after_immediate_exception(self):
2003 with self.assertRaises(RuntimeError):
2004 self.coroutine.throw(RuntimeError)
2005 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2006
2007 def test_easy_debugging(self):
2008 # repr() and str() of a coroutine state should contain the state name
2009 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2010 for name in names:
2011 state = getattr(inspect, name)
2012 self.assertIn(name, repr(state))
2013 self.assertIn(name, str(state))
2014
2015 def test_getcoroutinelocals(self):
2016 @types.coroutine
2017 def gencoro():
2018 yield
2019
2020 gencoro = gencoro()
2021 async def func(a=None):
2022 b = 'spam'
2023 await gencoro
2024
2025 coro = func()
2026 self.assertEqual(inspect.getcoroutinelocals(coro),
2027 {'a': None, 'gencoro': gencoro})
2028 coro.send(None)
2029 self.assertEqual(inspect.getcoroutinelocals(coro),
2030 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2031
2032
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002033class MySignature(inspect.Signature):
2034 # Top-level to make it picklable;
2035 # used in test_signature_object_pickle
2036 pass
2037
2038class MyParameter(inspect.Parameter):
2039 # Top-level to make it picklable;
2040 # used in test_signature_object_pickle
2041 pass
2042
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002043
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002044
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002045class TestSignatureObject(unittest.TestCase):
2046 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002047 def signature(func, **kw):
2048 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002049 return (tuple((param.name,
2050 (... if param.default is param.empty else param.default),
2051 (... if param.annotation is param.empty
2052 else param.annotation),
2053 str(param.kind).lower())
2054 for param in sig.parameters.values()),
2055 (... if sig.return_annotation is sig.empty
2056 else sig.return_annotation))
2057
2058 def test_signature_object(self):
2059 S = inspect.Signature
2060 P = inspect.Parameter
2061
2062 self.assertEqual(str(S()), '()')
2063
Yury Selivanov07a9e452014-01-29 10:58:16 -05002064 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002065 pass
2066 sig = inspect.signature(test)
2067 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002068 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002069 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002070 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002071 args = sig.parameters['args']
2072 ko = sig.parameters['ko']
2073 kwargs = sig.parameters['kwargs']
2074
2075 S((po, pk, args, ko, kwargs))
2076
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002077 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002078 S((pk, po, args, ko, kwargs))
2079
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002080 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002081 S((po, args, pk, ko, kwargs))
2082
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002083 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002084 S((args, po, pk, ko, kwargs))
2085
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002086 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002087 S((po, pk, args, kwargs, ko))
2088
2089 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002090 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002091 S((po, pk, args, kwargs2, ko))
2092
Yury Selivanov07a9e452014-01-29 10:58:16 -05002093 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2094 S((pod, po))
2095
2096 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2097 S((po, pkd, pk))
2098
2099 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2100 S((pkd, pk))
2101
Yury Selivanov374375d2014-03-27 12:41:53 -04002102 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002103 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002104
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002105 def test_signature_object_pickle(self):
2106 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2107 foo_partial = functools.partial(foo, a=1)
2108
2109 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002110
2111 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2112 with self.subTest(pickle_ver=ver, subclass=False):
2113 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2114 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002115
2116 # Test that basic sub-classing works
2117 sig = inspect.signature(foo)
2118 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2119 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2120 mysig = MySignature().replace(parameters=myparams.values(),
2121 return_annotation=sig.return_annotation)
2122 self.assertTrue(isinstance(mysig, MySignature))
2123 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2124
2125 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2126 with self.subTest(pickle_ver=ver, subclass=True):
2127 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2128 self.assertEqual(mysig, sig_pickled)
2129 self.assertTrue(isinstance(sig_pickled, MySignature))
2130 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2131 MyParameter))
2132
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002133 def test_signature_immutability(self):
2134 def test(a):
2135 pass
2136 sig = inspect.signature(test)
2137
2138 with self.assertRaises(AttributeError):
2139 sig.foo = 'bar'
2140
2141 with self.assertRaises(TypeError):
2142 sig.parameters['a'] = None
2143
2144 def test_signature_on_noarg(self):
2145 def test():
2146 pass
2147 self.assertEqual(self.signature(test), ((), ...))
2148
2149 def test_signature_on_wargs(self):
2150 def test(a, b:'foo') -> 123:
2151 pass
2152 self.assertEqual(self.signature(test),
2153 ((('a', ..., ..., "positional_or_keyword"),
2154 ('b', ..., 'foo', "positional_or_keyword")),
2155 123))
2156
2157 def test_signature_on_wkwonly(self):
2158 def test(*, a:float, b:str) -> int:
2159 pass
2160 self.assertEqual(self.signature(test),
2161 ((('a', ..., float, "keyword_only"),
2162 ('b', ..., str, "keyword_only")),
2163 int))
2164
2165 def test_signature_on_complex_args(self):
2166 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2167 pass
2168 self.assertEqual(self.signature(test),
2169 ((('a', ..., ..., "positional_or_keyword"),
2170 ('b', 10, 'foo', "positional_or_keyword"),
2171 ('args', ..., 'bar', "var_positional"),
2172 ('spam', ..., 'baz', "keyword_only"),
2173 ('ham', 123, ..., "keyword_only"),
2174 ('kwargs', ..., int, "var_keyword")),
2175 ...))
2176
Dong-hee Na378d7062017-05-18 04:00:51 +09002177 def test_signature_without_self(self):
2178 def test_args_only(*args): # NOQA
2179 pass
2180
2181 def test_args_kwargs_only(*args, **kwargs): # NOQA
2182 pass
2183
2184 class A:
2185 @classmethod
2186 def test_classmethod(*args): # NOQA
2187 pass
2188
2189 @staticmethod
2190 def test_staticmethod(*args): # NOQA
2191 pass
2192
2193 f1 = functools.partialmethod((test_classmethod), 1)
2194 f2 = functools.partialmethod((test_args_only), 1)
2195 f3 = functools.partialmethod((test_staticmethod), 1)
2196 f4 = functools.partialmethod((test_args_kwargs_only),1)
2197
2198 self.assertEqual(self.signature(test_args_only),
2199 ((('args', ..., ..., 'var_positional'),), ...))
2200 self.assertEqual(self.signature(test_args_kwargs_only),
2201 ((('args', ..., ..., 'var_positional'),
2202 ('kwargs', ..., ..., 'var_keyword')), ...))
2203 self.assertEqual(self.signature(A.f1),
2204 ((('args', ..., ..., 'var_positional'),), ...))
2205 self.assertEqual(self.signature(A.f2),
2206 ((('args', ..., ..., 'var_positional'),), ...))
2207 self.assertEqual(self.signature(A.f3),
2208 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002209 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002210 ((('args', ..., ..., 'var_positional'),
2211 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002212 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002213 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2214 "Signature information for builtins requires docstrings")
2215 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002216 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002217
Larry Hastings5c661892014-01-24 06:17:25 -08002218 def test_unbound_method(o):
2219 """Use this to test unbound methods (things that should have a self)"""
2220 signature = inspect.signature(o)
2221 self.assertTrue(isinstance(signature, inspect.Signature))
2222 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2223 return signature
2224
2225 def test_callable(o):
2226 """Use this to test bound methods or normal callables (things that don't expect self)"""
2227 signature = inspect.signature(o)
2228 self.assertTrue(isinstance(signature, inspect.Signature))
2229 if signature.parameters:
2230 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2231 return signature
2232
2233 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002234 def p(name): return signature.parameters[name].default
2235 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002236 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002237 self.assertEqual(p('d'), 3.14)
2238 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002239 self.assertEqual(p('n'), None)
2240 self.assertEqual(p('t'), True)
2241 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002242 self.assertEqual(p('local'), 3)
2243 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002244 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002245
Larry Hastings5c661892014-01-24 06:17:25 -08002246 test_callable(object)
2247
2248 # normal method
2249 # (PyMethodDescr_Type, "method_descriptor")
2250 test_unbound_method(_pickle.Pickler.dump)
2251 d = _pickle.Pickler(io.StringIO())
2252 test_callable(d.dump)
2253
2254 # static method
2255 test_callable(str.maketrans)
2256 test_callable('abc'.maketrans)
2257
2258 # class method
2259 test_callable(dict.fromkeys)
2260 test_callable({}.fromkeys)
2261
2262 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2263 test_unbound_method(type.__call__)
2264 test_unbound_method(int.__add__)
2265 test_callable((3).__add__)
2266
2267 # _PyMethodWrapper_Type
2268 # support for 'method-wrapper'
2269 test_callable(min.__call__)
2270
Larry Hastings2623c8c2014-02-08 22:15:29 -08002271 # This doesn't work now.
2272 # (We don't have a valid signature for "type" in 3.4)
2273 with self.assertRaisesRegex(ValueError, "no signature found"):
2274 class ThisWorksNow:
2275 __call__ = type
2276 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002277
Yury Selivanov056e2652014-03-02 12:25:27 -05002278 # Regression test for issue #20786
2279 test_unbound_method(dict.__delitem__)
2280 test_unbound_method(property.__delete__)
2281
Zachary Ware8ef887c2015-04-13 18:22:35 -05002282 # Regression test for issue #20586
2283 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2284
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002285 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002286 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2287 "Signature information for builtins requires docstrings")
2288 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002289 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002290 func = _testcapi.docstring_with_signature_with_defaults
2291
2292 def decorator(func):
2293 @functools.wraps(func)
2294 def wrapper(*args, **kwargs) -> int:
2295 return func(*args, **kwargs)
2296 return wrapper
2297
2298 decorated_func = decorator(func)
2299
2300 self.assertEqual(inspect.signature(func),
2301 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002302
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002303 def wrapper_like(*args, **kwargs) -> int: pass
2304 self.assertEqual(inspect.signature(decorated_func,
2305 follow_wrapped=False),
2306 inspect.signature(wrapper_like))
2307
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002308 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002309 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002310 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002311 with self.assertRaisesRegex(ValueError,
2312 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002313 inspect.signature(_testcapi.docstring_no_signature)
2314
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002315 with self.assertRaisesRegex(ValueError,
2316 'no signature found for builtin'):
2317 inspect.signature(str)
2318
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002319 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002320 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002321 inspect.signature(42)
2322
Yury Selivanov63da7c72014-01-31 14:48:37 -05002323 def test_signature_from_functionlike_object(self):
2324 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2325 pass
2326
2327 class funclike:
2328 # Has to be callable, and have correct
2329 # __code__, __annotations__, __defaults__, __name__,
2330 # and __kwdefaults__ attributes
2331
2332 def __init__(self, func):
2333 self.__name__ = func.__name__
2334 self.__code__ = func.__code__
2335 self.__annotations__ = func.__annotations__
2336 self.__defaults__ = func.__defaults__
2337 self.__kwdefaults__ = func.__kwdefaults__
2338 self.func = func
2339
2340 def __call__(self, *args, **kwargs):
2341 return self.func(*args, **kwargs)
2342
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002343 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002344
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002345 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002346 self.assertEqual(sig_funclike, sig_func)
2347
2348 sig_funclike = inspect.signature(funclike(func))
2349 self.assertEqual(sig_funclike, sig_func)
2350
2351 # If object is not a duck type of function, then
2352 # signature will try to get a signature for its '__call__'
2353 # method
2354 fl = funclike(func)
2355 del fl.__defaults__
2356 self.assertEqual(self.signature(fl),
2357 ((('args', ..., ..., "var_positional"),
2358 ('kwargs', ..., ..., "var_keyword")),
2359 ...))
2360
Yury Selivanova773de02014-02-21 18:30:53 -05002361 # Test with cython-like builtins:
2362 _orig_isdesc = inspect.ismethoddescriptor
2363 def _isdesc(obj):
2364 if hasattr(obj, '_builtinmock'):
2365 return True
2366 return _orig_isdesc(obj)
2367
2368 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2369 builtin_func = funclike(func)
2370 # Make sure that our mock setup is working
2371 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2372 builtin_func._builtinmock = True
2373 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2374 self.assertEqual(inspect.signature(builtin_func), sig_func)
2375
Yury Selivanov63da7c72014-01-31 14:48:37 -05002376 def test_signature_functionlike_class(self):
2377 # We only want to duck type function-like objects,
2378 # not classes.
2379
2380 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2381 pass
2382
2383 class funclike:
2384 def __init__(self, marker):
2385 pass
2386
2387 __name__ = func.__name__
2388 __code__ = func.__code__
2389 __annotations__ = func.__annotations__
2390 __defaults__ = func.__defaults__
2391 __kwdefaults__ = func.__kwdefaults__
2392
Yury Selivanov63da7c72014-01-31 14:48:37 -05002393 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2394
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002395 def test_signature_on_method(self):
2396 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002397 def __init__(*args):
2398 pass
2399 def m1(self, arg1, arg2=1) -> int:
2400 pass
2401 def m2(*args):
2402 pass
2403 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002404 pass
2405
Yury Selivanov62560fb2014-01-28 12:26:24 -05002406 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002407 ((('arg1', ..., ..., "positional_or_keyword"),
2408 ('arg2', 1, ..., "positional_or_keyword")),
2409 int))
2410
Yury Selivanov62560fb2014-01-28 12:26:24 -05002411 self.assertEqual(self.signature(Test().m2),
2412 ((('args', ..., ..., "var_positional"),),
2413 ...))
2414
2415 self.assertEqual(self.signature(Test),
2416 ((('args', ..., ..., "var_positional"),),
2417 ...))
2418
2419 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2420 self.signature(Test())
2421
Yury Selivanov46c759d2015-05-27 21:56:53 -04002422 def test_signature_wrapped_bound_method(self):
2423 # Issue 24298
2424 class Test:
2425 def m1(self, arg1, arg2=1) -> int:
2426 pass
2427 @functools.wraps(Test().m1)
2428 def m1d(*args, **kwargs):
2429 pass
2430 self.assertEqual(self.signature(m1d),
2431 ((('arg1', ..., ..., "positional_or_keyword"),
2432 ('arg2', 1, ..., "positional_or_keyword")),
2433 int))
2434
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002435 def test_signature_on_classmethod(self):
2436 class Test:
2437 @classmethod
2438 def foo(cls, arg1, *, arg2=1):
2439 pass
2440
2441 meth = Test().foo
2442 self.assertEqual(self.signature(meth),
2443 ((('arg1', ..., ..., "positional_or_keyword"),
2444 ('arg2', 1, ..., "keyword_only")),
2445 ...))
2446
2447 meth = Test.foo
2448 self.assertEqual(self.signature(meth),
2449 ((('arg1', ..., ..., "positional_or_keyword"),
2450 ('arg2', 1, ..., "keyword_only")),
2451 ...))
2452
2453 def test_signature_on_staticmethod(self):
2454 class Test:
2455 @staticmethod
2456 def foo(cls, *, arg):
2457 pass
2458
2459 meth = Test().foo
2460 self.assertEqual(self.signature(meth),
2461 ((('cls', ..., ..., "positional_or_keyword"),
2462 ('arg', ..., ..., "keyword_only")),
2463 ...))
2464
2465 meth = Test.foo
2466 self.assertEqual(self.signature(meth),
2467 ((('cls', ..., ..., "positional_or_keyword"),
2468 ('arg', ..., ..., "keyword_only")),
2469 ...))
2470
2471 def test_signature_on_partial(self):
2472 from functools import partial
2473
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002474 Parameter = inspect.Parameter
2475
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002476 def test():
2477 pass
2478
2479 self.assertEqual(self.signature(partial(test)), ((), ...))
2480
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002481 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002482 inspect.signature(partial(test, 1))
2483
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002484 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002485 inspect.signature(partial(test, a=1))
2486
2487 def test(a, b, *, c, d):
2488 pass
2489
2490 self.assertEqual(self.signature(partial(test)),
2491 ((('a', ..., ..., "positional_or_keyword"),
2492 ('b', ..., ..., "positional_or_keyword"),
2493 ('c', ..., ..., "keyword_only"),
2494 ('d', ..., ..., "keyword_only")),
2495 ...))
2496
2497 self.assertEqual(self.signature(partial(test, 1)),
2498 ((('b', ..., ..., "positional_or_keyword"),
2499 ('c', ..., ..., "keyword_only"),
2500 ('d', ..., ..., "keyword_only")),
2501 ...))
2502
2503 self.assertEqual(self.signature(partial(test, 1, c=2)),
2504 ((('b', ..., ..., "positional_or_keyword"),
2505 ('c', 2, ..., "keyword_only"),
2506 ('d', ..., ..., "keyword_only")),
2507 ...))
2508
2509 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2510 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002511 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002512 ('c', 2, ..., "keyword_only"),
2513 ('d', ..., ..., "keyword_only")),
2514 ...))
2515
2516 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002517 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002518 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002519 ('d', ..., ..., "keyword_only")),
2520 ...))
2521
2522 self.assertEqual(self.signature(partial(test, a=1)),
2523 ((('a', 1, ..., "keyword_only"),
2524 ('b', ..., ..., "keyword_only"),
2525 ('c', ..., ..., "keyword_only"),
2526 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002527 ...))
2528
2529 def test(a, *args, b, **kwargs):
2530 pass
2531
2532 self.assertEqual(self.signature(partial(test, 1)),
2533 ((('args', ..., ..., "var_positional"),
2534 ('b', ..., ..., "keyword_only"),
2535 ('kwargs', ..., ..., "var_keyword")),
2536 ...))
2537
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002538 self.assertEqual(self.signature(partial(test, a=1)),
2539 ((('a', 1, ..., "keyword_only"),
2540 ('b', ..., ..., "keyword_only"),
2541 ('kwargs', ..., ..., "var_keyword")),
2542 ...))
2543
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002544 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2545 ((('args', ..., ..., "var_positional"),
2546 ('b', ..., ..., "keyword_only"),
2547 ('kwargs', ..., ..., "var_keyword")),
2548 ...))
2549
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002550 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2551 ((('args', ..., ..., "var_positional"),
2552 ('b', ..., ..., "keyword_only"),
2553 ('kwargs', ..., ..., "var_keyword")),
2554 ...))
2555
2556 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2557 ((('args', ..., ..., "var_positional"),
2558 ('b', 0, ..., "keyword_only"),
2559 ('kwargs', ..., ..., "var_keyword")),
2560 ...))
2561
2562 self.assertEqual(self.signature(partial(test, b=0)),
2563 ((('a', ..., ..., "positional_or_keyword"),
2564 ('args', ..., ..., "var_positional"),
2565 ('b', 0, ..., "keyword_only"),
2566 ('kwargs', ..., ..., "var_keyword")),
2567 ...))
2568
2569 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2570 ((('a', ..., ..., "positional_or_keyword"),
2571 ('args', ..., ..., "var_positional"),
2572 ('b', 0, ..., "keyword_only"),
2573 ('kwargs', ..., ..., "var_keyword")),
2574 ...))
2575
2576 def test(a, b, c:int) -> 42:
2577 pass
2578
2579 sig = test.__signature__ = inspect.signature(test)
2580
2581 self.assertEqual(self.signature(partial(partial(test, 1))),
2582 ((('b', ..., ..., "positional_or_keyword"),
2583 ('c', ..., int, "positional_or_keyword")),
2584 42))
2585
2586 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2587 ((('c', ..., int, "positional_or_keyword"),),
2588 42))
2589
2590 psig = inspect.signature(partial(partial(test, 1), 2))
2591
2592 def foo(a):
2593 return a
2594 _foo = partial(partial(foo, a=10), a=20)
2595 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002596 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002597 ...))
2598 # check that we don't have any side-effects in signature(),
2599 # and the partial object is still functioning
2600 self.assertEqual(_foo(), 20)
2601
2602 def foo(a, b, c):
2603 return a, b, c
2604 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002605
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002606 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002607 ((('b', 30, ..., "keyword_only"),
2608 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002609 ...))
2610 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002611
2612 def foo(a, b, c, *, d):
2613 return a, b, c, d
2614 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2615 self.assertEqual(self.signature(_foo),
2616 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002617 ('b', 10, ..., "keyword_only"),
2618 ('c', 20, ..., "keyword_only"),
2619 ('d', 30, ..., "keyword_only"),
2620 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002621 ...))
2622 ba = inspect.signature(_foo).bind(a=200, b=11)
2623 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2624
2625 def foo(a=1, b=2, c=3):
2626 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002627 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2628
2629 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002630 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002631
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002632 ba = inspect.signature(_foo).bind(11, 12)
2633 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002634
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002635 ba = inspect.signature(_foo).bind(11, b=12)
2636 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002637
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002638 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002639 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2640
2641 _foo = partial(_foo, b=10, c=20)
2642 ba = inspect.signature(_foo).bind(12)
2643 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2644
2645
2646 def foo(a, b, c, d, **kwargs):
2647 pass
2648 sig = inspect.signature(foo)
2649 params = sig.parameters.copy()
2650 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2651 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2652 foo.__signature__ = inspect.Signature(params.values())
2653 sig = inspect.signature(foo)
2654 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2655
2656 self.assertEqual(self.signature(partial(foo, 1)),
2657 ((('b', ..., ..., 'positional_only'),
2658 ('c', ..., ..., 'positional_or_keyword'),
2659 ('d', ..., ..., 'positional_or_keyword'),
2660 ('kwargs', ..., ..., 'var_keyword')),
2661 ...))
2662
2663 self.assertEqual(self.signature(partial(foo, 1, 2)),
2664 ((('c', ..., ..., 'positional_or_keyword'),
2665 ('d', ..., ..., 'positional_or_keyword'),
2666 ('kwargs', ..., ..., 'var_keyword')),
2667 ...))
2668
2669 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2670 ((('d', ..., ..., 'positional_or_keyword'),
2671 ('kwargs', ..., ..., 'var_keyword')),
2672 ...))
2673
2674 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2675 ((('c', 3, ..., 'keyword_only'),
2676 ('d', ..., ..., 'keyword_only'),
2677 ('kwargs', ..., ..., 'var_keyword')),
2678 ...))
2679
2680 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2681 ((('b', ..., ..., 'positional_only'),
2682 ('c', 3, ..., 'keyword_only'),
2683 ('d', ..., ..., 'keyword_only'),
2684 ('kwargs', ..., ..., 'var_keyword')),
2685 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002686
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002687 def test_signature_on_partialmethod(self):
2688 from functools import partialmethod
2689
2690 class Spam:
2691 def test():
2692 pass
2693 ham = partialmethod(test)
2694
2695 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2696 inspect.signature(Spam.ham)
2697
2698 class Spam:
2699 def test(it, a, *, c) -> 'spam':
2700 pass
2701 ham = partialmethod(test, c=1)
2702
2703 self.assertEqual(self.signature(Spam.ham),
2704 ((('it', ..., ..., 'positional_or_keyword'),
2705 ('a', ..., ..., 'positional_or_keyword'),
2706 ('c', 1, ..., 'keyword_only')),
2707 'spam'))
2708
2709 self.assertEqual(self.signature(Spam().ham),
2710 ((('a', ..., ..., 'positional_or_keyword'),
2711 ('c', 1, ..., 'keyword_only')),
2712 'spam'))
2713
Yury Selivanov8a387212018-03-06 12:59:45 -05002714 class Spam:
2715 def test(self: 'anno', x):
2716 pass
2717
2718 g = partialmethod(test, 1)
2719
2720 self.assertEqual(self.signature(Spam.g),
2721 ((('self', ..., 'anno', 'positional_or_keyword'),),
2722 ...))
2723
Yury Selivanov0486f812014-01-29 12:18:59 -05002724 def test_signature_on_fake_partialmethod(self):
2725 def foo(a): pass
2726 foo._partialmethod = 'spam'
2727 self.assertEqual(str(inspect.signature(foo)), '(a)')
2728
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002729 def test_signature_on_decorated(self):
2730 import functools
2731
2732 def decorator(func):
2733 @functools.wraps(func)
2734 def wrapper(*args, **kwargs) -> int:
2735 return func(*args, **kwargs)
2736 return wrapper
2737
2738 class Foo:
2739 @decorator
2740 def bar(self, a, b):
2741 pass
2742
2743 self.assertEqual(self.signature(Foo.bar),
2744 ((('self', ..., ..., "positional_or_keyword"),
2745 ('a', ..., ..., "positional_or_keyword"),
2746 ('b', ..., ..., "positional_or_keyword")),
2747 ...))
2748
2749 self.assertEqual(self.signature(Foo().bar),
2750 ((('a', ..., ..., "positional_or_keyword"),
2751 ('b', ..., ..., "positional_or_keyword")),
2752 ...))
2753
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002754 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2755 ((('args', ..., ..., "var_positional"),
2756 ('kwargs', ..., ..., "var_keyword")),
2757 ...)) # functools.wraps will copy __annotations__
2758 # from "func" to "wrapper", hence no
2759 # return_annotation
2760
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002761 # Test that we handle method wrappers correctly
2762 def decorator(func):
2763 @functools.wraps(func)
2764 def wrapper(*args, **kwargs) -> int:
2765 return func(42, *args, **kwargs)
2766 sig = inspect.signature(func)
2767 new_params = tuple(sig.parameters.values())[1:]
2768 wrapper.__signature__ = sig.replace(parameters=new_params)
2769 return wrapper
2770
2771 class Foo:
2772 @decorator
2773 def __call__(self, a, b):
2774 pass
2775
2776 self.assertEqual(self.signature(Foo.__call__),
2777 ((('a', ..., ..., "positional_or_keyword"),
2778 ('b', ..., ..., "positional_or_keyword")),
2779 ...))
2780
2781 self.assertEqual(self.signature(Foo().__call__),
2782 ((('b', ..., ..., "positional_or_keyword"),),
2783 ...))
2784
Nick Coghlane8c45d62013-07-28 20:00:01 +10002785 # Test we handle __signature__ partway down the wrapper stack
2786 def wrapped_foo_call():
2787 pass
2788 wrapped_foo_call.__wrapped__ = Foo.__call__
2789
2790 self.assertEqual(self.signature(wrapped_foo_call),
2791 ((('a', ..., ..., "positional_or_keyword"),
2792 ('b', ..., ..., "positional_or_keyword")),
2793 ...))
2794
2795
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002796 def test_signature_on_class(self):
2797 class C:
2798 def __init__(self, a):
2799 pass
2800
2801 self.assertEqual(self.signature(C),
2802 ((('a', ..., ..., "positional_or_keyword"),),
2803 ...))
2804
2805 class CM(type):
2806 def __call__(cls, a):
2807 pass
2808 class C(metaclass=CM):
2809 def __init__(self, b):
2810 pass
2811
2812 self.assertEqual(self.signature(C),
2813 ((('a', ..., ..., "positional_or_keyword"),),
2814 ...))
2815
2816 class CM(type):
2817 def __new__(mcls, name, bases, dct, *, foo=1):
2818 return super().__new__(mcls, name, bases, dct)
2819 class C(metaclass=CM):
2820 def __init__(self, b):
2821 pass
2822
2823 self.assertEqual(self.signature(C),
2824 ((('b', ..., ..., "positional_or_keyword"),),
2825 ...))
2826
2827 self.assertEqual(self.signature(CM),
2828 ((('name', ..., ..., "positional_or_keyword"),
2829 ('bases', ..., ..., "positional_or_keyword"),
2830 ('dct', ..., ..., "positional_or_keyword"),
2831 ('foo', 1, ..., "keyword_only")),
2832 ...))
2833
2834 class CMM(type):
2835 def __new__(mcls, name, bases, dct, *, foo=1):
2836 return super().__new__(mcls, name, bases, dct)
2837 def __call__(cls, nm, bs, dt):
2838 return type(nm, bs, dt)
2839 class CM(type, metaclass=CMM):
2840 def __new__(mcls, name, bases, dct, *, bar=2):
2841 return super().__new__(mcls, name, bases, dct)
2842 class C(metaclass=CM):
2843 def __init__(self, b):
2844 pass
2845
2846 self.assertEqual(self.signature(CMM),
2847 ((('name', ..., ..., "positional_or_keyword"),
2848 ('bases', ..., ..., "positional_or_keyword"),
2849 ('dct', ..., ..., "positional_or_keyword"),
2850 ('foo', 1, ..., "keyword_only")),
2851 ...))
2852
2853 self.assertEqual(self.signature(CM),
2854 ((('nm', ..., ..., "positional_or_keyword"),
2855 ('bs', ..., ..., "positional_or_keyword"),
2856 ('dt', ..., ..., "positional_or_keyword")),
2857 ...))
2858
2859 self.assertEqual(self.signature(C),
2860 ((('b', ..., ..., "positional_or_keyword"),),
2861 ...))
2862
2863 class CM(type):
2864 def __init__(cls, name, bases, dct, *, bar=2):
2865 return super().__init__(name, bases, dct)
2866 class C(metaclass=CM):
2867 def __init__(self, b):
2868 pass
2869
2870 self.assertEqual(self.signature(CM),
2871 ((('name', ..., ..., "positional_or_keyword"),
2872 ('bases', ..., ..., "positional_or_keyword"),
2873 ('dct', ..., ..., "positional_or_keyword"),
2874 ('bar', 2, ..., "keyword_only")),
2875 ...))
2876
Yury Selivanov145dff82014-02-01 13:49:29 -05002877 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2878 "Signature information for builtins requires docstrings")
2879 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002880 # Test classes without user-defined __init__ or __new__
2881 class C: pass
2882 self.assertEqual(str(inspect.signature(C)), '()')
2883 class D(C): pass
2884 self.assertEqual(str(inspect.signature(D)), '()')
2885
2886 # Test meta-classes without user-defined __init__ or __new__
2887 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002888 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002889 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2890 self.assertEqual(inspect.signature(C), None)
2891 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2892 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002893
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002894 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2895 "Signature information for builtins requires docstrings")
2896 def test_signature_on_builtin_class(self):
Antoine Pitrou91f43802019-05-26 17:10:09 +02002897 expected = ('(file, protocol=None, fix_imports=True, '
2898 'buffer_callback=None)')
2899 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002900
2901 class P(_pickle.Pickler): pass
2902 class EmptyTrait: pass
2903 class P2(EmptyTrait, P): pass
Antoine Pitrou91f43802019-05-26 17:10:09 +02002904 self.assertEqual(str(inspect.signature(P)), expected)
2905 self.assertEqual(str(inspect.signature(P2)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002906
2907 class P3(P2):
2908 def __init__(self, spam):
2909 pass
2910 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2911
2912 class MetaP(type):
2913 def __call__(cls, foo, bar):
2914 pass
2915 class P4(P2, metaclass=MetaP):
2916 pass
2917 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2918
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002919 def test_signature_on_callable_objects(self):
2920 class Foo:
2921 def __call__(self, a):
2922 pass
2923
2924 self.assertEqual(self.signature(Foo()),
2925 ((('a', ..., ..., "positional_or_keyword"),),
2926 ...))
2927
2928 class Spam:
2929 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002930 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002931 inspect.signature(Spam())
2932
2933 class Bar(Spam, Foo):
2934 pass
2935
2936 self.assertEqual(self.signature(Bar()),
2937 ((('a', ..., ..., "positional_or_keyword"),),
2938 ...))
2939
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002940 class Wrapped:
2941 pass
2942 Wrapped.__wrapped__ = lambda a: None
2943 self.assertEqual(self.signature(Wrapped),
2944 ((('a', ..., ..., "positional_or_keyword"),),
2945 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002946 # wrapper loop:
2947 Wrapped.__wrapped__ = Wrapped
2948 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2949 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002950
2951 def test_signature_on_lambdas(self):
2952 self.assertEqual(self.signature((lambda a=10: a)),
2953 ((('a', 10, ..., "positional_or_keyword"),),
2954 ...))
2955
2956 def test_signature_equality(self):
2957 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002958 self.assertFalse(inspect.signature(foo) == 42)
2959 self.assertTrue(inspect.signature(foo) != 42)
2960 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2961 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002962
2963 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002964 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2965 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002966 self.assertEqual(
2967 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002968
2969 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002970 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2971 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002972 self.assertNotEqual(
2973 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002974
2975 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002976 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2977 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002978 self.assertNotEqual(
2979 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002980
2981 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002982 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2983 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002984 self.assertNotEqual(
2985 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002986
2987 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002988 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2989 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002990 self.assertNotEqual(
2991 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002992
2993 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002994 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2995 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002996 self.assertNotEqual(
2997 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002998 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002999 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3000 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003001 self.assertNotEqual(
3002 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003003
3004 def foo(*, a, b, c): pass
3005 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003006 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3007 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003008 self.assertEqual(
3009 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003010
3011 def foo(*, a=1, b, c): pass
3012 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003013 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3014 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003015 self.assertEqual(
3016 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003017
3018 def foo(pos, *, a=1, b, c): pass
3019 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003020 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3021 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003022 self.assertEqual(
3023 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003024
3025 def foo(pos, *, a, b, c): pass
3026 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003027 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3028 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003029 self.assertNotEqual(
3030 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003031
3032 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3033 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003034 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3035 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003036 self.assertEqual(
3037 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003038
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003039 def test_signature_hashable(self):
3040 S = inspect.Signature
3041 P = inspect.Parameter
3042
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003043 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003044 foo_sig = inspect.signature(foo)
3045
3046 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3047
3048 self.assertEqual(hash(foo_sig), hash(manual_sig))
3049 self.assertNotEqual(hash(foo_sig),
3050 hash(manual_sig.replace(return_annotation='spam')))
3051
3052 def bar(a) -> 1: pass
3053 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3054
3055 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003056 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003057 hash(inspect.signature(foo))
3058
3059 def foo(a) -> {}: pass
3060 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3061 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003062
3063 def test_signature_str(self):
3064 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3065 pass
3066 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003067 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003068
3069 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3070 pass
3071 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003072 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003073
3074 def foo():
3075 pass
3076 self.assertEqual(str(inspect.signature(foo)), '()')
3077
3078 def test_signature_str_positional_only(self):
3079 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003080 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003081
3082 def test(a_po, *, b, **kwargs):
3083 return a_po, kwargs
3084
3085 sig = inspect.signature(test)
3086 new_params = list(sig.parameters.values())
3087 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3088 test.__signature__ = sig.replace(parameters=new_params)
3089
3090 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003091 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003092
Yury Selivanov2393dca2014-01-27 15:07:58 -05003093 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3094 '(foo, /)')
3095
3096 self.assertEqual(str(S(parameters=[
3097 P('foo', P.POSITIONAL_ONLY),
3098 P('bar', P.VAR_KEYWORD)])),
3099 '(foo, /, **bar)')
3100
3101 self.assertEqual(str(S(parameters=[
3102 P('foo', P.POSITIONAL_ONLY),
3103 P('bar', P.VAR_POSITIONAL)])),
3104 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003105
3106 def test_signature_replace_anno(self):
3107 def test() -> 42:
3108 pass
3109
3110 sig = inspect.signature(test)
3111 sig = sig.replace(return_annotation=None)
3112 self.assertIs(sig.return_annotation, None)
3113 sig = sig.replace(return_annotation=sig.empty)
3114 self.assertIs(sig.return_annotation, sig.empty)
3115 sig = sig.replace(return_annotation=42)
3116 self.assertEqual(sig.return_annotation, 42)
3117 self.assertEqual(sig, inspect.signature(test))
3118
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003119 def test_signature_on_mangled_parameters(self):
3120 class Spam:
3121 def foo(self, __p1:1=2, *, __p2:2=3):
3122 pass
3123 class Ham(Spam):
3124 pass
3125
3126 self.assertEqual(self.signature(Spam.foo),
3127 ((('self', ..., ..., "positional_or_keyword"),
3128 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3129 ('_Spam__p2', 3, 2, "keyword_only")),
3130 ...))
3131
3132 self.assertEqual(self.signature(Spam.foo),
3133 self.signature(Ham.foo))
3134
Yury Selivanovda396452014-03-27 12:09:24 -04003135 def test_signature_from_callable_python_obj(self):
3136 class MySignature(inspect.Signature): pass
3137 def foo(a, *, b:1): pass
3138 foo_sig = MySignature.from_callable(foo)
3139 self.assertTrue(isinstance(foo_sig, MySignature))
3140
3141 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3142 "Signature information for builtins requires docstrings")
3143 def test_signature_from_callable_builtin_obj(self):
3144 class MySignature(inspect.Signature): pass
3145 sig = MySignature.from_callable(_pickle.Pickler)
3146 self.assertTrue(isinstance(sig, MySignature))
3147
larryhastingsf36ba122018-01-28 11:13:09 -08003148 def test_signature_definition_order_preserved_on_kwonly(self):
3149 for fn in signatures_with_lexicographic_keyword_only_parameters():
3150 signature = inspect.signature(fn)
3151 l = list(signature.parameters)
3152 sorted_l = sorted(l)
3153 self.assertTrue(l)
3154 self.assertEqual(l, sorted_l)
3155 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3156 l = list(signature.parameters)
3157 self.assertEqual(l, unsorted_keyword_only_parameters)
3158
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003159
3160class TestParameterObject(unittest.TestCase):
3161 def test_signature_parameter_kinds(self):
3162 P = inspect.Parameter
3163 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3164 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3165
3166 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3167 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3168
3169 def test_signature_parameter_object(self):
3170 p = inspect.Parameter('foo', default=10,
3171 kind=inspect.Parameter.POSITIONAL_ONLY)
3172 self.assertEqual(p.name, 'foo')
3173 self.assertEqual(p.default, 10)
3174 self.assertIs(p.annotation, p.empty)
3175 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3176
Dong-hee Naa9cab432018-05-30 00:04:08 +09003177 with self.assertRaisesRegex(ValueError, "value '123' is "
3178 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003179 inspect.Parameter('foo', default=10, kind='123')
3180
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003181 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003182 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3183
Yury Selivanov2393dca2014-01-27 15:07:58 -05003184 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003185 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3186
Yury Selivanov2393dca2014-01-27 15:07:58 -05003187 with self.assertRaisesRegex(ValueError,
3188 'is not a valid parameter name'):
3189 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3190
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003191 with self.assertRaisesRegex(ValueError,
3192 'is not a valid parameter name'):
3193 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3194
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003195 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003196 inspect.Parameter('a', default=42,
3197 kind=inspect.Parameter.VAR_KEYWORD)
3198
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003199 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003200 inspect.Parameter('a', default=42,
3201 kind=inspect.Parameter.VAR_POSITIONAL)
3202
3203 p = inspect.Parameter('a', default=42,
3204 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003205 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003206 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3207
3208 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003209 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003210
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003211 def test_signature_parameter_hashable(self):
3212 P = inspect.Parameter
3213 foo = P('foo', kind=P.POSITIONAL_ONLY)
3214 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3215 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3216 default=42)))
3217 self.assertNotEqual(hash(foo),
3218 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3219
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003220 def test_signature_parameter_equality(self):
3221 P = inspect.Parameter
3222 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3223
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003224 self.assertTrue(p == p)
3225 self.assertFalse(p != p)
3226 self.assertFalse(p == 42)
3227 self.assertTrue(p != 42)
3228 self.assertTrue(p == EqualsToAll())
3229 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003230
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003231 self.assertTrue(p == P('foo', default=42,
3232 kind=inspect.Parameter.KEYWORD_ONLY))
3233 self.assertFalse(p != P('foo', default=42,
3234 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003235
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003236 def test_signature_parameter_replace(self):
3237 p = inspect.Parameter('foo', default=42,
3238 kind=inspect.Parameter.KEYWORD_ONLY)
3239
3240 self.assertIsNot(p, p.replace())
3241 self.assertEqual(p, p.replace())
3242
3243 p2 = p.replace(annotation=1)
3244 self.assertEqual(p2.annotation, 1)
3245 p2 = p2.replace(annotation=p2.empty)
3246 self.assertEqual(p, p2)
3247
3248 p2 = p2.replace(name='bar')
3249 self.assertEqual(p2.name, 'bar')
3250 self.assertNotEqual(p2, p)
3251
Yury Selivanov2393dca2014-01-27 15:07:58 -05003252 with self.assertRaisesRegex(ValueError,
3253 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003254 p2 = p2.replace(name=p2.empty)
3255
3256 p2 = p2.replace(name='foo', default=None)
3257 self.assertIs(p2.default, None)
3258 self.assertNotEqual(p2, p)
3259
3260 p2 = p2.replace(name='foo', default=p2.empty)
3261 self.assertIs(p2.default, p2.empty)
3262
3263
3264 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3265 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3266 self.assertNotEqual(p2, p)
3267
Dong-hee Naa9cab432018-05-30 00:04:08 +09003268 with self.assertRaisesRegex(ValueError,
3269 "value <class 'inspect._empty'> "
3270 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003271 p2 = p2.replace(kind=p2.empty)
3272
3273 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3274 self.assertEqual(p2, p)
3275
3276 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003277 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3278 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003279
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003280 @cpython_only
3281 def test_signature_parameter_implicit(self):
3282 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003283 'implicit arguments must be passed as '
3284 'positional or keyword arguments, '
3285 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003286 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3287
3288 param = inspect.Parameter(
3289 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3290 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3291 self.assertEqual(param.name, 'implicit0')
3292
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003293 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003294 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003295
3296 with self.assertRaises(AttributeError):
3297 p.foo = 'bar'
3298
3299 with self.assertRaises(AttributeError):
3300 p.kind = 123
3301
3302
3303class TestSignatureBind(unittest.TestCase):
3304 @staticmethod
3305 def call(func, *args, **kwargs):
3306 sig = inspect.signature(func)
3307 ba = sig.bind(*args, **kwargs)
3308 return func(*ba.args, **ba.kwargs)
3309
3310 def test_signature_bind_empty(self):
3311 def test():
3312 return 42
3313
3314 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003315 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003316 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003317 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003318 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003319 with self.assertRaisesRegex(
3320 TypeError, "got an unexpected keyword argument 'spam'"):
3321
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003322 self.call(test, spam=1)
3323
3324 def test_signature_bind_var(self):
3325 def test(*args, **kwargs):
3326 return args, kwargs
3327
3328 self.assertEqual(self.call(test), ((), {}))
3329 self.assertEqual(self.call(test, 1), ((1,), {}))
3330 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3331 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3332 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3333 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3334 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3335 ((1, 2), {'foo': 'bar'}))
3336
3337 def test_signature_bind_just_args(self):
3338 def test(a, b, c):
3339 return a, b, c
3340
3341 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3342
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003343 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003344 self.call(test, 1, 2, 3, 4)
3345
Yury Selivanov86872752015-05-19 00:27:49 -04003346 with self.assertRaisesRegex(TypeError,
3347 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003348 self.call(test, 1)
3349
Yury Selivanov86872752015-05-19 00:27:49 -04003350 with self.assertRaisesRegex(TypeError,
3351 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003352 self.call(test)
3353
3354 def test(a, b, c=10):
3355 return a, b, c
3356 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3357 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3358
3359 def test(a=1, b=2, c=3):
3360 return a, b, c
3361 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3362 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3363 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3364
3365 def test_signature_bind_varargs_order(self):
3366 def test(*args):
3367 return args
3368
3369 self.assertEqual(self.call(test), ())
3370 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3371
3372 def test_signature_bind_args_and_varargs(self):
3373 def test(a, b, c=3, *args):
3374 return a, b, c, args
3375
3376 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3377 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3378 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3379 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3380
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003381 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003382 "multiple values for argument 'c'"):
3383 self.call(test, 1, 2, 3, c=4)
3384
3385 def test_signature_bind_just_kwargs(self):
3386 def test(**kwargs):
3387 return kwargs
3388
3389 self.assertEqual(self.call(test), {})
3390 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3391 {'foo': 'bar', 'spam': 'ham'})
3392
3393 def test_signature_bind_args_and_kwargs(self):
3394 def test(a, b, c=3, **kwargs):
3395 return a, b, c, kwargs
3396
3397 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3398 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3399 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3400 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3401 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3402 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3403 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3404 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3405 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3406 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3407 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3408 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3409 (1, 2, 4, {'foo': 'bar'}))
3410 self.assertEqual(self.call(test, c=5, a=4, b=3),
3411 (4, 3, 5, {}))
3412
3413 def test_signature_bind_kwonly(self):
3414 def test(*, foo):
3415 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003416 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003417 'too many positional arguments'):
3418 self.call(test, 1)
3419 self.assertEqual(self.call(test, foo=1), 1)
3420
3421 def test(a, *, foo=1, bar):
3422 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003423 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003424 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003425 self.call(test, 1)
3426
3427 def test(foo, *, bar):
3428 return foo, bar
3429 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3430 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3431
Yury Selivanov86872752015-05-19 00:27:49 -04003432 with self.assertRaisesRegex(
3433 TypeError, "got an unexpected keyword argument 'spam'"):
3434
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003435 self.call(test, bar=2, foo=1, spam=10)
3436
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003437 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003438 'too many positional arguments'):
3439 self.call(test, 1, 2)
3440
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003441 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003442 'too many positional arguments'):
3443 self.call(test, 1, 2, bar=2)
3444
Yury Selivanov86872752015-05-19 00:27:49 -04003445 with self.assertRaisesRegex(
3446 TypeError, "got an unexpected keyword argument 'spam'"):
3447
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003448 self.call(test, 1, bar=2, spam='ham')
3449
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003450 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003451 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003452 self.call(test, 1)
3453
3454 def test(foo, *, bar, **bin):
3455 return foo, bar, bin
3456 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3457 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3458 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3459 (1, 2, {'spam': 'ham'}))
3460 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3461 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003462 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003463 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003464 self.call(test, spam='ham', bar=2)
3465 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3466 (1, 2, {'bin': 1, 'spam': 10}))
3467
3468 def test_signature_bind_arguments(self):
3469 def test(a, *args, b, z=100, **kwargs):
3470 pass
3471 sig = inspect.signature(test)
3472 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3473 # we won't have 'z' argument in the bound arguments object, as we didn't
3474 # pass it to the 'bind'
3475 self.assertEqual(tuple(ba.arguments.items()),
3476 (('a', 10), ('args', (20,)), ('b', 30),
3477 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3478 self.assertEqual(ba.kwargs,
3479 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3480 self.assertEqual(ba.args, (10, 20))
3481
3482 def test_signature_bind_positional_only(self):
3483 P = inspect.Parameter
3484
3485 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3486 return a_po, b_po, c_po, foo, bar, kwargs
3487
3488 sig = inspect.signature(test)
3489 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3490 for name in ('a_po', 'b_po', 'c_po'):
3491 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3492 new_sig = sig.replace(parameters=new_params.values())
3493 test.__signature__ = new_sig
3494
3495 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3496 (1, 2, 4, 5, 6, {}))
3497
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003498 self.assertEqual(self.call(test, 1, 2),
3499 (1, 2, 3, 42, 50, {}))
3500
3501 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3502 (1, 2, 3, 4, 5, {}))
3503
3504 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3505 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3506
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003507 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003508 self.call(test, 1, 2, c_po=4)
3509
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003510 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003511 self.call(test, a_po=1, b_po=2)
3512
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003513 def test_signature_bind_with_self_arg(self):
3514 # Issue #17071: one of the parameters is named "self
3515 def test(a, self, b):
3516 pass
3517 sig = inspect.signature(test)
3518 ba = sig.bind(1, 2, 3)
3519 self.assertEqual(ba.args, (1, 2, 3))
3520 ba = sig.bind(1, self=2, b=3)
3521 self.assertEqual(ba.args, (1, 2, 3))
3522
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003523 def test_signature_bind_vararg_name(self):
3524 def test(a, *args):
3525 return a, args
3526 sig = inspect.signature(test)
3527
Yury Selivanov86872752015-05-19 00:27:49 -04003528 with self.assertRaisesRegex(
3529 TypeError, "got an unexpected keyword argument 'args'"):
3530
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003531 sig.bind(a=0, args=1)
3532
3533 def test(*args, **kwargs):
3534 return args, kwargs
3535 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3536
3537 sig = inspect.signature(test)
3538 ba = sig.bind(args=1)
3539 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3540
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003541 @cpython_only
3542 def test_signature_bind_implicit_arg(self):
3543 # Issue #19611: getcallargs should work with set comprehensions
3544 def make_set():
3545 return {z * z for z in range(5)}
3546 setcomp_code = make_set.__code__.co_consts[1]
3547 setcomp_func = types.FunctionType(setcomp_code, {})
3548
3549 iterator = iter(range(5))
3550 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3551
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003552
3553class TestBoundArguments(unittest.TestCase):
3554 def test_signature_bound_arguments_unhashable(self):
3555 def foo(a): pass
3556 ba = inspect.signature(foo).bind(1)
3557
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003558 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003559 hash(ba)
3560
3561 def test_signature_bound_arguments_equality(self):
3562 def foo(a): pass
3563 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003564 self.assertTrue(ba == ba)
3565 self.assertFalse(ba != ba)
3566 self.assertTrue(ba == EqualsToAll())
3567 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003568
3569 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003570 self.assertTrue(ba == ba2)
3571 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003572
3573 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003574 self.assertFalse(ba == ba3)
3575 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003576 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003577 self.assertTrue(ba == ba3)
3578 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003579
3580 def bar(b): pass
3581 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003582 self.assertFalse(ba == ba4)
3583 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003584
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003585 def foo(*, a, b): pass
3586 sig = inspect.signature(foo)
3587 ba1 = sig.bind(a=1, b=2)
3588 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003589 self.assertTrue(ba1 == ba2)
3590 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003591
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003592 def test_signature_bound_arguments_pickle(self):
3593 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3594 sig = inspect.signature(foo)
3595 ba = sig.bind(20, 30, z={})
3596
3597 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3598 with self.subTest(pickle_ver=ver):
3599 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3600 self.assertEqual(ba, ba_pickled)
3601
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003602 def test_signature_bound_arguments_repr(self):
3603 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3604 sig = inspect.signature(foo)
3605 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003606 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003607
Yury Selivanovb907a512015-05-16 13:45:09 -04003608 def test_signature_bound_arguments_apply_defaults(self):
3609 def foo(a, b=1, *args, c:1={}, **kw): pass
3610 sig = inspect.signature(foo)
3611
3612 ba = sig.bind(20)
3613 ba.apply_defaults()
3614 self.assertEqual(
3615 list(ba.arguments.items()),
3616 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3617
3618 # Make sure that we preserve the order:
3619 # i.e. 'c' should be *before* 'kw'.
3620 ba = sig.bind(10, 20, 30, d=1)
3621 ba.apply_defaults()
3622 self.assertEqual(
3623 list(ba.arguments.items()),
3624 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3625
3626 # Make sure that BoundArguments produced by bind_partial()
3627 # are supported.
3628 def foo(a, b): pass
3629 sig = inspect.signature(foo)
3630 ba = sig.bind_partial(20)
3631 ba.apply_defaults()
3632 self.assertEqual(
3633 list(ba.arguments.items()),
3634 [('a', 20)])
3635
3636 # Test no args
3637 def foo(): pass
3638 sig = inspect.signature(foo)
3639 ba = sig.bind()
3640 ba.apply_defaults()
3641 self.assertEqual(list(ba.arguments.items()), [])
3642
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003643 # Make sure a no-args binding still acquires proper defaults.
3644 def foo(a='spam'): pass
3645 sig = inspect.signature(foo)
3646 ba = sig.bind()
3647 ba.apply_defaults()
3648 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3649
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003650
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003651class TestSignaturePrivateHelpers(unittest.TestCase):
3652 def test_signature_get_bound_param(self):
3653 getter = inspect._signature_get_bound_param
3654
3655 self.assertEqual(getter('($self)'), 'self')
3656 self.assertEqual(getter('($self, obj)'), 'self')
3657 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3658
Larry Hastings2623c8c2014-02-08 22:15:29 -08003659 def _strip_non_python_syntax(self, input,
3660 clean_signature, self_parameter, last_positional_only):
3661 computed_clean_signature, \
3662 computed_self_parameter, \
3663 computed_last_positional_only = \
3664 inspect._signature_strip_non_python_syntax(input)
3665 self.assertEqual(computed_clean_signature, clean_signature)
3666 self.assertEqual(computed_self_parameter, self_parameter)
3667 self.assertEqual(computed_last_positional_only, last_positional_only)
3668
3669 def test_signature_strip_non_python_syntax(self):
3670 self._strip_non_python_syntax(
3671 "($module, /, path, mode, *, dir_fd=None, " +
3672 "effective_ids=False,\n follow_symlinks=True)",
3673 "(module, path, mode, *, dir_fd=None, " +
3674 "effective_ids=False, follow_symlinks=True)",
3675 0,
3676 0)
3677
3678 self._strip_non_python_syntax(
3679 "($module, word, salt, /)",
3680 "(module, word, salt)",
3681 0,
3682 2)
3683
3684 self._strip_non_python_syntax(
3685 "(x, y=None, z=None, /)",
3686 "(x, y=None, z=None)",
3687 None,
3688 2)
3689
3690 self._strip_non_python_syntax(
3691 "(x, y=None, z=None)",
3692 "(x, y=None, z=None)",
3693 None,
3694 None)
3695
3696 self._strip_non_python_syntax(
3697 "(x,\n y=None,\n z = None )",
3698 "(x, y=None, z=None)",
3699 None,
3700 None)
3701
3702 self._strip_non_python_syntax(
3703 "",
3704 "",
3705 None,
3706 None)
3707
3708 self._strip_non_python_syntax(
3709 None,
3710 None,
3711 None,
3712 None)
3713
Nick Coghlan9c680b02015-04-13 12:54:54 -04003714class TestSignatureDefinitions(unittest.TestCase):
3715 # This test case provides a home for checking that particular APIs
3716 # have signatures available for introspection
3717
3718 @cpython_only
3719 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3720 "Signature information for builtins requires docstrings")
3721 def test_builtins_have_signatures(self):
3722 # This checks all builtin callables in CPython have signatures
3723 # A few have signatures Signature can't yet handle, so we skip those
3724 # since they will have to wait until PEP 457 adds the required
3725 # introspection support to the inspect module
3726 # Some others also haven't been converted yet for various other
3727 # reasons, so we also skip those for the time being, but design
3728 # the test to fail in order to indicate when it needs to be
3729 # updated.
3730 no_signature = set()
3731 # These need PEP 457 groups
3732 needs_groups = {"range", "slice", "dir", "getattr",
3733 "next", "iter", "vars"}
3734 no_signature |= needs_groups
3735 # These need PEP 457 groups or a signature change to accept None
3736 needs_semantic_update = {"round"}
3737 no_signature |= needs_semantic_update
3738 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003739 needs_varargs = {"breakpoint", "min", "max", "print",
3740 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003741 no_signature |= needs_varargs
3742 # These simply weren't covered in the initial AC conversion
3743 # for builtin callables
3744 not_converted_yet = {"open", "__import__"}
3745 no_signature |= not_converted_yet
3746 # These builtin types are expected to provide introspection info
3747 types_with_signatures = set()
3748 # Check the signatures we expect to be there
3749 ns = vars(builtins)
3750 for name, obj in sorted(ns.items()):
3751 if not callable(obj):
3752 continue
3753 # The builtin types haven't been converted to AC yet
3754 if isinstance(obj, type) and (name not in types_with_signatures):
3755 # Note that this also skips all the exception types
3756 no_signature.add(name)
3757 if (name in no_signature):
3758 # Not yet converted
3759 continue
3760 with self.subTest(builtin=name):
3761 self.assertIsNotNone(inspect.signature(obj))
3762 # Check callables that haven't been converted don't claim a signature
3763 # This ensures this test will start failing as more signatures are
3764 # added, so the affected items can be moved into the scope of the
3765 # regression test above
3766 for name in no_signature:
3767 with self.subTest(builtin=name):
3768 self.assertIsNone(obj.__text_signature__)
3769
Serhiy Storchakad53cf992019-05-06 22:40:27 +03003770 def test_python_function_override_signature(self):
3771 def func(*args, **kwargs):
3772 pass
3773 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
3774 sig = inspect.signature(func)
3775 self.assertIsNotNone(sig)
3776 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
3777 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
3778 sig = inspect.signature(func)
3779 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
3780
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003781
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003782class NTimesUnwrappable:
3783 def __init__(self, n):
3784 self.n = n
3785 self._next = None
3786
3787 @property
3788 def __wrapped__(self):
3789 if self.n <= 0:
3790 raise Exception("Unwrapped too many times")
3791 if self._next is None:
3792 self._next = NTimesUnwrappable(self.n - 1)
3793 return self._next
3794
Nick Coghlane8c45d62013-07-28 20:00:01 +10003795class TestUnwrap(unittest.TestCase):
3796
3797 def test_unwrap_one(self):
3798 def func(a, b):
3799 return a + b
3800 wrapper = functools.lru_cache(maxsize=20)(func)
3801 self.assertIs(inspect.unwrap(wrapper), func)
3802
3803 def test_unwrap_several(self):
3804 def func(a, b):
3805 return a + b
3806 wrapper = func
3807 for __ in range(10):
3808 @functools.wraps(wrapper)
3809 def wrapper():
3810 pass
3811 self.assertIsNot(wrapper.__wrapped__, func)
3812 self.assertIs(inspect.unwrap(wrapper), func)
3813
3814 def test_stop(self):
3815 def func1(a, b):
3816 return a + b
3817 @functools.wraps(func1)
3818 def func2():
3819 pass
3820 @functools.wraps(func2)
3821 def wrapper():
3822 pass
3823 func2.stop_here = 1
3824 unwrapped = inspect.unwrap(wrapper,
3825 stop=(lambda f: hasattr(f, "stop_here")))
3826 self.assertIs(unwrapped, func2)
3827
3828 def test_cycle(self):
3829 def func1(): pass
3830 func1.__wrapped__ = func1
3831 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3832 inspect.unwrap(func1)
3833
3834 def func2(): pass
3835 func2.__wrapped__ = func1
3836 func1.__wrapped__ = func2
3837 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3838 inspect.unwrap(func1)
3839 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3840 inspect.unwrap(func2)
3841
3842 def test_unhashable(self):
3843 def func(): pass
3844 func.__wrapped__ = None
3845 class C:
3846 __hash__ = None
3847 __wrapped__ = func
3848 self.assertIsNone(inspect.unwrap(C()))
3849
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003850 def test_recursion_limit(self):
3851 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3852 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3853 inspect.unwrap(obj)
3854
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003855class TestMain(unittest.TestCase):
3856 def test_only_source(self):
3857 module = importlib.import_module('unittest')
3858 rc, out, err = assert_python_ok('-m', 'inspect',
3859 'unittest')
3860 lines = out.decode().splitlines()
3861 # ignore the final newline
3862 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3863 self.assertEqual(err, b'')
3864
Yury Selivanov42407ab2014-06-23 10:23:50 -07003865 def test_custom_getattr(self):
3866 def foo():
3867 pass
3868 foo.__signature__ = 42
3869 with self.assertRaises(TypeError):
3870 inspect.signature(foo)
3871
Brett Cannon634a8fc2013-10-02 10:25:42 -04003872 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003873 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003874 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003875 rc, out, err = assert_python_ok('-m', 'inspect',
3876 'concurrent.futures:ThreadPoolExecutor')
3877 lines = out.decode().splitlines()
3878 # ignore the final newline
3879 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003880 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003881 self.assertEqual(err, b'')
3882
3883 def test_builtins(self):
3884 module = importlib.import_module('unittest')
3885 _, out, err = assert_python_failure('-m', 'inspect',
3886 'sys')
3887 lines = err.decode().splitlines()
3888 self.assertEqual(lines, ["Can't get info for builtin modules."])
3889
3890 def test_details(self):
3891 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003892 args = support.optim_args_from_interpreter_flags()
3893 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003894 'unittest', '--details')
3895 output = out.decode()
3896 # Just a quick sanity check on the output
3897 self.assertIn(module.__name__, output)
3898 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003899 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003900 self.assertEqual(err, b'')
3901
3902
Yury Selivanovef1e7502014-12-08 16:05:34 -05003903class TestReload(unittest.TestCase):
3904
3905 src_before = textwrap.dedent("""\
3906def foo():
3907 print("Bla")
3908 """)
3909
3910 src_after = textwrap.dedent("""\
3911def foo():
3912 print("Oh no!")
3913 """)
3914
3915 def assertInspectEqual(self, path, source):
3916 inspected_src = inspect.getsource(source)
3917 with open(path) as src:
3918 self.assertEqual(
3919 src.read().splitlines(True),
3920 inspected_src.splitlines(True)
3921 )
3922
3923 def test_getsource_reload(self):
3924 # see issue 1218234
3925 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3926 module = importlib.import_module(name)
3927 self.assertInspectEqual(path, module)
3928 with open(path, 'w') as src:
3929 src.write(self.src_after)
3930 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003931
Nick Coghlane8c45d62013-07-28 20:00:01 +10003932
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003933def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003934 run_unittest(
3935 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3936 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3937 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003938 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003939 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003940 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04003941 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003942 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07003943 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00003944 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003945
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003946if __name__ == "__main__":
3947 test_main()