blob: ad93f304827fbaf1aec2006652f459bc4f71375d [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 Storchaka5cf2b722015-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
Miss Islington (bot)c5daae42019-06-08 05:24:59 -0700516 def test_getfile_builtin_module(self):
517 with self.assertRaises(TypeError) as e:
518 inspect.getfile(sys)
519 self.assertTrue(str(e.exception).startswith('<module'))
520
521 def test_getfile_builtin_class(self):
522 with self.assertRaises(TypeError) as e:
523 inspect.getfile(int)
524 self.assertTrue(str(e.exception).startswith('<class'))
525
526 def test_getfile_builtin_function_or_method(self):
527 with self.assertRaises(TypeError) as e_abs:
528 inspect.getfile(abs)
529 self.assertIn('expected, got', str(e_abs.exception))
530 with self.assertRaises(TypeError) as e_append:
531 inspect.getfile(list.append)
532 self.assertIn('expected, got', str(e_append.exception))
533
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500534 def test_getfile_class_without_module(self):
535 class CM(type):
536 @property
537 def __module__(cls):
538 raise AttributeError
539 class C(metaclass=CM):
540 pass
541 with self.assertRaises(TypeError):
542 inspect.getfile(C)
543
Thomas Kluyvere968bc732017-10-24 13:42:36 +0100544 def test_getfile_broken_repr(self):
545 class ErrorRepr:
546 def __repr__(self):
547 raise Exception('xyz')
548 er = ErrorRepr()
549 with self.assertRaises(TypeError):
550 inspect.getfile(er)
551
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000552 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000553 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000554 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000555 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000556 m.__file__ = "<string>" # hopefully not a real filename...
557 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000558 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000559 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000560 del sys.modules[name]
561 inspect.getmodule(compile('a=10','','single'))
562
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500563 def test_proceed_with_fake_filename(self):
564 '''doctest monkeypatches linecache to enable inspection'''
565 fn, source = '<test>', 'def x(): pass\n'
566 getlines = linecache.getlines
567 def monkey(filename, module_globals=None):
568 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300569 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500570 else:
571 return getlines(filename, module_globals)
572 linecache.getlines = monkey
573 try:
574 ns = {}
575 exec(compile(source, fn, 'single'), ns)
576 inspect.getsource(ns["x"])
577 finally:
578 linecache.getlines = getlines
579
Antoine Pitroua8723a02015-04-15 00:41:29 +0200580 def test_getsource_on_code_object(self):
581 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
582
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700583class TestGettingSourceOfToplevelFrames(GetSourceBase):
584 fodderModule = mod
585
586 def test_range_toplevel_frame(self):
587 self.maxDiff = None
588 self.assertSourceEqual(mod.currentframe, 1, None)
589
590 def test_range_traceback_toplevel_frame(self):
591 self.assertSourceEqual(mod.tb, 1, None)
592
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000593class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000594 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000595
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000596 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000597 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000598
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000599 def test_replacing_decorator(self):
600 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000601
Yury Selivanov081bbf62014-09-26 17:34:54 -0400602 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200603 self.assertSourceEqual(mod2.real, 130, 132)
604
605 def test_decorator_with_lambda(self):
606 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400607
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000608class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000609 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000610 def test_oneline_lambda(self):
611 # Test inspect.getsource with a one-line lambda function.
612 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000613
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000614 def test_threeline_lambda(self):
615 # Test inspect.getsource with a three-line lambda function,
616 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000617 self.assertSourceEqual(mod2.tll, 28, 30)
618
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000619 def test_twoline_indented_lambda(self):
620 # Test inspect.getsource with a two-line lambda function,
621 # where the second line _is_ indented.
622 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000623
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000624 def test_onelinefunc(self):
625 # Test inspect.getsource with a regular one-line function.
626 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000627
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000628 def test_manyargs(self):
629 # Test inspect.getsource with a regular function where
630 # the arguments are on two lines and _not_ indented and
631 # the body on the second line with the last arguments.
632 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000633
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000634 def test_twolinefunc(self):
635 # Test inspect.getsource with a regular function where
636 # the body is on two lines, following the argument list and
637 # continued on the next line by a \\.
638 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000639
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000640 def test_lambda_in_list(self):
641 # Test inspect.getsource with a one-line lambda function
642 # defined in a list, indented.
643 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000644
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000645 def test_anonymous(self):
646 # Test inspect.getsource with a lambda function defined
647 # as argument to another function.
648 self.assertSourceEqual(mod2.anonymous, 55, 55)
649
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000650class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000651 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000652
653 def test_with_comment(self):
654 self.assertSourceEqual(mod2.with_comment, 58, 59)
655
656 def test_multiline_sig(self):
657 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
658
Armin Rigodd5c0232005-09-25 11:45:45 +0000659 def test_nested_class(self):
660 self.assertSourceEqual(mod2.func69().func71, 71, 72)
661
662 def test_one_liner_followed_by_non_name(self):
663 self.assertSourceEqual(mod2.func77, 77, 77)
664
665 def test_one_liner_dedent_non_name(self):
666 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
667
668 def test_with_comment_instead_of_docstring(self):
669 self.assertSourceEqual(mod2.func88, 88, 90)
670
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000671 def test_method_in_dynamic_class(self):
672 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
673
R David Murray32562d72014-10-03 11:15:38 -0400674 # This should not skip for CPython, but might on a repackaged python where
675 # unicodedata is not an external module, or on pypy.
676 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
677 unicodedata.__file__.endswith('.py'),
678 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000679 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200680 self.assertRaises(OSError, inspect.getsource, unicodedata)
681 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000682
R. David Murraya1b37402010-06-17 02:04:29 +0000683 def test_findsource_code_in_linecache(self):
684 lines = ["x=1"]
685 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200686 self.assertRaises(OSError, inspect.findsource, co)
687 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000688 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200689 try:
690 self.assertEqual(inspect.findsource(co), (lines,0))
691 self.assertEqual(inspect.getsource(co), lines[0])
692 finally:
693 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000694
Ezio Melotti1b145922013-03-30 05:17:24 +0200695 def test_findsource_without_filename(self):
696 for fname in ['', '<string>']:
697 co = compile('x=1', fname, "exec")
698 self.assertRaises(IOError, inspect.findsource, co)
699 self.assertRaises(IOError, inspect.getsource, co)
700
Antoine Pitroua8723a02015-04-15 00:41:29 +0200701 def test_getsource_on_method(self):
702 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
703
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300704 def test_nested_func(self):
705 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
706
707
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000708class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400709 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000710 self.tempdir = TESTFN + '_dir'
711 os.mkdir(self.tempdir)
712 with open(os.path.join(self.tempdir,
713 'inspect_fodder3%spy' % os.extsep), 'w') as f:
714 f.write("class X:\n pass # No EOL")
715 with DirsOnSysPath(self.tempdir):
716 import inspect_fodder3 as mod3
717 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400718 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000719
720 def tearDown(self):
721 shutil.rmtree(self.tempdir)
722
723 def test_class(self):
724 self.assertSourceEqual(self.fodderModule.X, 1, 2)
725
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100726
727class _BrokenDataDescriptor(object):
728 """
729 A broken data descriptor. See bug #1785.
730 """
731 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700732 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100733
734 def __set__(*args):
735 raise RuntimeError
736
737 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700738 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100739
740
741class _BrokenMethodDescriptor(object):
742 """
743 A broken method descriptor. See bug #1785.
744 """
745 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700746 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100747
748 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700749 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100750
751
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000752# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000753def attrs_wo_objs(cls):
754 return [t[:3] for t in inspect.classify_class_attrs(cls)]
755
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100756
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000757class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000758 def test_newstyle_mro(self):
759 # The same w/ new-class MRO.
760 class A(object): pass
761 class B(A): pass
762 class C(A): pass
763 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000764
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000765 expected = (D, B, C, A, object)
766 got = inspect.getmro(D)
767 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000768
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500769 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
770 varkw_e=None, defaults_e=None, formatted=None):
Xtreak6d0b7472019-05-30 17:31:39 +0530771 with self.assertWarns(DeprecationWarning):
772 args, varargs, varkw, defaults = inspect.getargspec(routine)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500773 self.assertEqual(args, args_e)
774 self.assertEqual(varargs, varargs_e)
775 self.assertEqual(varkw, varkw_e)
776 self.assertEqual(defaults, defaults_e)
777 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530778 with self.assertWarns(DeprecationWarning):
779 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
780 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500781
Christian Heimes3795b532007-11-08 13:48:53 +0000782 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
783 varkw_e=None, defaults_e=None,
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100784 posonlyargs_e=[], kwonlyargs_e=[],
785 kwonlydefaults_e=None,
Christian Heimes3795b532007-11-08 13:48:53 +0000786 ann_e={}, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100787 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
788 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000789 self.assertEqual(args, args_e)
790 self.assertEqual(varargs, varargs_e)
791 self.assertEqual(varkw, varkw_e)
792 self.assertEqual(defaults, defaults_e)
793 self.assertEqual(kwonlyargs, kwonlyargs_e)
794 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
795 self.assertEqual(ann, ann_e)
796 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530797 with self.assertWarns(DeprecationWarning):
798 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
799 kwonlyargs, kwonlydefaults, ann),
800 formatted)
Christian Heimes3795b532007-11-08 13:48:53 +0000801
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500802 def test_getargspec(self):
803 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
804
Pablo Galindod5d2b452019-04-30 02:01:14 +0100805 self.assertArgSpecEquals(mod.spam,
806 ['a', 'b', 'c', 'd', 'e', 'f'],
807 'g', 'h', (3, 4, 5),
808 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500809
810 self.assertRaises(ValueError, self.assertArgSpecEquals,
811 mod2.keyworded, [])
812
813 self.assertRaises(ValueError, self.assertArgSpecEquals,
814 mod2.annotated, [])
815 self.assertRaises(ValueError, self.assertArgSpecEquals,
816 mod2.keyword_only_arg, [])
817
818
Christian Heimes3795b532007-11-08 13:48:53 +0000819 def test_getfullargspec(self):
820 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
821 kwonlyargs_e=['arg2'],
822 kwonlydefaults_e={'arg2':1},
823 formatted='(*arg1, arg2=1)')
824
825 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000826 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000827 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000828 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
829 kwonlyargs_e=['arg'],
830 formatted='(*, arg)')
831
Pablo Galindod5d2b452019-04-30 02:01:14 +0100832 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100833 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100834 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100835
836 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100837 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100838 varargs_e='args',
839 varkw_e='kwargs',
840 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100841 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100842
Pablo Galindod5d2b452019-04-30 02:01:14 +0100843 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100844 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100845 kwonlyargs_e=['e', 'f'],
846 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100847 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100848
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500849 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500850 # Issue 20684: low level introspection API must ignore __wrapped__
851 @functools.wraps(mod.spam)
852 def ham(x, y):
853 pass
854 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500855 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500856 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
857 self.assertFullArgSpecEquals(functools.partial(ham),
858 ['x', 'y'], formatted='(x, y)')
859 # Other variants
860 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500861 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
862 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500863 class C:
864 @functools.wraps(mod.spam)
865 def ham(self, x, y):
866 pass
867 pham = functools.partialmethod(ham)
868 @functools.wraps(mod.spam)
869 def __call__(self, x, y):
870 pass
871 check_method(C())
872 check_method(C.ham)
873 check_method(C().ham)
874 check_method(C.pham)
875 check_method(C().pham)
876
877 class C_new:
878 @functools.wraps(mod.spam)
879 def __new__(self, x, y):
880 pass
881 check_method(C_new)
882
883 class C_init:
884 @functools.wraps(mod.spam)
885 def __init__(self, x, y):
886 pass
887 check_method(C_init)
888
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500889 def test_getfullargspec_signature_attr(self):
890 def test():
891 pass
892 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
893 test.__signature__ = inspect.Signature(parameters=(spam_param,))
894
Pablo Galindod5d2b452019-04-30 02:01:14 +0100895 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500896
Yury Selivanov4cb93912014-01-29 11:54:12 -0500897 def test_getfullargspec_signature_annos(self):
898 def test(a:'spam') -> 'ham': pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100899 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500900 self.assertEqual(test.__annotations__, spec.annotations)
901
902 def test(): pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100903 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500904 self.assertEqual(test.__annotations__, spec.annotations)
905
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500906 @unittest.skipIf(MISSING_C_DOCSTRINGS,
907 "Signature information for builtins requires docstrings")
908 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100909 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
910 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500911
Pablo Galindod5d2b452019-04-30 02:01:14 +0100912 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
913 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500914
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500915 self.assertFullArgSpecEquals(
916 os.stat,
917 args_e=['path'],
918 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
919 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
920 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
921
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200922 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500923 @unittest.skipIf(MISSING_C_DOCSTRINGS,
924 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800925 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200926 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500927 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindoaee19f52019-05-16 21:08:15 +0100928 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500929 self.assertEqual(spec.defaults[0], 'avocado')
930
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200931 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500932 @unittest.skipIf(MISSING_C_DOCSTRINGS,
933 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800934 def test_getfullargspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200935 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500936 builtin = _testcapi.docstring_no_signature
Pablo Galindoaee19f52019-05-16 21:08:15 +0100937 with self.assertRaises(TypeError):
938 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000939
larryhastingsf36ba122018-01-28 11:13:09 -0800940 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
941 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindoaee19f52019-05-16 21:08:15 +0100942 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800943 l = list(signature.kwonlyargs)
944 sorted_l = sorted(l)
945 self.assertTrue(l)
946 self.assertEqual(l, sorted_l)
Pablo Galindoaee19f52019-05-16 21:08:15 +0100947 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800948 l = list(signature.kwonlyargs)
949 self.assertEqual(l, unsorted_keyword_only_parameters)
950
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500951 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000952 class A(object):
953 def m(self):
954 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500955 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000956
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000957 def test_classify_newstyle(self):
958 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000959
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000960 def s(): pass
961 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000962
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000963 def c(cls): pass
964 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000965
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000966 def getp(self): pass
967 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000968
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000969 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000970
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000971 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000972
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000973 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000974
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100975 dd = _BrokenDataDescriptor()
976 md = _BrokenMethodDescriptor()
977
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000978 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500979
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +0200980 self.assertIn(('__new__', 'static method', object), attrs,
981 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500982 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
983
Benjamin Peterson577473f2010-01-19 00:09:57 +0000984 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
985 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
986 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000987 self.assertIn(('m', 'method', A), attrs,
988 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000989 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
990 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100991 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
992 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000993
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000994 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000995
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000996 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000997
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000998 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000999 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1000 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1001 self.assertIn(('p', 'property', A), attrs, 'missing property')
1002 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1003 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1004 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001005 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1006 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001007
1008
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001009 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001010
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001011 def m(self): pass
1012 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001013
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001014 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001015 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1016 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1017 self.assertIn(('p', 'property', A), attrs, 'missing property')
1018 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
1019 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1020 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001021 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1022 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001023
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001024 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001025
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001026 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001027
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001028 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001029 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1030 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1031 self.assertIn(('p', 'property', A), attrs, 'missing property')
1032 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1033 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1034 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001035 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1036 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1037
1038 def test_classify_builtin_types(self):
1039 # Simple sanity check that all built-in types can have their
1040 # attributes classified.
1041 for name in dir(__builtins__):
1042 builtin = getattr(__builtins__, name)
1043 if isinstance(builtin, type):
1044 inspect.classify_class_attrs(builtin)
1045
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001046 attrs = attrs_wo_objs(bool)
1047 self.assertIn(('__new__', 'static method', bool), attrs,
1048 'missing __new__')
1049 self.assertIn(('from_bytes', 'class method', int), attrs,
1050 'missing class method')
1051 self.assertIn(('to_bytes', 'method', int), attrs,
1052 'missing plain method')
1053 self.assertIn(('__add__', 'method', int), attrs,
1054 'missing plain method')
1055 self.assertIn(('__and__', 'method', bool), attrs,
1056 'missing plain method')
1057
Ethan Furman63c141c2013-10-18 00:27:39 -07001058 def test_classify_DynamicClassAttribute(self):
1059 class Meta(type):
1060 def __getattr__(self, name):
1061 if name == 'ham':
1062 return 'spam'
1063 return super().__getattr__(name)
1064 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001065 @types.DynamicClassAttribute
1066 def ham(self):
1067 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001068 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1069 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001070 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001071 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1072
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001073 def test_classify_overrides_bool(self):
1074 class NoBool(object):
1075 def __eq__(self, other):
1076 return NoBool()
1077
1078 def __bool__(self):
1079 raise NotImplementedError(
1080 "This object does not specify a boolean value")
1081
1082 class HasNB(object):
1083 dd = NoBool()
1084
1085 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1086 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1087
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001088 def test_classify_metaclass_class_attribute(self):
1089 class Meta(type):
1090 fish = 'slap'
1091 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001092 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001093 class Class(metaclass=Meta):
1094 pass
1095 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1096 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1097
Ethan Furman63c141c2013-10-18 00:27:39 -07001098 def test_classify_VirtualAttribute(self):
1099 class Meta(type):
1100 def __dir__(cls):
1101 return ['__class__', '__module__', '__name__', 'BOOM']
1102 def __getattr__(self, name):
1103 if name =='BOOM':
1104 return 42
1105 return super().__getattr(name)
1106 class Class(metaclass=Meta):
1107 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001108 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001109 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1110
1111 def test_classify_VirtualAttribute_multi_classes(self):
1112 class Meta1(type):
1113 def __dir__(cls):
1114 return ['__class__', '__module__', '__name__', 'one']
1115 def __getattr__(self, name):
1116 if name =='one':
1117 return 1
1118 return super().__getattr__(name)
1119 class Meta2(type):
1120 def __dir__(cls):
1121 return ['__class__', '__module__', '__name__', 'two']
1122 def __getattr__(self, name):
1123 if name =='two':
1124 return 2
1125 return super().__getattr__(name)
1126 class Meta3(Meta1, Meta2):
1127 def __dir__(cls):
1128 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1129 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1130 def __getattr__(self, name):
1131 if name =='three':
1132 return 3
1133 return super().__getattr__(name)
1134 class Class1(metaclass=Meta1):
1135 pass
1136 class Class2(Class1, metaclass=Meta3):
1137 pass
1138
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001139 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1140 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1141 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001142 cca = inspect.classify_class_attrs(Class2)
1143 for sf in (should_find1, should_find2, should_find3):
1144 self.assertIn(sf, cca)
1145
1146 def test_classify_class_attrs_with_buggy_dir(self):
1147 class M(type):
1148 def __dir__(cls):
1149 return ['__class__', '__name__', 'missing']
1150 class C(metaclass=M):
1151 pass
1152 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1153 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001154
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001155 def test_getmembers_descriptors(self):
1156 class A(object):
1157 dd = _BrokenDataDescriptor()
1158 md = _BrokenMethodDescriptor()
1159
1160 def pred_wrapper(pred):
1161 # A quick'n'dirty way to discard standard attributes of new-style
1162 # classes.
1163 class Empty(object):
1164 pass
1165 def wrapped(x):
1166 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1167 return False
1168 return pred(x)
1169 return wrapped
1170
1171 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1172 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1173
1174 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1175 [('md', A.__dict__['md'])])
1176 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1177 [('dd', A.__dict__['dd'])])
1178
1179 class B(A):
1180 pass
1181
1182 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1183 [('md', A.__dict__['md'])])
1184 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1185 [('dd', A.__dict__['dd'])])
1186
Antoine Pitrou0c603812012-01-18 17:40:18 +01001187 def test_getmembers_method(self):
1188 class B:
1189 def f(self):
1190 pass
1191
1192 self.assertIn(('f', B.f), inspect.getmembers(B))
1193 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1194 b = B()
1195 self.assertIn(('f', b.f), inspect.getmembers(b))
1196 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1197
Ethan Furmane03ea372013-09-25 07:14:41 -07001198 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001199 class M(type):
1200 def __getattr__(cls, name):
1201 if name == 'eggs':
1202 return 'scrambled'
1203 return super().__getattr__(name)
1204 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001205 @types.DynamicClassAttribute
1206 def eggs(self):
1207 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001208 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1209 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1210
1211 def test_getmembers_with_buggy_dir(self):
1212 class M(type):
1213 def __dir__(cls):
1214 return ['__class__', '__name__', 'missing']
1215 class C(metaclass=M):
1216 pass
1217 attrs = [a[0] for a in inspect.getmembers(C)]
1218 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001219
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001220class TestIsDataDescriptor(unittest.TestCase):
1221
1222 def test_custom_descriptors(self):
1223 class NonDataDescriptor:
1224 def __get__(self, value, type=None): pass
1225 class DataDescriptor0:
1226 def __set__(self, name, value): pass
1227 class DataDescriptor1:
1228 def __delete__(self, name): pass
1229 class DataDescriptor2:
1230 __set__ = None
1231 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1232 'class with only __get__ not a data descriptor')
1233 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1234 'class with __set__ is a data descriptor')
1235 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1236 'class with __delete__ is a data descriptor')
1237 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1238 'class with __set__ = None is a data descriptor')
1239
1240 def test_slot(self):
1241 class Slotted:
1242 __slots__ = 'foo',
1243 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1244 'a slot is a data descriptor')
1245
1246 def test_property(self):
1247 class Propertied:
1248 @property
1249 def a_property(self):
1250 pass
1251 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1252 'a property is a data descriptor')
1253
1254 def test_functions(self):
1255 class Test(object):
1256 def instance_method(self): pass
1257 @classmethod
1258 def class_method(cls): pass
1259 @staticmethod
1260 def static_method(): pass
1261 def function():
1262 pass
1263 a_lambda = lambda: None
1264 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1265 'a instance method is not a data descriptor')
1266 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1267 'a class method is not a data descriptor')
1268 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1269 'a static method is not a data descriptor')
1270 self.assertFalse(inspect.isdatadescriptor(function),
1271 'a function is not a data descriptor')
1272 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1273 'a lambda is not a data descriptor')
1274
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001275
Nick Coghlan2f92e542012-06-23 19:39:55 +10001276_global_ref = object()
1277class TestGetClosureVars(unittest.TestCase):
1278
1279 def test_name_resolution(self):
1280 # Basic test of the 4 different resolution mechanisms
1281 def f(nonlocal_ref):
1282 def g(local_ref):
1283 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1284 return g
1285 _arg = object()
1286 nonlocal_vars = {"nonlocal_ref": _arg}
1287 global_vars = {"_global_ref": _global_ref}
1288 builtin_vars = {"print": print}
1289 unbound_names = {"unbound_ref"}
1290 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1291 builtin_vars, unbound_names)
1292 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1293
1294 def test_generator_closure(self):
1295 def f(nonlocal_ref):
1296 def g(local_ref):
1297 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1298 yield
1299 return g
1300 _arg = object()
1301 nonlocal_vars = {"nonlocal_ref": _arg}
1302 global_vars = {"_global_ref": _global_ref}
1303 builtin_vars = {"print": print}
1304 unbound_names = {"unbound_ref"}
1305 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1306 builtin_vars, unbound_names)
1307 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1308
1309 def test_method_closure(self):
1310 class C:
1311 def f(self, nonlocal_ref):
1312 def g(local_ref):
1313 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1314 return g
1315 _arg = object()
1316 nonlocal_vars = {"nonlocal_ref": _arg}
1317 global_vars = {"_global_ref": _global_ref}
1318 builtin_vars = {"print": print}
1319 unbound_names = {"unbound_ref"}
1320 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1321 builtin_vars, unbound_names)
1322 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1323
1324 def test_nonlocal_vars(self):
1325 # More complex tests of nonlocal resolution
1326 def _nonlocal_vars(f):
1327 return inspect.getclosurevars(f).nonlocals
1328
1329 def make_adder(x):
1330 def add(y):
1331 return x + y
1332 return add
1333
1334 def curry(func, arg1):
1335 return lambda arg2: func(arg1, arg2)
1336
1337 def less_than(a, b):
1338 return a < b
1339
1340 # The infamous Y combinator.
1341 def Y(le):
1342 def g(f):
1343 return le(lambda x: f(f)(x))
1344 Y.g_ref = g
1345 return g(g)
1346
1347 def check_y_combinator(func):
1348 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1349
1350 inc = make_adder(1)
1351 add_two = make_adder(2)
1352 greater_than_five = curry(less_than, 5)
1353
1354 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1355 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1356 self.assertEqual(_nonlocal_vars(greater_than_five),
1357 {'arg1': 5, 'func': less_than})
1358 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1359 {'x': 3})
1360 Y(check_y_combinator)
1361
1362 def test_getclosurevars_empty(self):
1363 def foo(): pass
1364 _empty = inspect.ClosureVars({}, {}, {}, set())
1365 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1366 self.assertEqual(inspect.getclosurevars(foo), _empty)
1367
1368 def test_getclosurevars_error(self):
1369 class T: pass
1370 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1371 self.assertRaises(TypeError, inspect.getclosurevars, list)
1372 self.assertRaises(TypeError, inspect.getclosurevars, {})
1373
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001374 def _private_globals(self):
1375 code = """def f(): print(path)"""
1376 ns = {}
1377 exec(code, ns)
1378 return ns["f"], ns
1379
1380 def test_builtins_fallback(self):
1381 f, ns = self._private_globals()
1382 ns.pop("__builtins__", None)
1383 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1384 self.assertEqual(inspect.getclosurevars(f), expected)
1385
1386 def test_builtins_as_dict(self):
1387 f, ns = self._private_globals()
1388 ns["__builtins__"] = {"path":1}
1389 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1390 self.assertEqual(inspect.getclosurevars(f), expected)
1391
1392 def test_builtins_as_module(self):
1393 f, ns = self._private_globals()
1394 ns["__builtins__"] = os
1395 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1396 self.assertEqual(inspect.getclosurevars(f), expected)
1397
Nick Coghlan2f92e542012-06-23 19:39:55 +10001398
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001399class TestGetcallargsFunctions(unittest.TestCase):
1400
1401 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1402 locs = dict(locs or {}, func=func)
1403 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001404 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1405 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001406 self.assertEqual(r1, r2)
1407
1408 def assertEqualException(self, func, call_param_string, locs=None):
1409 locs = dict(locs or {}, func=func)
1410 try:
1411 eval('func(%s)' % call_param_string, None, locs)
1412 except Exception as e:
1413 ex1 = e
1414 else:
1415 self.fail('Exception not raised')
1416 try:
Pablo Galindoaee19f52019-05-16 21:08:15 +01001417 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1418 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001419 except Exception as e:
1420 ex2 = e
1421 else:
1422 self.fail('Exception not raised')
1423 self.assertIs(type(ex1), type(ex2))
1424 self.assertEqual(str(ex1), str(ex2))
1425 del ex1, ex2
1426
1427 def makeCallable(self, signature):
1428 """Create a function that returns its locals()"""
1429 code = "lambda %s: locals()"
1430 return eval(code % signature)
1431
1432 def test_plain(self):
1433 f = self.makeCallable('a, b=1')
1434 self.assertEqualCallArgs(f, '2')
1435 self.assertEqualCallArgs(f, '2, 3')
1436 self.assertEqualCallArgs(f, 'a=2')
1437 self.assertEqualCallArgs(f, 'b=3, a=2')
1438 self.assertEqualCallArgs(f, '2, b=3')
1439 # expand *iterable / **mapping
1440 self.assertEqualCallArgs(f, '*(2,)')
1441 self.assertEqualCallArgs(f, '*[2]')
1442 self.assertEqualCallArgs(f, '*(2, 3)')
1443 self.assertEqualCallArgs(f, '*[2, 3]')
1444 self.assertEqualCallArgs(f, '**{"a":2}')
1445 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1446 self.assertEqualCallArgs(f, '2, **{"b":3}')
1447 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1448 # expand UserList / UserDict
1449 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1450 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1451 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1452 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1453 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1454
1455 def test_varargs(self):
1456 f = self.makeCallable('a, b=1, *c')
1457 self.assertEqualCallArgs(f, '2')
1458 self.assertEqualCallArgs(f, '2, 3')
1459 self.assertEqualCallArgs(f, '2, 3, 4')
1460 self.assertEqualCallArgs(f, '*(2,3,4)')
1461 self.assertEqualCallArgs(f, '2, *[3,4]')
1462 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1463
1464 def test_varkw(self):
1465 f = self.makeCallable('a, b=1, **c')
1466 self.assertEqualCallArgs(f, 'a=2')
1467 self.assertEqualCallArgs(f, '2, b=3, c=4')
1468 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1469 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1470 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1471 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1472 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1473 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1474 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1475
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001476 def test_varkw_only(self):
1477 # issue11256:
1478 f = self.makeCallable('**c')
1479 self.assertEqualCallArgs(f, '')
1480 self.assertEqualCallArgs(f, 'a=1')
1481 self.assertEqualCallArgs(f, 'a=1, b=2')
1482 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1483 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1484 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1485
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001486 def test_keyword_only(self):
1487 f = self.makeCallable('a=3, *, c, d=2')
1488 self.assertEqualCallArgs(f, 'c=3')
1489 self.assertEqualCallArgs(f, 'c=3, a=3')
1490 self.assertEqualCallArgs(f, 'a=2, c=4')
1491 self.assertEqualCallArgs(f, '4, c=4')
1492 self.assertEqualException(f, '')
1493 self.assertEqualException(f, '3')
1494 self.assertEqualException(f, 'a=3')
1495 self.assertEqualException(f, 'd=4')
1496
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001497 f = self.makeCallable('*, c, d=2')
1498 self.assertEqualCallArgs(f, 'c=3')
1499 self.assertEqualCallArgs(f, 'c=3, d=4')
1500 self.assertEqualCallArgs(f, 'd=4, c=3')
1501
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001502 def test_multiple_features(self):
1503 f = self.makeCallable('a, b=2, *f, **g')
1504 self.assertEqualCallArgs(f, '2, 3, 7')
1505 self.assertEqualCallArgs(f, '2, 3, x=8')
1506 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1507 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1508 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1509 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1510 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1511 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1512 '(4,[5,6])]), **collections.UserDict('
1513 'y=9, z=10)')
1514
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001515 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1516 self.assertEqualCallArgs(f, '2, 3, x=8')
1517 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1518 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1519 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1520 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1521 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1522 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1523 '(4,[5,6])]), q=0, **collections.UserDict('
1524 'y=9, z=10)')
1525
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001526 def test_errors(self):
1527 f0 = self.makeCallable('')
1528 f1 = self.makeCallable('a, b')
1529 f2 = self.makeCallable('a, b=1')
1530 # f0 takes no arguments
1531 self.assertEqualException(f0, '1')
1532 self.assertEqualException(f0, 'x=1')
1533 self.assertEqualException(f0, '1,x=1')
1534 # f1 takes exactly 2 arguments
1535 self.assertEqualException(f1, '')
1536 self.assertEqualException(f1, '1')
1537 self.assertEqualException(f1, 'a=2')
1538 self.assertEqualException(f1, 'b=3')
1539 # f2 takes at least 1 argument
1540 self.assertEqualException(f2, '')
1541 self.assertEqualException(f2, 'b=3')
1542 for f in f1, f2:
1543 # f1/f2 takes exactly/at most 2 arguments
1544 self.assertEqualException(f, '2, 3, 4')
1545 self.assertEqualException(f, '1, 2, 3, a=1')
1546 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001547 # XXX: success of this one depends on dict order
1548 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001549 # f got an unexpected keyword argument
1550 self.assertEqualException(f, 'c=2')
1551 self.assertEqualException(f, '2, c=3')
1552 self.assertEqualException(f, '2, 3, c=4')
1553 self.assertEqualException(f, '2, c=4, b=3')
1554 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1555 # f got multiple values for keyword argument
1556 self.assertEqualException(f, '1, a=2')
1557 self.assertEqualException(f, '1, **{"a":2}')
1558 self.assertEqualException(f, '1, 2, b=3')
1559 # XXX: Python inconsistency
1560 # - for functions and bound methods: unexpected keyword 'c'
1561 # - for unbound methods: multiple values for keyword 'a'
1562 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001563 # issue11256:
1564 f3 = self.makeCallable('**c')
1565 self.assertEqualException(f3, '1, 2')
1566 self.assertEqualException(f3, '1, 2, a=1, b=2')
1567 f4 = self.makeCallable('*, a, b=0')
1568 self.assertEqualException(f3, '1, 2')
1569 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001570
Yury Selivanov875df202014-03-27 18:23:03 -04001571 # issue #20816: getcallargs() fails to iterate over non-existent
1572 # kwonlydefaults and raises a wrong TypeError
1573 def f5(*, a): pass
1574 with self.assertRaisesRegex(TypeError,
1575 'missing 1 required keyword-only'):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001576 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001577
1578
Yury Selivanovdccfa132014-03-27 18:42:52 -04001579 # issue20817:
1580 def f6(a, b, c):
1581 pass
1582 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001583 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001584
Dong-hee Naa9cab432018-05-30 00:04:08 +09001585 # bpo-33197
1586 with self.assertRaisesRegex(ValueError,
1587 'variadic keyword parameters cannot'
1588 ' have default values'):
1589 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1590 default=42)
1591 with self.assertRaisesRegex(ValueError,
1592 "value 5 is not a valid Parameter.kind"):
1593 inspect.Parameter("bar", kind=5, default=42)
1594
1595 with self.assertRaisesRegex(TypeError,
1596 'name must be a str, not a int'):
1597 inspect.Parameter(123, kind=4)
1598
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001599class TestGetcallargsMethods(TestGetcallargsFunctions):
1600
1601 def setUp(self):
1602 class Foo(object):
1603 pass
1604 self.cls = Foo
1605 self.inst = Foo()
1606
1607 def makeCallable(self, signature):
1608 assert 'self' not in signature
1609 mk = super(TestGetcallargsMethods, self).makeCallable
1610 self.cls.method = mk('self, ' + signature)
1611 return self.inst.method
1612
1613class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1614
1615 def makeCallable(self, signature):
1616 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1617 return self.cls.method
1618
1619 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1620 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1621 *self._getAssertEqualParams(func, call_params_string, locs))
1622
1623 def assertEqualException(self, func, call_params_string, locs=None):
1624 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1625 *self._getAssertEqualParams(func, call_params_string, locs))
1626
1627 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1628 assert 'inst' not in call_params_string
1629 locs = dict(locs or {}, inst=self.inst)
1630 return (func, 'inst,' + call_params_string, locs)
1631
Michael Foord95fc51d2010-11-20 15:07:30 +00001632
1633class TestGetattrStatic(unittest.TestCase):
1634
1635 def test_basic(self):
1636 class Thing(object):
1637 x = object()
1638
1639 thing = Thing()
1640 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1641 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1642 with self.assertRaises(AttributeError):
1643 inspect.getattr_static(thing, 'y')
1644
1645 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1646
1647 def test_inherited(self):
1648 class Thing(object):
1649 x = object()
1650 class OtherThing(Thing):
1651 pass
1652
1653 something = OtherThing()
1654 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1655
1656 def test_instance_attr(self):
1657 class Thing(object):
1658 x = 2
1659 def __init__(self, x):
1660 self.x = x
1661 thing = Thing(3)
1662 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1663 del thing.x
1664 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1665
1666 def test_property(self):
1667 class Thing(object):
1668 @property
1669 def x(self):
1670 raise AttributeError("I'm pretending not to exist")
1671 thing = Thing()
1672 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1673
Ezio Melotti75cbd732011-04-28 00:59:29 +03001674 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001675 class descriptor(object):
1676 def __get__(*_):
1677 raise AttributeError("I'm pretending not to exist")
1678 desc = descriptor()
1679 class Thing(object):
1680 x = desc
1681 thing = Thing()
1682 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1683
1684 def test_classAttribute(self):
1685 class Thing(object):
1686 x = object()
1687
1688 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1689
Ethan Furmane03ea372013-09-25 07:14:41 -07001690 def test_classVirtualAttribute(self):
1691 class Thing(object):
1692 @types.DynamicClassAttribute
1693 def x(self):
1694 return self._x
1695 _x = object()
1696
1697 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1698
Michael Foord95fc51d2010-11-20 15:07:30 +00001699 def test_inherited_classattribute(self):
1700 class Thing(object):
1701 x = object()
1702 class OtherThing(Thing):
1703 pass
1704
1705 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1706
1707 def test_slots(self):
1708 class Thing(object):
1709 y = 'bar'
1710 __slots__ = ['x']
1711 def __init__(self):
1712 self.x = 'foo'
1713 thing = Thing()
1714 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1715 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1716
1717 del thing.x
1718 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1719
1720 def test_metaclass(self):
1721 class meta(type):
1722 attr = 'foo'
1723 class Thing(object, metaclass=meta):
1724 pass
1725 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1726
1727 class sub(meta):
1728 pass
1729 class OtherThing(object, metaclass=sub):
1730 x = 3
1731 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1732
1733 class OtherOtherThing(OtherThing):
1734 pass
1735 # this test is odd, but it was added as it exposed a bug
1736 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1737
1738 def test_no_dict_no_slots(self):
1739 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1740 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1741
1742 def test_no_dict_no_slots_instance_member(self):
1743 # returns descriptor
1744 with open(__file__) as handle:
1745 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1746
1747 def test_inherited_slots(self):
1748 # returns descriptor
1749 class Thing(object):
1750 __slots__ = ['x']
1751 def __init__(self):
1752 self.x = 'foo'
1753
1754 class OtherThing(Thing):
1755 pass
1756 # it would be nice if this worked...
1757 # we get the descriptor instead of the instance attribute
1758 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1759
1760 def test_descriptor(self):
1761 class descriptor(object):
1762 def __get__(self, instance, owner):
1763 return 3
1764 class Foo(object):
1765 d = descriptor()
1766
1767 foo = Foo()
1768
1769 # for a non data descriptor we return the instance attribute
1770 foo.__dict__['d'] = 1
1771 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1772
Mike53f7a7c2017-12-14 14:04:53 +03001773 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001774 # descriptor
1775 descriptor.__set__ = lambda s, i, v: None
1776 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1777
1778
1779 def test_metaclass_with_descriptor(self):
1780 class descriptor(object):
1781 def __get__(self, instance, owner):
1782 return 3
1783 class meta(type):
1784 d = descriptor()
1785 class Thing(object, metaclass=meta):
1786 pass
1787 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1788
1789
Michael Foordcc7ebb82010-11-20 16:20:16 +00001790 def test_class_as_property(self):
1791 class Base(object):
1792 foo = 3
1793
1794 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001795 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001796 @property
1797 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001798 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001799 return object
1800
Michael Foord35184ed2010-11-20 16:58:30 +00001801 instance = Something()
1802 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1803 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001804 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1805
Michael Foorde5162652010-11-20 16:40:44 +00001806 def test_mro_as_property(self):
1807 class Meta(type):
1808 @property
1809 def __mro__(self):
1810 return (object,)
1811
1812 class Base(object):
1813 foo = 3
1814
1815 class Something(Base, metaclass=Meta):
1816 pass
1817
1818 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1819 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1820
Michael Foorddcebe0f2011-03-15 19:20:44 -04001821 def test_dict_as_property(self):
1822 test = self
1823 test.called = False
1824
1825 class Foo(dict):
1826 a = 3
1827 @property
1828 def __dict__(self):
1829 test.called = True
1830 return {}
1831
1832 foo = Foo()
1833 foo.a = 4
1834 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1835 self.assertFalse(test.called)
1836
1837 def test_custom_object_dict(self):
1838 test = self
1839 test.called = False
1840
1841 class Custom(dict):
1842 def get(self, key, default=None):
1843 test.called = True
1844 super().get(key, default)
1845
1846 class Foo(object):
1847 a = 3
1848 foo = Foo()
1849 foo.__dict__ = Custom()
1850 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1851 self.assertFalse(test.called)
1852
1853 def test_metaclass_dict_as_property(self):
1854 class Meta(type):
1855 @property
1856 def __dict__(self):
1857 self.executed = True
1858
1859 class Thing(metaclass=Meta):
1860 executed = False
1861
1862 def __init__(self):
1863 self.spam = 42
1864
1865 instance = Thing()
1866 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1867 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001868
Michael Foorda51623b2011-12-18 22:01:40 +00001869 def test_module(self):
1870 sentinel = object()
1871 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1872 sentinel)
1873
Michael Foord3ba95f82011-12-22 01:13:37 +00001874 def test_metaclass_with_metaclass_with_dict_as_property(self):
1875 class MetaMeta(type):
1876 @property
1877 def __dict__(self):
1878 self.executed = True
1879 return dict(spam=42)
1880
1881 class Meta(type, metaclass=MetaMeta):
1882 executed = False
1883
1884 class Thing(metaclass=Meta):
1885 pass
1886
1887 with self.assertRaises(AttributeError):
1888 inspect.getattr_static(Thing, "spam")
1889 self.assertFalse(Thing.executed)
1890
Nick Coghlane0f04652010-11-21 03:44:04 +00001891class TestGetGeneratorState(unittest.TestCase):
1892
1893 def setUp(self):
1894 def number_generator():
1895 for number in range(5):
1896 yield number
1897 self.generator = number_generator()
1898
1899 def _generatorstate(self):
1900 return inspect.getgeneratorstate(self.generator)
1901
1902 def test_created(self):
1903 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1904
1905 def test_suspended(self):
1906 next(self.generator)
1907 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1908
1909 def test_closed_after_exhaustion(self):
1910 for i in self.generator:
1911 pass
1912 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1913
1914 def test_closed_after_immediate_exception(self):
1915 with self.assertRaises(RuntimeError):
1916 self.generator.throw(RuntimeError)
1917 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1918
1919 def test_running(self):
1920 # As mentioned on issue #10220, checking for the RUNNING state only
1921 # makes sense inside the generator itself.
1922 # The following generator checks for this by using the closure's
1923 # reference to self and the generator state checking helper method
1924 def running_check_generator():
1925 for number in range(5):
1926 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1927 yield number
1928 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1929 self.generator = running_check_generator()
1930 # Running up to the first yield
1931 next(self.generator)
1932 # Running after the first yield
1933 next(self.generator)
1934
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001935 def test_easy_debugging(self):
1936 # repr() and str() of a generator state should contain the state name
1937 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1938 for name in names:
1939 state = getattr(inspect, name)
1940 self.assertIn(name, repr(state))
1941 self.assertIn(name, str(state))
1942
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001943 def test_getgeneratorlocals(self):
1944 def each(lst, a=None):
1945 b=(1, 2, 3)
1946 for v in lst:
1947 if v == 3:
1948 c = 12
1949 yield v
1950
1951 numbers = each([1, 2, 3])
1952 self.assertEqual(inspect.getgeneratorlocals(numbers),
1953 {'a': None, 'lst': [1, 2, 3]})
1954 next(numbers)
1955 self.assertEqual(inspect.getgeneratorlocals(numbers),
1956 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1957 'b': (1, 2, 3)})
1958 next(numbers)
1959 self.assertEqual(inspect.getgeneratorlocals(numbers),
1960 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1961 'b': (1, 2, 3)})
1962 next(numbers)
1963 self.assertEqual(inspect.getgeneratorlocals(numbers),
1964 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1965 'b': (1, 2, 3), 'c': 12})
1966 try:
1967 next(numbers)
1968 except StopIteration:
1969 pass
1970 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1971
1972 def test_getgeneratorlocals_empty(self):
1973 def yield_one():
1974 yield 1
1975 one = yield_one()
1976 self.assertEqual(inspect.getgeneratorlocals(one), {})
1977 try:
1978 next(one)
1979 except StopIteration:
1980 pass
1981 self.assertEqual(inspect.getgeneratorlocals(one), {})
1982
1983 def test_getgeneratorlocals_error(self):
1984 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1985 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1986 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1987 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1988
Nick Coghlane0f04652010-11-21 03:44:04 +00001989
Yury Selivanov5376ba92015-06-22 12:19:30 -04001990class TestGetCoroutineState(unittest.TestCase):
1991
1992 def setUp(self):
1993 @types.coroutine
1994 def number_coroutine():
1995 for number in range(5):
1996 yield number
1997 async def coroutine():
1998 await number_coroutine()
1999 self.coroutine = coroutine()
2000
2001 def tearDown(self):
2002 self.coroutine.close()
2003
2004 def _coroutinestate(self):
2005 return inspect.getcoroutinestate(self.coroutine)
2006
2007 def test_created(self):
2008 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
2009
2010 def test_suspended(self):
2011 self.coroutine.send(None)
2012 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
2013
2014 def test_closed_after_exhaustion(self):
2015 while True:
2016 try:
2017 self.coroutine.send(None)
2018 except StopIteration:
2019 break
2020
2021 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2022
2023 def test_closed_after_immediate_exception(self):
2024 with self.assertRaises(RuntimeError):
2025 self.coroutine.throw(RuntimeError)
2026 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2027
2028 def test_easy_debugging(self):
2029 # repr() and str() of a coroutine state should contain the state name
2030 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2031 for name in names:
2032 state = getattr(inspect, name)
2033 self.assertIn(name, repr(state))
2034 self.assertIn(name, str(state))
2035
2036 def test_getcoroutinelocals(self):
2037 @types.coroutine
2038 def gencoro():
2039 yield
2040
2041 gencoro = gencoro()
2042 async def func(a=None):
2043 b = 'spam'
2044 await gencoro
2045
2046 coro = func()
2047 self.assertEqual(inspect.getcoroutinelocals(coro),
2048 {'a': None, 'gencoro': gencoro})
2049 coro.send(None)
2050 self.assertEqual(inspect.getcoroutinelocals(coro),
2051 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2052
2053
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002054class MySignature(inspect.Signature):
2055 # Top-level to make it picklable;
2056 # used in test_signature_object_pickle
2057 pass
2058
2059class MyParameter(inspect.Parameter):
2060 # Top-level to make it picklable;
2061 # used in test_signature_object_pickle
2062 pass
2063
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002064
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002065
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002066class TestSignatureObject(unittest.TestCase):
2067 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002068 def signature(func, **kw):
2069 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002070 return (tuple((param.name,
2071 (... if param.default is param.empty else param.default),
2072 (... if param.annotation is param.empty
2073 else param.annotation),
2074 str(param.kind).lower())
2075 for param in sig.parameters.values()),
2076 (... if sig.return_annotation is sig.empty
2077 else sig.return_annotation))
2078
2079 def test_signature_object(self):
2080 S = inspect.Signature
2081 P = inspect.Parameter
2082
2083 self.assertEqual(str(S()), '()')
2084
Yury Selivanov07a9e452014-01-29 10:58:16 -05002085 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002086 pass
2087 sig = inspect.signature(test)
2088 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002089 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002090 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002091 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002092 args = sig.parameters['args']
2093 ko = sig.parameters['ko']
2094 kwargs = sig.parameters['kwargs']
2095
2096 S((po, pk, args, ko, kwargs))
2097
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002098 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002099 S((pk, po, args, ko, kwargs))
2100
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002101 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002102 S((po, args, pk, ko, kwargs))
2103
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002104 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002105 S((args, po, pk, ko, kwargs))
2106
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002107 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002108 S((po, pk, args, kwargs, ko))
2109
2110 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002111 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002112 S((po, pk, args, kwargs2, ko))
2113
Yury Selivanov07a9e452014-01-29 10:58:16 -05002114 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2115 S((pod, po))
2116
2117 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2118 S((po, pkd, pk))
2119
2120 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2121 S((pkd, pk))
2122
Yury Selivanov374375d2014-03-27 12:41:53 -04002123 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002124 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002125
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002126 def test_signature_object_pickle(self):
2127 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2128 foo_partial = functools.partial(foo, a=1)
2129
2130 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002131
2132 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2133 with self.subTest(pickle_ver=ver, subclass=False):
2134 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2135 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002136
2137 # Test that basic sub-classing works
2138 sig = inspect.signature(foo)
2139 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2140 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2141 mysig = MySignature().replace(parameters=myparams.values(),
2142 return_annotation=sig.return_annotation)
2143 self.assertTrue(isinstance(mysig, MySignature))
2144 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2145
2146 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2147 with self.subTest(pickle_ver=ver, subclass=True):
2148 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2149 self.assertEqual(mysig, sig_pickled)
2150 self.assertTrue(isinstance(sig_pickled, MySignature))
2151 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2152 MyParameter))
2153
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002154 def test_signature_immutability(self):
2155 def test(a):
2156 pass
2157 sig = inspect.signature(test)
2158
2159 with self.assertRaises(AttributeError):
2160 sig.foo = 'bar'
2161
2162 with self.assertRaises(TypeError):
2163 sig.parameters['a'] = None
2164
2165 def test_signature_on_noarg(self):
2166 def test():
2167 pass
2168 self.assertEqual(self.signature(test), ((), ...))
2169
2170 def test_signature_on_wargs(self):
2171 def test(a, b:'foo') -> 123:
2172 pass
2173 self.assertEqual(self.signature(test),
2174 ((('a', ..., ..., "positional_or_keyword"),
2175 ('b', ..., 'foo', "positional_or_keyword")),
2176 123))
2177
2178 def test_signature_on_wkwonly(self):
2179 def test(*, a:float, b:str) -> int:
2180 pass
2181 self.assertEqual(self.signature(test),
2182 ((('a', ..., float, "keyword_only"),
2183 ('b', ..., str, "keyword_only")),
2184 int))
2185
2186 def test_signature_on_complex_args(self):
2187 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2188 pass
2189 self.assertEqual(self.signature(test),
2190 ((('a', ..., ..., "positional_or_keyword"),
2191 ('b', 10, 'foo', "positional_or_keyword"),
2192 ('args', ..., 'bar', "var_positional"),
2193 ('spam', ..., 'baz', "keyword_only"),
2194 ('ham', 123, ..., "keyword_only"),
2195 ('kwargs', ..., int, "var_keyword")),
2196 ...))
2197
Dong-hee Na378d7062017-05-18 04:00:51 +09002198 def test_signature_without_self(self):
2199 def test_args_only(*args): # NOQA
2200 pass
2201
2202 def test_args_kwargs_only(*args, **kwargs): # NOQA
2203 pass
2204
2205 class A:
2206 @classmethod
2207 def test_classmethod(*args): # NOQA
2208 pass
2209
2210 @staticmethod
2211 def test_staticmethod(*args): # NOQA
2212 pass
2213
2214 f1 = functools.partialmethod((test_classmethod), 1)
2215 f2 = functools.partialmethod((test_args_only), 1)
2216 f3 = functools.partialmethod((test_staticmethod), 1)
2217 f4 = functools.partialmethod((test_args_kwargs_only),1)
2218
2219 self.assertEqual(self.signature(test_args_only),
2220 ((('args', ..., ..., 'var_positional'),), ...))
2221 self.assertEqual(self.signature(test_args_kwargs_only),
2222 ((('args', ..., ..., 'var_positional'),
2223 ('kwargs', ..., ..., 'var_keyword')), ...))
2224 self.assertEqual(self.signature(A.f1),
2225 ((('args', ..., ..., 'var_positional'),), ...))
2226 self.assertEqual(self.signature(A.f2),
2227 ((('args', ..., ..., 'var_positional'),), ...))
2228 self.assertEqual(self.signature(A.f3),
2229 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002230 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002231 ((('args', ..., ..., 'var_positional'),
2232 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002233 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002234 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2235 "Signature information for builtins requires docstrings")
2236 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002237 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002238
Larry Hastings5c661892014-01-24 06:17:25 -08002239 def test_unbound_method(o):
2240 """Use this to test unbound methods (things that should have a self)"""
2241 signature = inspect.signature(o)
2242 self.assertTrue(isinstance(signature, inspect.Signature))
2243 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2244 return signature
2245
2246 def test_callable(o):
2247 """Use this to test bound methods or normal callables (things that don't expect self)"""
2248 signature = inspect.signature(o)
2249 self.assertTrue(isinstance(signature, inspect.Signature))
2250 if signature.parameters:
2251 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2252 return signature
2253
2254 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002255 def p(name): return signature.parameters[name].default
2256 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002257 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002258 self.assertEqual(p('d'), 3.14)
2259 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002260 self.assertEqual(p('n'), None)
2261 self.assertEqual(p('t'), True)
2262 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002263 self.assertEqual(p('local'), 3)
2264 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002265 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002266
Larry Hastings5c661892014-01-24 06:17:25 -08002267 test_callable(object)
2268
2269 # normal method
2270 # (PyMethodDescr_Type, "method_descriptor")
2271 test_unbound_method(_pickle.Pickler.dump)
2272 d = _pickle.Pickler(io.StringIO())
2273 test_callable(d.dump)
2274
2275 # static method
Serhiy Storchakad322abb2019-09-14 13:31:50 +03002276 test_callable(bytes.maketrans)
2277 test_callable(b'abc'.maketrans)
Larry Hastings5c661892014-01-24 06:17:25 -08002278
2279 # class method
2280 test_callable(dict.fromkeys)
2281 test_callable({}.fromkeys)
2282
2283 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2284 test_unbound_method(type.__call__)
2285 test_unbound_method(int.__add__)
2286 test_callable((3).__add__)
2287
2288 # _PyMethodWrapper_Type
2289 # support for 'method-wrapper'
2290 test_callable(min.__call__)
2291
Larry Hastings2623c8c2014-02-08 22:15:29 -08002292 # This doesn't work now.
2293 # (We don't have a valid signature for "type" in 3.4)
2294 with self.assertRaisesRegex(ValueError, "no signature found"):
2295 class ThisWorksNow:
2296 __call__ = type
2297 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002298
Yury Selivanov056e2652014-03-02 12:25:27 -05002299 # Regression test for issue #20786
2300 test_unbound_method(dict.__delitem__)
2301 test_unbound_method(property.__delete__)
2302
Zachary Ware8ef887c2015-04-13 18:22:35 -05002303 # Regression test for issue #20586
2304 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2305
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002306 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002307 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2308 "Signature information for builtins requires docstrings")
2309 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002310 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002311 func = _testcapi.docstring_with_signature_with_defaults
2312
2313 def decorator(func):
2314 @functools.wraps(func)
2315 def wrapper(*args, **kwargs) -> int:
2316 return func(*args, **kwargs)
2317 return wrapper
2318
2319 decorated_func = decorator(func)
2320
2321 self.assertEqual(inspect.signature(func),
2322 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002323
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002324 def wrapper_like(*args, **kwargs) -> int: pass
2325 self.assertEqual(inspect.signature(decorated_func,
2326 follow_wrapped=False),
2327 inspect.signature(wrapper_like))
2328
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002329 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002330 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002331 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002332 with self.assertRaisesRegex(ValueError,
2333 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002334 inspect.signature(_testcapi.docstring_no_signature)
2335
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002336 with self.assertRaisesRegex(ValueError,
2337 'no signature found for builtin'):
2338 inspect.signature(str)
2339
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002340 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002341 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002342 inspect.signature(42)
2343
Yury Selivanov63da7c72014-01-31 14:48:37 -05002344 def test_signature_from_functionlike_object(self):
2345 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2346 pass
2347
2348 class funclike:
2349 # Has to be callable, and have correct
2350 # __code__, __annotations__, __defaults__, __name__,
2351 # and __kwdefaults__ attributes
2352
2353 def __init__(self, func):
2354 self.__name__ = func.__name__
2355 self.__code__ = func.__code__
2356 self.__annotations__ = func.__annotations__
2357 self.__defaults__ = func.__defaults__
2358 self.__kwdefaults__ = func.__kwdefaults__
2359 self.func = func
2360
2361 def __call__(self, *args, **kwargs):
2362 return self.func(*args, **kwargs)
2363
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002364 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002365
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002366 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002367 self.assertEqual(sig_funclike, sig_func)
2368
2369 sig_funclike = inspect.signature(funclike(func))
2370 self.assertEqual(sig_funclike, sig_func)
2371
2372 # If object is not a duck type of function, then
2373 # signature will try to get a signature for its '__call__'
2374 # method
2375 fl = funclike(func)
2376 del fl.__defaults__
2377 self.assertEqual(self.signature(fl),
2378 ((('args', ..., ..., "var_positional"),
2379 ('kwargs', ..., ..., "var_keyword")),
2380 ...))
2381
Yury Selivanova773de02014-02-21 18:30:53 -05002382 # Test with cython-like builtins:
2383 _orig_isdesc = inspect.ismethoddescriptor
2384 def _isdesc(obj):
2385 if hasattr(obj, '_builtinmock'):
2386 return True
2387 return _orig_isdesc(obj)
2388
2389 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2390 builtin_func = funclike(func)
2391 # Make sure that our mock setup is working
2392 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2393 builtin_func._builtinmock = True
2394 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2395 self.assertEqual(inspect.signature(builtin_func), sig_func)
2396
Yury Selivanov63da7c72014-01-31 14:48:37 -05002397 def test_signature_functionlike_class(self):
2398 # We only want to duck type function-like objects,
2399 # not classes.
2400
2401 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2402 pass
2403
2404 class funclike:
2405 def __init__(self, marker):
2406 pass
2407
2408 __name__ = func.__name__
2409 __code__ = func.__code__
2410 __annotations__ = func.__annotations__
2411 __defaults__ = func.__defaults__
2412 __kwdefaults__ = func.__kwdefaults__
2413
Yury Selivanov63da7c72014-01-31 14:48:37 -05002414 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2415
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002416 def test_signature_on_method(self):
2417 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002418 def __init__(*args):
2419 pass
2420 def m1(self, arg1, arg2=1) -> int:
2421 pass
2422 def m2(*args):
2423 pass
2424 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002425 pass
2426
Yury Selivanov62560fb2014-01-28 12:26:24 -05002427 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002428 ((('arg1', ..., ..., "positional_or_keyword"),
2429 ('arg2', 1, ..., "positional_or_keyword")),
2430 int))
2431
Yury Selivanov62560fb2014-01-28 12:26:24 -05002432 self.assertEqual(self.signature(Test().m2),
2433 ((('args', ..., ..., "var_positional"),),
2434 ...))
2435
2436 self.assertEqual(self.signature(Test),
2437 ((('args', ..., ..., "var_positional"),),
2438 ...))
2439
2440 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2441 self.signature(Test())
2442
Yury Selivanov46c759d2015-05-27 21:56:53 -04002443 def test_signature_wrapped_bound_method(self):
2444 # Issue 24298
2445 class Test:
2446 def m1(self, arg1, arg2=1) -> int:
2447 pass
2448 @functools.wraps(Test().m1)
2449 def m1d(*args, **kwargs):
2450 pass
2451 self.assertEqual(self.signature(m1d),
2452 ((('arg1', ..., ..., "positional_or_keyword"),
2453 ('arg2', 1, ..., "positional_or_keyword")),
2454 int))
2455
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002456 def test_signature_on_classmethod(self):
2457 class Test:
2458 @classmethod
2459 def foo(cls, arg1, *, arg2=1):
2460 pass
2461
2462 meth = Test().foo
2463 self.assertEqual(self.signature(meth),
2464 ((('arg1', ..., ..., "positional_or_keyword"),
2465 ('arg2', 1, ..., "keyword_only")),
2466 ...))
2467
2468 meth = Test.foo
2469 self.assertEqual(self.signature(meth),
2470 ((('arg1', ..., ..., "positional_or_keyword"),
2471 ('arg2', 1, ..., "keyword_only")),
2472 ...))
2473
2474 def test_signature_on_staticmethod(self):
2475 class Test:
2476 @staticmethod
2477 def foo(cls, *, arg):
2478 pass
2479
2480 meth = Test().foo
2481 self.assertEqual(self.signature(meth),
2482 ((('cls', ..., ..., "positional_or_keyword"),
2483 ('arg', ..., ..., "keyword_only")),
2484 ...))
2485
2486 meth = Test.foo
2487 self.assertEqual(self.signature(meth),
2488 ((('cls', ..., ..., "positional_or_keyword"),
2489 ('arg', ..., ..., "keyword_only")),
2490 ...))
2491
2492 def test_signature_on_partial(self):
2493 from functools import partial
2494
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002495 Parameter = inspect.Parameter
2496
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002497 def test():
2498 pass
2499
2500 self.assertEqual(self.signature(partial(test)), ((), ...))
2501
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002502 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002503 inspect.signature(partial(test, 1))
2504
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002505 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002506 inspect.signature(partial(test, a=1))
2507
2508 def test(a, b, *, c, d):
2509 pass
2510
2511 self.assertEqual(self.signature(partial(test)),
2512 ((('a', ..., ..., "positional_or_keyword"),
2513 ('b', ..., ..., "positional_or_keyword"),
2514 ('c', ..., ..., "keyword_only"),
2515 ('d', ..., ..., "keyword_only")),
2516 ...))
2517
2518 self.assertEqual(self.signature(partial(test, 1)),
2519 ((('b', ..., ..., "positional_or_keyword"),
2520 ('c', ..., ..., "keyword_only"),
2521 ('d', ..., ..., "keyword_only")),
2522 ...))
2523
2524 self.assertEqual(self.signature(partial(test, 1, c=2)),
2525 ((('b', ..., ..., "positional_or_keyword"),
2526 ('c', 2, ..., "keyword_only"),
2527 ('d', ..., ..., "keyword_only")),
2528 ...))
2529
2530 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2531 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002532 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002533 ('c', 2, ..., "keyword_only"),
2534 ('d', ..., ..., "keyword_only")),
2535 ...))
2536
2537 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002538 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002539 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002540 ('d', ..., ..., "keyword_only")),
2541 ...))
2542
2543 self.assertEqual(self.signature(partial(test, a=1)),
2544 ((('a', 1, ..., "keyword_only"),
2545 ('b', ..., ..., "keyword_only"),
2546 ('c', ..., ..., "keyword_only"),
2547 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002548 ...))
2549
2550 def test(a, *args, b, **kwargs):
2551 pass
2552
2553 self.assertEqual(self.signature(partial(test, 1)),
2554 ((('args', ..., ..., "var_positional"),
2555 ('b', ..., ..., "keyword_only"),
2556 ('kwargs', ..., ..., "var_keyword")),
2557 ...))
2558
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002559 self.assertEqual(self.signature(partial(test, a=1)),
2560 ((('a', 1, ..., "keyword_only"),
2561 ('b', ..., ..., "keyword_only"),
2562 ('kwargs', ..., ..., "var_keyword")),
2563 ...))
2564
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002565 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2566 ((('args', ..., ..., "var_positional"),
2567 ('b', ..., ..., "keyword_only"),
2568 ('kwargs', ..., ..., "var_keyword")),
2569 ...))
2570
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002571 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2572 ((('args', ..., ..., "var_positional"),
2573 ('b', ..., ..., "keyword_only"),
2574 ('kwargs', ..., ..., "var_keyword")),
2575 ...))
2576
2577 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2578 ((('args', ..., ..., "var_positional"),
2579 ('b', 0, ..., "keyword_only"),
2580 ('kwargs', ..., ..., "var_keyword")),
2581 ...))
2582
2583 self.assertEqual(self.signature(partial(test, b=0)),
2584 ((('a', ..., ..., "positional_or_keyword"),
2585 ('args', ..., ..., "var_positional"),
2586 ('b', 0, ..., "keyword_only"),
2587 ('kwargs', ..., ..., "var_keyword")),
2588 ...))
2589
2590 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2591 ((('a', ..., ..., "positional_or_keyword"),
2592 ('args', ..., ..., "var_positional"),
2593 ('b', 0, ..., "keyword_only"),
2594 ('kwargs', ..., ..., "var_keyword")),
2595 ...))
2596
2597 def test(a, b, c:int) -> 42:
2598 pass
2599
2600 sig = test.__signature__ = inspect.signature(test)
2601
2602 self.assertEqual(self.signature(partial(partial(test, 1))),
2603 ((('b', ..., ..., "positional_or_keyword"),
2604 ('c', ..., int, "positional_or_keyword")),
2605 42))
2606
2607 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2608 ((('c', ..., int, "positional_or_keyword"),),
2609 42))
2610
2611 psig = inspect.signature(partial(partial(test, 1), 2))
2612
2613 def foo(a):
2614 return a
2615 _foo = partial(partial(foo, a=10), a=20)
2616 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002617 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002618 ...))
2619 # check that we don't have any side-effects in signature(),
2620 # and the partial object is still functioning
2621 self.assertEqual(_foo(), 20)
2622
2623 def foo(a, b, c):
2624 return a, b, c
2625 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002626
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002627 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002628 ((('b', 30, ..., "keyword_only"),
2629 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002630 ...))
2631 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002632
2633 def foo(a, b, c, *, d):
2634 return a, b, c, d
2635 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2636 self.assertEqual(self.signature(_foo),
2637 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002638 ('b', 10, ..., "keyword_only"),
2639 ('c', 20, ..., "keyword_only"),
2640 ('d', 30, ..., "keyword_only"),
2641 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002642 ...))
2643 ba = inspect.signature(_foo).bind(a=200, b=11)
2644 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2645
2646 def foo(a=1, b=2, c=3):
2647 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002648 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2649
2650 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002651 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002652
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002653 ba = inspect.signature(_foo).bind(11, 12)
2654 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002655
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002656 ba = inspect.signature(_foo).bind(11, b=12)
2657 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002658
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002659 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002660 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2661
2662 _foo = partial(_foo, b=10, c=20)
2663 ba = inspect.signature(_foo).bind(12)
2664 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2665
2666
2667 def foo(a, b, c, d, **kwargs):
2668 pass
2669 sig = inspect.signature(foo)
2670 params = sig.parameters.copy()
2671 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2672 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2673 foo.__signature__ = inspect.Signature(params.values())
2674 sig = inspect.signature(foo)
2675 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2676
2677 self.assertEqual(self.signature(partial(foo, 1)),
2678 ((('b', ..., ..., 'positional_only'),
2679 ('c', ..., ..., 'positional_or_keyword'),
2680 ('d', ..., ..., 'positional_or_keyword'),
2681 ('kwargs', ..., ..., 'var_keyword')),
2682 ...))
2683
2684 self.assertEqual(self.signature(partial(foo, 1, 2)),
2685 ((('c', ..., ..., 'positional_or_keyword'),
2686 ('d', ..., ..., 'positional_or_keyword'),
2687 ('kwargs', ..., ..., 'var_keyword')),
2688 ...))
2689
2690 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2691 ((('d', ..., ..., 'positional_or_keyword'),
2692 ('kwargs', ..., ..., 'var_keyword')),
2693 ...))
2694
2695 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2696 ((('c', 3, ..., 'keyword_only'),
2697 ('d', ..., ..., 'keyword_only'),
2698 ('kwargs', ..., ..., 'var_keyword')),
2699 ...))
2700
2701 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2702 ((('b', ..., ..., 'positional_only'),
2703 ('c', 3, ..., 'keyword_only'),
2704 ('d', ..., ..., 'keyword_only'),
2705 ('kwargs', ..., ..., 'var_keyword')),
2706 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002707
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002708 def test_signature_on_partialmethod(self):
2709 from functools import partialmethod
2710
2711 class Spam:
2712 def test():
2713 pass
2714 ham = partialmethod(test)
2715
2716 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2717 inspect.signature(Spam.ham)
2718
2719 class Spam:
2720 def test(it, a, *, c) -> 'spam':
2721 pass
2722 ham = partialmethod(test, c=1)
2723
2724 self.assertEqual(self.signature(Spam.ham),
2725 ((('it', ..., ..., 'positional_or_keyword'),
2726 ('a', ..., ..., 'positional_or_keyword'),
2727 ('c', 1, ..., 'keyword_only')),
2728 'spam'))
2729
2730 self.assertEqual(self.signature(Spam().ham),
2731 ((('a', ..., ..., 'positional_or_keyword'),
2732 ('c', 1, ..., 'keyword_only')),
2733 'spam'))
2734
Yury Selivanov8a387212018-03-06 12:59:45 -05002735 class Spam:
2736 def test(self: 'anno', x):
2737 pass
2738
2739 g = partialmethod(test, 1)
2740
2741 self.assertEqual(self.signature(Spam.g),
2742 ((('self', ..., 'anno', 'positional_or_keyword'),),
2743 ...))
2744
Yury Selivanov0486f812014-01-29 12:18:59 -05002745 def test_signature_on_fake_partialmethod(self):
2746 def foo(a): pass
2747 foo._partialmethod = 'spam'
2748 self.assertEqual(str(inspect.signature(foo)), '(a)')
2749
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002750 def test_signature_on_decorated(self):
2751 import functools
2752
2753 def decorator(func):
2754 @functools.wraps(func)
2755 def wrapper(*args, **kwargs) -> int:
2756 return func(*args, **kwargs)
2757 return wrapper
2758
2759 class Foo:
2760 @decorator
2761 def bar(self, a, b):
2762 pass
2763
2764 self.assertEqual(self.signature(Foo.bar),
2765 ((('self', ..., ..., "positional_or_keyword"),
2766 ('a', ..., ..., "positional_or_keyword"),
2767 ('b', ..., ..., "positional_or_keyword")),
2768 ...))
2769
2770 self.assertEqual(self.signature(Foo().bar),
2771 ((('a', ..., ..., "positional_or_keyword"),
2772 ('b', ..., ..., "positional_or_keyword")),
2773 ...))
2774
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002775 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2776 ((('args', ..., ..., "var_positional"),
2777 ('kwargs', ..., ..., "var_keyword")),
2778 ...)) # functools.wraps will copy __annotations__
2779 # from "func" to "wrapper", hence no
2780 # return_annotation
2781
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002782 # Test that we handle method wrappers correctly
2783 def decorator(func):
2784 @functools.wraps(func)
2785 def wrapper(*args, **kwargs) -> int:
2786 return func(42, *args, **kwargs)
2787 sig = inspect.signature(func)
2788 new_params = tuple(sig.parameters.values())[1:]
2789 wrapper.__signature__ = sig.replace(parameters=new_params)
2790 return wrapper
2791
2792 class Foo:
2793 @decorator
2794 def __call__(self, a, b):
2795 pass
2796
2797 self.assertEqual(self.signature(Foo.__call__),
2798 ((('a', ..., ..., "positional_or_keyword"),
2799 ('b', ..., ..., "positional_or_keyword")),
2800 ...))
2801
2802 self.assertEqual(self.signature(Foo().__call__),
2803 ((('b', ..., ..., "positional_or_keyword"),),
2804 ...))
2805
Nick Coghlane8c45d62013-07-28 20:00:01 +10002806 # Test we handle __signature__ partway down the wrapper stack
2807 def wrapped_foo_call():
2808 pass
2809 wrapped_foo_call.__wrapped__ = Foo.__call__
2810
2811 self.assertEqual(self.signature(wrapped_foo_call),
2812 ((('a', ..., ..., "positional_or_keyword"),
2813 ('b', ..., ..., "positional_or_keyword")),
2814 ...))
2815
2816
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002817 def test_signature_on_class(self):
2818 class C:
2819 def __init__(self, a):
2820 pass
2821
2822 self.assertEqual(self.signature(C),
2823 ((('a', ..., ..., "positional_or_keyword"),),
2824 ...))
2825
2826 class CM(type):
2827 def __call__(cls, a):
2828 pass
2829 class C(metaclass=CM):
2830 def __init__(self, b):
2831 pass
2832
2833 self.assertEqual(self.signature(C),
2834 ((('a', ..., ..., "positional_or_keyword"),),
2835 ...))
2836
2837 class CM(type):
2838 def __new__(mcls, name, bases, dct, *, foo=1):
2839 return super().__new__(mcls, name, bases, dct)
2840 class C(metaclass=CM):
2841 def __init__(self, b):
2842 pass
2843
2844 self.assertEqual(self.signature(C),
2845 ((('b', ..., ..., "positional_or_keyword"),),
2846 ...))
2847
2848 self.assertEqual(self.signature(CM),
2849 ((('name', ..., ..., "positional_or_keyword"),
2850 ('bases', ..., ..., "positional_or_keyword"),
2851 ('dct', ..., ..., "positional_or_keyword"),
2852 ('foo', 1, ..., "keyword_only")),
2853 ...))
2854
2855 class CMM(type):
2856 def __new__(mcls, name, bases, dct, *, foo=1):
2857 return super().__new__(mcls, name, bases, dct)
2858 def __call__(cls, nm, bs, dt):
2859 return type(nm, bs, dt)
2860 class CM(type, metaclass=CMM):
2861 def __new__(mcls, name, bases, dct, *, bar=2):
2862 return super().__new__(mcls, name, bases, dct)
2863 class C(metaclass=CM):
2864 def __init__(self, b):
2865 pass
2866
2867 self.assertEqual(self.signature(CMM),
2868 ((('name', ..., ..., "positional_or_keyword"),
2869 ('bases', ..., ..., "positional_or_keyword"),
2870 ('dct', ..., ..., "positional_or_keyword"),
2871 ('foo', 1, ..., "keyword_only")),
2872 ...))
2873
2874 self.assertEqual(self.signature(CM),
2875 ((('nm', ..., ..., "positional_or_keyword"),
2876 ('bs', ..., ..., "positional_or_keyword"),
2877 ('dt', ..., ..., "positional_or_keyword")),
2878 ...))
2879
2880 self.assertEqual(self.signature(C),
2881 ((('b', ..., ..., "positional_or_keyword"),),
2882 ...))
2883
2884 class CM(type):
2885 def __init__(cls, name, bases, dct, *, bar=2):
2886 return super().__init__(name, bases, dct)
2887 class C(metaclass=CM):
2888 def __init__(self, b):
2889 pass
2890
2891 self.assertEqual(self.signature(CM),
2892 ((('name', ..., ..., "positional_or_keyword"),
2893 ('bases', ..., ..., "positional_or_keyword"),
2894 ('dct', ..., ..., "positional_or_keyword"),
2895 ('bar', 2, ..., "keyword_only")),
2896 ...))
2897
Yury Selivanov145dff82014-02-01 13:49:29 -05002898 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2899 "Signature information for builtins requires docstrings")
2900 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002901 # Test classes without user-defined __init__ or __new__
2902 class C: pass
2903 self.assertEqual(str(inspect.signature(C)), '()')
2904 class D(C): pass
2905 self.assertEqual(str(inspect.signature(D)), '()')
2906
2907 # Test meta-classes without user-defined __init__ or __new__
2908 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002909 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002910 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2911 self.assertEqual(inspect.signature(C), None)
2912 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2913 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002914
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002915 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2916 "Signature information for builtins requires docstrings")
2917 def test_signature_on_builtin_class(self):
Antoine Pitrou91f43802019-05-26 17:10:09 +02002918 expected = ('(file, protocol=None, fix_imports=True, '
2919 'buffer_callback=None)')
2920 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002921
2922 class P(_pickle.Pickler): pass
2923 class EmptyTrait: pass
2924 class P2(EmptyTrait, P): pass
Antoine Pitrou91f43802019-05-26 17:10:09 +02002925 self.assertEqual(str(inspect.signature(P)), expected)
2926 self.assertEqual(str(inspect.signature(P2)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002927
2928 class P3(P2):
2929 def __init__(self, spam):
2930 pass
2931 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2932
2933 class MetaP(type):
2934 def __call__(cls, foo, bar):
2935 pass
2936 class P4(P2, metaclass=MetaP):
2937 pass
2938 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2939
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002940 def test_signature_on_callable_objects(self):
2941 class Foo:
2942 def __call__(self, a):
2943 pass
2944
2945 self.assertEqual(self.signature(Foo()),
2946 ((('a', ..., ..., "positional_or_keyword"),),
2947 ...))
2948
2949 class Spam:
2950 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002951 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002952 inspect.signature(Spam())
2953
2954 class Bar(Spam, Foo):
2955 pass
2956
2957 self.assertEqual(self.signature(Bar()),
2958 ((('a', ..., ..., "positional_or_keyword"),),
2959 ...))
2960
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002961 class Wrapped:
2962 pass
2963 Wrapped.__wrapped__ = lambda a: None
2964 self.assertEqual(self.signature(Wrapped),
2965 ((('a', ..., ..., "positional_or_keyword"),),
2966 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002967 # wrapper loop:
2968 Wrapped.__wrapped__ = Wrapped
2969 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2970 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002971
2972 def test_signature_on_lambdas(self):
2973 self.assertEqual(self.signature((lambda a=10: a)),
2974 ((('a', 10, ..., "positional_or_keyword"),),
2975 ...))
2976
2977 def test_signature_equality(self):
2978 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002979 self.assertFalse(inspect.signature(foo) == 42)
2980 self.assertTrue(inspect.signature(foo) != 42)
2981 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2982 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002983
2984 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002985 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2986 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002987 self.assertEqual(
2988 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002989
2990 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002991 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2992 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002993 self.assertNotEqual(
2994 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002995
2996 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002997 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2998 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002999 self.assertNotEqual(
3000 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003001
3002 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003003 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3004 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003005 self.assertNotEqual(
3006 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003007
3008 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003009 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3010 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003011 self.assertNotEqual(
3012 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003013
3014 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003015 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3016 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003017 self.assertNotEqual(
3018 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003019 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003020 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3021 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003022 self.assertNotEqual(
3023 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003024
3025 def foo(*, a, b, c): pass
3026 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003027 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3028 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003029 self.assertEqual(
3030 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003031
3032 def foo(*, a=1, b, c): pass
3033 def bar(*, c, b, a=1): 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
3039 def foo(pos, *, a=1, b, c): pass
3040 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003041 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3042 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003043 self.assertEqual(
3044 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003045
3046 def foo(pos, *, a, b, c): pass
3047 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003048 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3049 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003050 self.assertNotEqual(
3051 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003052
3053 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3054 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003055 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3056 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003057 self.assertEqual(
3058 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003059
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003060 def test_signature_hashable(self):
3061 S = inspect.Signature
3062 P = inspect.Parameter
3063
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003064 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003065 foo_sig = inspect.signature(foo)
3066
3067 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3068
3069 self.assertEqual(hash(foo_sig), hash(manual_sig))
3070 self.assertNotEqual(hash(foo_sig),
3071 hash(manual_sig.replace(return_annotation='spam')))
3072
3073 def bar(a) -> 1: pass
3074 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3075
3076 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003077 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003078 hash(inspect.signature(foo))
3079
3080 def foo(a) -> {}: pass
3081 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3082 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003083
3084 def test_signature_str(self):
3085 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3086 pass
3087 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003088 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003089
3090 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3091 pass
3092 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003093 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003094
3095 def foo():
3096 pass
3097 self.assertEqual(str(inspect.signature(foo)), '()')
3098
3099 def test_signature_str_positional_only(self):
3100 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003101 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003102
3103 def test(a_po, *, b, **kwargs):
3104 return a_po, kwargs
3105
3106 sig = inspect.signature(test)
3107 new_params = list(sig.parameters.values())
3108 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3109 test.__signature__ = sig.replace(parameters=new_params)
3110
3111 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003112 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003113
Yury Selivanov2393dca2014-01-27 15:07:58 -05003114 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3115 '(foo, /)')
3116
3117 self.assertEqual(str(S(parameters=[
3118 P('foo', P.POSITIONAL_ONLY),
3119 P('bar', P.VAR_KEYWORD)])),
3120 '(foo, /, **bar)')
3121
3122 self.assertEqual(str(S(parameters=[
3123 P('foo', P.POSITIONAL_ONLY),
3124 P('bar', P.VAR_POSITIONAL)])),
3125 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003126
3127 def test_signature_replace_anno(self):
3128 def test() -> 42:
3129 pass
3130
3131 sig = inspect.signature(test)
3132 sig = sig.replace(return_annotation=None)
3133 self.assertIs(sig.return_annotation, None)
3134 sig = sig.replace(return_annotation=sig.empty)
3135 self.assertIs(sig.return_annotation, sig.empty)
3136 sig = sig.replace(return_annotation=42)
3137 self.assertEqual(sig.return_annotation, 42)
3138 self.assertEqual(sig, inspect.signature(test))
3139
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003140 def test_signature_on_mangled_parameters(self):
3141 class Spam:
3142 def foo(self, __p1:1=2, *, __p2:2=3):
3143 pass
3144 class Ham(Spam):
3145 pass
3146
3147 self.assertEqual(self.signature(Spam.foo),
3148 ((('self', ..., ..., "positional_or_keyword"),
3149 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3150 ('_Spam__p2', 3, 2, "keyword_only")),
3151 ...))
3152
3153 self.assertEqual(self.signature(Spam.foo),
3154 self.signature(Ham.foo))
3155
Yury Selivanovda396452014-03-27 12:09:24 -04003156 def test_signature_from_callable_python_obj(self):
3157 class MySignature(inspect.Signature): pass
3158 def foo(a, *, b:1): pass
3159 foo_sig = MySignature.from_callable(foo)
Miss Islington (bot)cf257652019-09-13 10:42:35 -07003160 self.assertIsInstance(foo_sig, MySignature)
3161
3162 def test_signature_from_callable_class(self):
3163 # A regression test for a class inheriting its signature from `object`.
3164 class MySignature(inspect.Signature): pass
3165 class foo: pass
3166 foo_sig = MySignature.from_callable(foo)
3167 self.assertIsInstance(foo_sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003168
3169 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3170 "Signature information for builtins requires docstrings")
3171 def test_signature_from_callable_builtin_obj(self):
3172 class MySignature(inspect.Signature): pass
3173 sig = MySignature.from_callable(_pickle.Pickler)
Miss Islington (bot)cf257652019-09-13 10:42:35 -07003174 self.assertIsInstance(sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003175
larryhastingsf36ba122018-01-28 11:13:09 -08003176 def test_signature_definition_order_preserved_on_kwonly(self):
3177 for fn in signatures_with_lexicographic_keyword_only_parameters():
3178 signature = inspect.signature(fn)
3179 l = list(signature.parameters)
3180 sorted_l = sorted(l)
3181 self.assertTrue(l)
3182 self.assertEqual(l, sorted_l)
3183 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3184 l = list(signature.parameters)
3185 self.assertEqual(l, unsorted_keyword_only_parameters)
3186
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003187
3188class TestParameterObject(unittest.TestCase):
3189 def test_signature_parameter_kinds(self):
3190 P = inspect.Parameter
3191 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3192 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3193
3194 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3195 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3196
3197 def test_signature_parameter_object(self):
3198 p = inspect.Parameter('foo', default=10,
3199 kind=inspect.Parameter.POSITIONAL_ONLY)
3200 self.assertEqual(p.name, 'foo')
3201 self.assertEqual(p.default, 10)
3202 self.assertIs(p.annotation, p.empty)
3203 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3204
Dong-hee Naa9cab432018-05-30 00:04:08 +09003205 with self.assertRaisesRegex(ValueError, "value '123' is "
3206 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003207 inspect.Parameter('foo', default=10, kind='123')
3208
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003209 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003210 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3211
Yury Selivanov2393dca2014-01-27 15:07:58 -05003212 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003213 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3214
Yury Selivanov2393dca2014-01-27 15:07:58 -05003215 with self.assertRaisesRegex(ValueError,
3216 'is not a valid parameter name'):
3217 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3218
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003219 with self.assertRaisesRegex(ValueError,
3220 'is not a valid parameter name'):
3221 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3222
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003223 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003224 inspect.Parameter('a', default=42,
3225 kind=inspect.Parameter.VAR_KEYWORD)
3226
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003227 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003228 inspect.Parameter('a', default=42,
3229 kind=inspect.Parameter.VAR_POSITIONAL)
3230
3231 p = inspect.Parameter('a', default=42,
3232 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003233 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003234 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3235
3236 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003237 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003238
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003239 def test_signature_parameter_hashable(self):
3240 P = inspect.Parameter
3241 foo = P('foo', kind=P.POSITIONAL_ONLY)
3242 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3243 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3244 default=42)))
3245 self.assertNotEqual(hash(foo),
3246 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3247
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003248 def test_signature_parameter_equality(self):
3249 P = inspect.Parameter
3250 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3251
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003252 self.assertTrue(p == p)
3253 self.assertFalse(p != p)
3254 self.assertFalse(p == 42)
3255 self.assertTrue(p != 42)
3256 self.assertTrue(p == EqualsToAll())
3257 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003258
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003259 self.assertTrue(p == P('foo', default=42,
3260 kind=inspect.Parameter.KEYWORD_ONLY))
3261 self.assertFalse(p != P('foo', default=42,
3262 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003263
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003264 def test_signature_parameter_replace(self):
3265 p = inspect.Parameter('foo', default=42,
3266 kind=inspect.Parameter.KEYWORD_ONLY)
3267
3268 self.assertIsNot(p, p.replace())
3269 self.assertEqual(p, p.replace())
3270
3271 p2 = p.replace(annotation=1)
3272 self.assertEqual(p2.annotation, 1)
3273 p2 = p2.replace(annotation=p2.empty)
3274 self.assertEqual(p, p2)
3275
3276 p2 = p2.replace(name='bar')
3277 self.assertEqual(p2.name, 'bar')
3278 self.assertNotEqual(p2, p)
3279
Yury Selivanov2393dca2014-01-27 15:07:58 -05003280 with self.assertRaisesRegex(ValueError,
3281 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003282 p2 = p2.replace(name=p2.empty)
3283
3284 p2 = p2.replace(name='foo', default=None)
3285 self.assertIs(p2.default, None)
3286 self.assertNotEqual(p2, p)
3287
3288 p2 = p2.replace(name='foo', default=p2.empty)
3289 self.assertIs(p2.default, p2.empty)
3290
3291
3292 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3293 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3294 self.assertNotEqual(p2, p)
3295
Dong-hee Naa9cab432018-05-30 00:04:08 +09003296 with self.assertRaisesRegex(ValueError,
3297 "value <class 'inspect._empty'> "
3298 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003299 p2 = p2.replace(kind=p2.empty)
3300
3301 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3302 self.assertEqual(p2, p)
3303
3304 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003305 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3306 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003307
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003308 @cpython_only
3309 def test_signature_parameter_implicit(self):
3310 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003311 'implicit arguments must be passed as '
3312 'positional or keyword arguments, '
3313 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003314 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3315
3316 param = inspect.Parameter(
3317 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3318 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3319 self.assertEqual(param.name, 'implicit0')
3320
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003321 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003322 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003323
3324 with self.assertRaises(AttributeError):
3325 p.foo = 'bar'
3326
3327 with self.assertRaises(AttributeError):
3328 p.kind = 123
3329
3330
3331class TestSignatureBind(unittest.TestCase):
3332 @staticmethod
3333 def call(func, *args, **kwargs):
3334 sig = inspect.signature(func)
3335 ba = sig.bind(*args, **kwargs)
3336 return func(*ba.args, **ba.kwargs)
3337
3338 def test_signature_bind_empty(self):
3339 def test():
3340 return 42
3341
3342 self.assertEqual(self.call(test), 42)
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)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003345 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003346 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003347 with self.assertRaisesRegex(
3348 TypeError, "got an unexpected keyword argument 'spam'"):
3349
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003350 self.call(test, spam=1)
3351
3352 def test_signature_bind_var(self):
3353 def test(*args, **kwargs):
3354 return args, kwargs
3355
3356 self.assertEqual(self.call(test), ((), {}))
3357 self.assertEqual(self.call(test, 1), ((1,), {}))
3358 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3359 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3360 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3361 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3362 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3363 ((1, 2), {'foo': 'bar'}))
3364
3365 def test_signature_bind_just_args(self):
3366 def test(a, b, c):
3367 return a, b, c
3368
3369 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3370
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003371 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003372 self.call(test, 1, 2, 3, 4)
3373
Yury Selivanov86872752015-05-19 00:27:49 -04003374 with self.assertRaisesRegex(TypeError,
3375 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003376 self.call(test, 1)
3377
Yury Selivanov86872752015-05-19 00:27:49 -04003378 with self.assertRaisesRegex(TypeError,
3379 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003380 self.call(test)
3381
3382 def test(a, b, c=10):
3383 return a, b, c
3384 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3385 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3386
3387 def test(a=1, b=2, c=3):
3388 return a, b, c
3389 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3390 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3391 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3392
3393 def test_signature_bind_varargs_order(self):
3394 def test(*args):
3395 return args
3396
3397 self.assertEqual(self.call(test), ())
3398 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3399
3400 def test_signature_bind_args_and_varargs(self):
3401 def test(a, b, c=3, *args):
3402 return a, b, c, args
3403
3404 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3405 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3406 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3407 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3408
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003409 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003410 "multiple values for argument 'c'"):
3411 self.call(test, 1, 2, 3, c=4)
3412
3413 def test_signature_bind_just_kwargs(self):
3414 def test(**kwargs):
3415 return kwargs
3416
3417 self.assertEqual(self.call(test), {})
3418 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3419 {'foo': 'bar', 'spam': 'ham'})
3420
3421 def test_signature_bind_args_and_kwargs(self):
3422 def test(a, b, c=3, **kwargs):
3423 return a, b, c, kwargs
3424
3425 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3426 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3427 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3428 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3429 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3430 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3431 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3432 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3433 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3434 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3435 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3436 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3437 (1, 2, 4, {'foo': 'bar'}))
3438 self.assertEqual(self.call(test, c=5, a=4, b=3),
3439 (4, 3, 5, {}))
3440
3441 def test_signature_bind_kwonly(self):
3442 def test(*, foo):
3443 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003444 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003445 'too many positional arguments'):
3446 self.call(test, 1)
3447 self.assertEqual(self.call(test, foo=1), 1)
3448
3449 def test(a, *, foo=1, bar):
3450 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003451 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003452 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003453 self.call(test, 1)
3454
3455 def test(foo, *, bar):
3456 return foo, bar
3457 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3458 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3459
Yury Selivanov86872752015-05-19 00:27:49 -04003460 with self.assertRaisesRegex(
3461 TypeError, "got an unexpected keyword argument 'spam'"):
3462
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003463 self.call(test, bar=2, foo=1, spam=10)
3464
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003465 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003466 'too many positional arguments'):
3467 self.call(test, 1, 2)
3468
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003469 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003470 'too many positional arguments'):
3471 self.call(test, 1, 2, bar=2)
3472
Yury Selivanov86872752015-05-19 00:27:49 -04003473 with self.assertRaisesRegex(
3474 TypeError, "got an unexpected keyword argument 'spam'"):
3475
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003476 self.call(test, 1, bar=2, spam='ham')
3477
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003478 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003479 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003480 self.call(test, 1)
3481
3482 def test(foo, *, bar, **bin):
3483 return foo, bar, bin
3484 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3485 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3486 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3487 (1, 2, {'spam': 'ham'}))
3488 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3489 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003490 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003491 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003492 self.call(test, spam='ham', bar=2)
3493 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3494 (1, 2, {'bin': 1, 'spam': 10}))
3495
3496 def test_signature_bind_arguments(self):
3497 def test(a, *args, b, z=100, **kwargs):
3498 pass
3499 sig = inspect.signature(test)
3500 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3501 # we won't have 'z' argument in the bound arguments object, as we didn't
3502 # pass it to the 'bind'
3503 self.assertEqual(tuple(ba.arguments.items()),
3504 (('a', 10), ('args', (20,)), ('b', 30),
3505 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3506 self.assertEqual(ba.kwargs,
3507 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3508 self.assertEqual(ba.args, (10, 20))
3509
3510 def test_signature_bind_positional_only(self):
3511 P = inspect.Parameter
3512
3513 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3514 return a_po, b_po, c_po, foo, bar, kwargs
3515
3516 sig = inspect.signature(test)
3517 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3518 for name in ('a_po', 'b_po', 'c_po'):
3519 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3520 new_sig = sig.replace(parameters=new_params.values())
3521 test.__signature__ = new_sig
3522
3523 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3524 (1, 2, 4, 5, 6, {}))
3525
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003526 self.assertEqual(self.call(test, 1, 2),
3527 (1, 2, 3, 42, 50, {}))
3528
3529 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3530 (1, 2, 3, 4, 5, {}))
3531
3532 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3533 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3534
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003535 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003536 self.call(test, 1, 2, c_po=4)
3537
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003538 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003539 self.call(test, a_po=1, b_po=2)
3540
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003541 def test_signature_bind_with_self_arg(self):
3542 # Issue #17071: one of the parameters is named "self
3543 def test(a, self, b):
3544 pass
3545 sig = inspect.signature(test)
3546 ba = sig.bind(1, 2, 3)
3547 self.assertEqual(ba.args, (1, 2, 3))
3548 ba = sig.bind(1, self=2, b=3)
3549 self.assertEqual(ba.args, (1, 2, 3))
3550
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003551 def test_signature_bind_vararg_name(self):
3552 def test(a, *args):
3553 return a, args
3554 sig = inspect.signature(test)
3555
Yury Selivanov86872752015-05-19 00:27:49 -04003556 with self.assertRaisesRegex(
3557 TypeError, "got an unexpected keyword argument 'args'"):
3558
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003559 sig.bind(a=0, args=1)
3560
3561 def test(*args, **kwargs):
3562 return args, kwargs
3563 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3564
3565 sig = inspect.signature(test)
3566 ba = sig.bind(args=1)
3567 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3568
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003569 @cpython_only
3570 def test_signature_bind_implicit_arg(self):
3571 # Issue #19611: getcallargs should work with set comprehensions
3572 def make_set():
3573 return {z * z for z in range(5)}
3574 setcomp_code = make_set.__code__.co_consts[1]
3575 setcomp_func = types.FunctionType(setcomp_code, {})
3576
3577 iterator = iter(range(5))
3578 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3579
Miss Islington (bot)f705f8e2019-10-15 05:02:34 -07003580 def test_signature_bind_posonly_kwargs(self):
3581 def foo(bar, /, **kwargs):
3582 return bar, kwargs.get(bar)
3583
3584 sig = inspect.signature(foo)
3585 result = sig.bind("pos-only", bar="keyword")
3586
3587 self.assertEqual(result.kwargs, {"bar": "keyword"})
3588 self.assertIn(("bar", "pos-only"), result.arguments.items())
3589
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003590
3591class TestBoundArguments(unittest.TestCase):
3592 def test_signature_bound_arguments_unhashable(self):
3593 def foo(a): pass
3594 ba = inspect.signature(foo).bind(1)
3595
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003596 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003597 hash(ba)
3598
3599 def test_signature_bound_arguments_equality(self):
3600 def foo(a): pass
3601 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003602 self.assertTrue(ba == ba)
3603 self.assertFalse(ba != ba)
3604 self.assertTrue(ba == EqualsToAll())
3605 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003606
3607 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003608 self.assertTrue(ba == ba2)
3609 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003610
3611 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003612 self.assertFalse(ba == ba3)
3613 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003614 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003615 self.assertTrue(ba == ba3)
3616 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003617
3618 def bar(b): pass
3619 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003620 self.assertFalse(ba == ba4)
3621 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003622
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003623 def foo(*, a, b): pass
3624 sig = inspect.signature(foo)
3625 ba1 = sig.bind(a=1, b=2)
3626 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003627 self.assertTrue(ba1 == ba2)
3628 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003629
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003630 def test_signature_bound_arguments_pickle(self):
3631 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3632 sig = inspect.signature(foo)
3633 ba = sig.bind(20, 30, z={})
3634
3635 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3636 with self.subTest(pickle_ver=ver):
3637 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3638 self.assertEqual(ba, ba_pickled)
3639
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003640 def test_signature_bound_arguments_repr(self):
3641 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3642 sig = inspect.signature(foo)
3643 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003644 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003645
Yury Selivanovb907a512015-05-16 13:45:09 -04003646 def test_signature_bound_arguments_apply_defaults(self):
3647 def foo(a, b=1, *args, c:1={}, **kw): pass
3648 sig = inspect.signature(foo)
3649
3650 ba = sig.bind(20)
3651 ba.apply_defaults()
3652 self.assertEqual(
3653 list(ba.arguments.items()),
3654 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3655
3656 # Make sure that we preserve the order:
3657 # i.e. 'c' should be *before* 'kw'.
3658 ba = sig.bind(10, 20, 30, d=1)
3659 ba.apply_defaults()
3660 self.assertEqual(
3661 list(ba.arguments.items()),
3662 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3663
3664 # Make sure that BoundArguments produced by bind_partial()
3665 # are supported.
3666 def foo(a, b): pass
3667 sig = inspect.signature(foo)
3668 ba = sig.bind_partial(20)
3669 ba.apply_defaults()
3670 self.assertEqual(
3671 list(ba.arguments.items()),
3672 [('a', 20)])
3673
3674 # Test no args
3675 def foo(): pass
3676 sig = inspect.signature(foo)
3677 ba = sig.bind()
3678 ba.apply_defaults()
3679 self.assertEqual(list(ba.arguments.items()), [])
3680
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003681 # Make sure a no-args binding still acquires proper defaults.
3682 def foo(a='spam'): pass
3683 sig = inspect.signature(foo)
3684 ba = sig.bind()
3685 ba.apply_defaults()
3686 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3687
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003688
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003689class TestSignaturePrivateHelpers(unittest.TestCase):
3690 def test_signature_get_bound_param(self):
3691 getter = inspect._signature_get_bound_param
3692
3693 self.assertEqual(getter('($self)'), 'self')
3694 self.assertEqual(getter('($self, obj)'), 'self')
3695 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3696
Larry Hastings2623c8c2014-02-08 22:15:29 -08003697 def _strip_non_python_syntax(self, input,
3698 clean_signature, self_parameter, last_positional_only):
3699 computed_clean_signature, \
3700 computed_self_parameter, \
3701 computed_last_positional_only = \
3702 inspect._signature_strip_non_python_syntax(input)
3703 self.assertEqual(computed_clean_signature, clean_signature)
3704 self.assertEqual(computed_self_parameter, self_parameter)
3705 self.assertEqual(computed_last_positional_only, last_positional_only)
3706
3707 def test_signature_strip_non_python_syntax(self):
3708 self._strip_non_python_syntax(
3709 "($module, /, path, mode, *, dir_fd=None, " +
3710 "effective_ids=False,\n follow_symlinks=True)",
3711 "(module, path, mode, *, dir_fd=None, " +
3712 "effective_ids=False, follow_symlinks=True)",
3713 0,
3714 0)
3715
3716 self._strip_non_python_syntax(
3717 "($module, word, salt, /)",
3718 "(module, word, salt)",
3719 0,
3720 2)
3721
3722 self._strip_non_python_syntax(
3723 "(x, y=None, z=None, /)",
3724 "(x, y=None, z=None)",
3725 None,
3726 2)
3727
3728 self._strip_non_python_syntax(
3729 "(x, y=None, z=None)",
3730 "(x, y=None, z=None)",
3731 None,
3732 None)
3733
3734 self._strip_non_python_syntax(
3735 "(x,\n y=None,\n z = None )",
3736 "(x, y=None, z=None)",
3737 None,
3738 None)
3739
3740 self._strip_non_python_syntax(
3741 "",
3742 "",
3743 None,
3744 None)
3745
3746 self._strip_non_python_syntax(
3747 None,
3748 None,
3749 None,
3750 None)
3751
Nick Coghlan9c680b02015-04-13 12:54:54 -04003752class TestSignatureDefinitions(unittest.TestCase):
3753 # This test case provides a home for checking that particular APIs
3754 # have signatures available for introspection
3755
3756 @cpython_only
3757 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3758 "Signature information for builtins requires docstrings")
3759 def test_builtins_have_signatures(self):
3760 # This checks all builtin callables in CPython have signatures
3761 # A few have signatures Signature can't yet handle, so we skip those
3762 # since they will have to wait until PEP 457 adds the required
3763 # introspection support to the inspect module
3764 # Some others also haven't been converted yet for various other
3765 # reasons, so we also skip those for the time being, but design
3766 # the test to fail in order to indicate when it needs to be
3767 # updated.
3768 no_signature = set()
3769 # These need PEP 457 groups
3770 needs_groups = {"range", "slice", "dir", "getattr",
3771 "next", "iter", "vars"}
3772 no_signature |= needs_groups
3773 # These need PEP 457 groups or a signature change to accept None
3774 needs_semantic_update = {"round"}
3775 no_signature |= needs_semantic_update
3776 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003777 needs_varargs = {"breakpoint", "min", "max", "print",
3778 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003779 no_signature |= needs_varargs
3780 # These simply weren't covered in the initial AC conversion
3781 # for builtin callables
3782 not_converted_yet = {"open", "__import__"}
3783 no_signature |= not_converted_yet
3784 # These builtin types are expected to provide introspection info
3785 types_with_signatures = set()
3786 # Check the signatures we expect to be there
3787 ns = vars(builtins)
3788 for name, obj in sorted(ns.items()):
3789 if not callable(obj):
3790 continue
3791 # The builtin types haven't been converted to AC yet
3792 if isinstance(obj, type) and (name not in types_with_signatures):
3793 # Note that this also skips all the exception types
3794 no_signature.add(name)
3795 if (name in no_signature):
3796 # Not yet converted
3797 continue
3798 with self.subTest(builtin=name):
3799 self.assertIsNotNone(inspect.signature(obj))
3800 # Check callables that haven't been converted don't claim a signature
3801 # This ensures this test will start failing as more signatures are
3802 # added, so the affected items can be moved into the scope of the
3803 # regression test above
3804 for name in no_signature:
3805 with self.subTest(builtin=name):
3806 self.assertIsNone(obj.__text_signature__)
3807
Serhiy Storchakad53cf992019-05-06 22:40:27 +03003808 def test_python_function_override_signature(self):
3809 def func(*args, **kwargs):
3810 pass
3811 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
3812 sig = inspect.signature(func)
3813 self.assertIsNotNone(sig)
3814 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
3815 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
3816 sig = inspect.signature(func)
3817 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
3818
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003819
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003820class NTimesUnwrappable:
3821 def __init__(self, n):
3822 self.n = n
3823 self._next = None
3824
3825 @property
3826 def __wrapped__(self):
3827 if self.n <= 0:
3828 raise Exception("Unwrapped too many times")
3829 if self._next is None:
3830 self._next = NTimesUnwrappable(self.n - 1)
3831 return self._next
3832
Nick Coghlane8c45d62013-07-28 20:00:01 +10003833class TestUnwrap(unittest.TestCase):
3834
3835 def test_unwrap_one(self):
3836 def func(a, b):
3837 return a + b
3838 wrapper = functools.lru_cache(maxsize=20)(func)
3839 self.assertIs(inspect.unwrap(wrapper), func)
3840
3841 def test_unwrap_several(self):
3842 def func(a, b):
3843 return a + b
3844 wrapper = func
3845 for __ in range(10):
3846 @functools.wraps(wrapper)
3847 def wrapper():
3848 pass
3849 self.assertIsNot(wrapper.__wrapped__, func)
3850 self.assertIs(inspect.unwrap(wrapper), func)
3851
3852 def test_stop(self):
3853 def func1(a, b):
3854 return a + b
3855 @functools.wraps(func1)
3856 def func2():
3857 pass
3858 @functools.wraps(func2)
3859 def wrapper():
3860 pass
3861 func2.stop_here = 1
3862 unwrapped = inspect.unwrap(wrapper,
3863 stop=(lambda f: hasattr(f, "stop_here")))
3864 self.assertIs(unwrapped, func2)
3865
3866 def test_cycle(self):
3867 def func1(): pass
3868 func1.__wrapped__ = func1
3869 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3870 inspect.unwrap(func1)
3871
3872 def func2(): pass
3873 func2.__wrapped__ = func1
3874 func1.__wrapped__ = func2
3875 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3876 inspect.unwrap(func1)
3877 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3878 inspect.unwrap(func2)
3879
3880 def test_unhashable(self):
3881 def func(): pass
3882 func.__wrapped__ = None
3883 class C:
3884 __hash__ = None
3885 __wrapped__ = func
3886 self.assertIsNone(inspect.unwrap(C()))
3887
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003888 def test_recursion_limit(self):
3889 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3890 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3891 inspect.unwrap(obj)
3892
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003893class TestMain(unittest.TestCase):
3894 def test_only_source(self):
3895 module = importlib.import_module('unittest')
3896 rc, out, err = assert_python_ok('-m', 'inspect',
3897 'unittest')
3898 lines = out.decode().splitlines()
3899 # ignore the final newline
3900 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3901 self.assertEqual(err, b'')
3902
Yury Selivanov42407ab2014-06-23 10:23:50 -07003903 def test_custom_getattr(self):
3904 def foo():
3905 pass
3906 foo.__signature__ = 42
3907 with self.assertRaises(TypeError):
3908 inspect.signature(foo)
3909
Brett Cannon634a8fc2013-10-02 10:25:42 -04003910 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003911 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003912 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003913 rc, out, err = assert_python_ok('-m', 'inspect',
3914 'concurrent.futures:ThreadPoolExecutor')
3915 lines = out.decode().splitlines()
3916 # ignore the final newline
3917 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003918 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003919 self.assertEqual(err, b'')
3920
3921 def test_builtins(self):
3922 module = importlib.import_module('unittest')
3923 _, out, err = assert_python_failure('-m', 'inspect',
3924 'sys')
3925 lines = err.decode().splitlines()
3926 self.assertEqual(lines, ["Can't get info for builtin modules."])
3927
3928 def test_details(self):
3929 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003930 args = support.optim_args_from_interpreter_flags()
3931 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003932 'unittest', '--details')
3933 output = out.decode()
3934 # Just a quick sanity check on the output
3935 self.assertIn(module.__name__, output)
3936 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003937 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003938 self.assertEqual(err, b'')
3939
3940
Yury Selivanovef1e7502014-12-08 16:05:34 -05003941class TestReload(unittest.TestCase):
3942
3943 src_before = textwrap.dedent("""\
3944def foo():
3945 print("Bla")
3946 """)
3947
3948 src_after = textwrap.dedent("""\
3949def foo():
3950 print("Oh no!")
3951 """)
3952
3953 def assertInspectEqual(self, path, source):
3954 inspected_src = inspect.getsource(source)
3955 with open(path) as src:
3956 self.assertEqual(
3957 src.read().splitlines(True),
3958 inspected_src.splitlines(True)
3959 )
3960
3961 def test_getsource_reload(self):
3962 # see issue 1218234
3963 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3964 module = importlib.import_module(name)
3965 self.assertInspectEqual(path, module)
3966 with open(path, 'w') as src:
3967 src.write(self.src_after)
3968 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003969
Nick Coghlane8c45d62013-07-28 20:00:01 +10003970
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003971def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003972 run_unittest(
3973 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3974 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3975 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003976 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003977 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003978 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04003979 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003980 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07003981 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00003982 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003983
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003984if __name__ == "__main__":
3985 test_main()