blob: be52b389e62dc1b85ae0a61d87d2fba86b801b05 [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
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500516 def test_getfile_class_without_module(self):
517 class CM(type):
518 @property
519 def __module__(cls):
520 raise AttributeError
521 class C(metaclass=CM):
522 pass
523 with self.assertRaises(TypeError):
524 inspect.getfile(C)
525
Thomas Kluyvere968bc732017-10-24 13:42:36 +0100526 def test_getfile_broken_repr(self):
527 class ErrorRepr:
528 def __repr__(self):
529 raise Exception('xyz')
530 er = ErrorRepr()
531 with self.assertRaises(TypeError):
532 inspect.getfile(er)
533
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000534 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000535 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000536 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000537 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000538 m.__file__ = "<string>" # hopefully not a real filename...
539 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000540 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000541 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000542 del sys.modules[name]
543 inspect.getmodule(compile('a=10','','single'))
544
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500545 def test_proceed_with_fake_filename(self):
546 '''doctest monkeypatches linecache to enable inspection'''
547 fn, source = '<test>', 'def x(): pass\n'
548 getlines = linecache.getlines
549 def monkey(filename, module_globals=None):
550 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300551 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500552 else:
553 return getlines(filename, module_globals)
554 linecache.getlines = monkey
555 try:
556 ns = {}
557 exec(compile(source, fn, 'single'), ns)
558 inspect.getsource(ns["x"])
559 finally:
560 linecache.getlines = getlines
561
Antoine Pitroua8723a02015-04-15 00:41:29 +0200562 def test_getsource_on_code_object(self):
563 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
564
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700565class TestGettingSourceOfToplevelFrames(GetSourceBase):
566 fodderModule = mod
567
568 def test_range_toplevel_frame(self):
569 self.maxDiff = None
570 self.assertSourceEqual(mod.currentframe, 1, None)
571
572 def test_range_traceback_toplevel_frame(self):
573 self.assertSourceEqual(mod.tb, 1, None)
574
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000575class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000576 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000577
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000578 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000579 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000580
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000581 def test_replacing_decorator(self):
582 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000583
Yury Selivanov081bbf62014-09-26 17:34:54 -0400584 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200585 self.assertSourceEqual(mod2.real, 130, 132)
586
587 def test_decorator_with_lambda(self):
588 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400589
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000590class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000591 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000592 def test_oneline_lambda(self):
593 # Test inspect.getsource with a one-line lambda function.
594 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000595
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000596 def test_threeline_lambda(self):
597 # Test inspect.getsource with a three-line lambda function,
598 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000599 self.assertSourceEqual(mod2.tll, 28, 30)
600
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000601 def test_twoline_indented_lambda(self):
602 # Test inspect.getsource with a two-line lambda function,
603 # where the second line _is_ indented.
604 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000605
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000606 def test_onelinefunc(self):
607 # Test inspect.getsource with a regular one-line function.
608 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000609
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000610 def test_manyargs(self):
611 # Test inspect.getsource with a regular function where
612 # the arguments are on two lines and _not_ indented and
613 # the body on the second line with the last arguments.
614 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000615
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000616 def test_twolinefunc(self):
617 # Test inspect.getsource with a regular function where
618 # the body is on two lines, following the argument list and
619 # continued on the next line by a \\.
620 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000621
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000622 def test_lambda_in_list(self):
623 # Test inspect.getsource with a one-line lambda function
624 # defined in a list, indented.
625 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000626
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000627 def test_anonymous(self):
628 # Test inspect.getsource with a lambda function defined
629 # as argument to another function.
630 self.assertSourceEqual(mod2.anonymous, 55, 55)
631
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000632class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000633 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000634
635 def test_with_comment(self):
636 self.assertSourceEqual(mod2.with_comment, 58, 59)
637
638 def test_multiline_sig(self):
639 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
640
Armin Rigodd5c0232005-09-25 11:45:45 +0000641 def test_nested_class(self):
642 self.assertSourceEqual(mod2.func69().func71, 71, 72)
643
644 def test_one_liner_followed_by_non_name(self):
645 self.assertSourceEqual(mod2.func77, 77, 77)
646
647 def test_one_liner_dedent_non_name(self):
648 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
649
650 def test_with_comment_instead_of_docstring(self):
651 self.assertSourceEqual(mod2.func88, 88, 90)
652
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000653 def test_method_in_dynamic_class(self):
654 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
655
R David Murray32562d72014-10-03 11:15:38 -0400656 # This should not skip for CPython, but might on a repackaged python where
657 # unicodedata is not an external module, or on pypy.
658 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
659 unicodedata.__file__.endswith('.py'),
660 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000661 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200662 self.assertRaises(OSError, inspect.getsource, unicodedata)
663 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000664
R. David Murraya1b37402010-06-17 02:04:29 +0000665 def test_findsource_code_in_linecache(self):
666 lines = ["x=1"]
667 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200668 self.assertRaises(OSError, inspect.findsource, co)
669 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000670 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200671 try:
672 self.assertEqual(inspect.findsource(co), (lines,0))
673 self.assertEqual(inspect.getsource(co), lines[0])
674 finally:
675 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000676
Ezio Melotti1b145922013-03-30 05:17:24 +0200677 def test_findsource_without_filename(self):
678 for fname in ['', '<string>']:
679 co = compile('x=1', fname, "exec")
680 self.assertRaises(IOError, inspect.findsource, co)
681 self.assertRaises(IOError, inspect.getsource, co)
682
Antoine Pitroua8723a02015-04-15 00:41:29 +0200683 def test_getsource_on_method(self):
684 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
685
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300686 def test_nested_func(self):
687 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
688
689
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000690class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400691 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000692 self.tempdir = TESTFN + '_dir'
693 os.mkdir(self.tempdir)
694 with open(os.path.join(self.tempdir,
695 'inspect_fodder3%spy' % os.extsep), 'w') as f:
696 f.write("class X:\n pass # No EOL")
697 with DirsOnSysPath(self.tempdir):
698 import inspect_fodder3 as mod3
699 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400700 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000701
702 def tearDown(self):
703 shutil.rmtree(self.tempdir)
704
705 def test_class(self):
706 self.assertSourceEqual(self.fodderModule.X, 1, 2)
707
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100708
709class _BrokenDataDescriptor(object):
710 """
711 A broken data descriptor. See bug #1785.
712 """
713 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700714 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100715
716 def __set__(*args):
717 raise RuntimeError
718
719 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700720 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100721
722
723class _BrokenMethodDescriptor(object):
724 """
725 A broken method descriptor. See bug #1785.
726 """
727 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700728 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100729
730 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700731 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100732
733
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000734# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000735def attrs_wo_objs(cls):
736 return [t[:3] for t in inspect.classify_class_attrs(cls)]
737
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100738
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000739class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000740 def test_newstyle_mro(self):
741 # The same w/ new-class MRO.
742 class A(object): pass
743 class B(A): pass
744 class C(A): pass
745 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000746
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000747 expected = (D, B, C, A, object)
748 got = inspect.getmro(D)
749 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000750
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500751 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
752 varkw_e=None, defaults_e=None, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100753 args, varargs, varkw, defaults = inspect.getargspec(routine)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500754 self.assertEqual(args, args_e)
755 self.assertEqual(varargs, varargs_e)
756 self.assertEqual(varkw, varkw_e)
757 self.assertEqual(defaults, defaults_e)
758 if formatted is not None:
Pablo Galindoaee19f52019-05-16 21:08:15 +0100759 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
760 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500761
Christian Heimes3795b532007-11-08 13:48:53 +0000762 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
763 varkw_e=None, defaults_e=None,
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100764 posonlyargs_e=[], kwonlyargs_e=[],
765 kwonlydefaults_e=None,
Christian Heimes3795b532007-11-08 13:48:53 +0000766 ann_e={}, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100767 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
768 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000769 self.assertEqual(args, args_e)
770 self.assertEqual(varargs, varargs_e)
771 self.assertEqual(varkw, varkw_e)
772 self.assertEqual(defaults, defaults_e)
773 self.assertEqual(kwonlyargs, kwonlyargs_e)
774 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
775 self.assertEqual(ann, ann_e)
776 if formatted is not None:
Pablo Galindoaee19f52019-05-16 21:08:15 +0100777 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
778 kwonlyargs, kwonlydefaults, ann),
Christian Heimes3795b532007-11-08 13:48:53 +0000779 formatted)
780
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500781 def test_getargspec(self):
782 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
783
Pablo Galindod5d2b452019-04-30 02:01:14 +0100784 self.assertArgSpecEquals(mod.spam,
785 ['a', 'b', 'c', 'd', 'e', 'f'],
786 'g', 'h', (3, 4, 5),
787 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500788
789 self.assertRaises(ValueError, self.assertArgSpecEquals,
790 mod2.keyworded, [])
791
792 self.assertRaises(ValueError, self.assertArgSpecEquals,
793 mod2.annotated, [])
794 self.assertRaises(ValueError, self.assertArgSpecEquals,
795 mod2.keyword_only_arg, [])
796
797
Christian Heimes3795b532007-11-08 13:48:53 +0000798 def test_getfullargspec(self):
799 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
800 kwonlyargs_e=['arg2'],
801 kwonlydefaults_e={'arg2':1},
802 formatted='(*arg1, arg2=1)')
803
804 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000805 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000806 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000807 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
808 kwonlyargs_e=['arg'],
809 formatted='(*, arg)')
810
Pablo Galindod5d2b452019-04-30 02:01:14 +0100811 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100812 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100813 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100814
815 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100816 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100817 varargs_e='args',
818 varkw_e='kwargs',
819 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100820 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100821
Pablo Galindod5d2b452019-04-30 02:01:14 +0100822 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100823 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100824 kwonlyargs_e=['e', 'f'],
825 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100826 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100827
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500828 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500829 # Issue 20684: low level introspection API must ignore __wrapped__
830 @functools.wraps(mod.spam)
831 def ham(x, y):
832 pass
833 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500834 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500835 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
836 self.assertFullArgSpecEquals(functools.partial(ham),
837 ['x', 'y'], formatted='(x, y)')
838 # Other variants
839 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500840 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
841 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500842 class C:
843 @functools.wraps(mod.spam)
844 def ham(self, x, y):
845 pass
846 pham = functools.partialmethod(ham)
847 @functools.wraps(mod.spam)
848 def __call__(self, x, y):
849 pass
850 check_method(C())
851 check_method(C.ham)
852 check_method(C().ham)
853 check_method(C.pham)
854 check_method(C().pham)
855
856 class C_new:
857 @functools.wraps(mod.spam)
858 def __new__(self, x, y):
859 pass
860 check_method(C_new)
861
862 class C_init:
863 @functools.wraps(mod.spam)
864 def __init__(self, x, y):
865 pass
866 check_method(C_init)
867
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500868 def test_getfullargspec_signature_attr(self):
869 def test():
870 pass
871 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
872 test.__signature__ = inspect.Signature(parameters=(spam_param,))
873
Pablo Galindod5d2b452019-04-30 02:01:14 +0100874 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500875
Yury Selivanov4cb93912014-01-29 11:54:12 -0500876 def test_getfullargspec_signature_annos(self):
877 def test(a:'spam') -> 'ham': pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100878 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500879 self.assertEqual(test.__annotations__, spec.annotations)
880
881 def test(): pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100882 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500883 self.assertEqual(test.__annotations__, spec.annotations)
884
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500885 @unittest.skipIf(MISSING_C_DOCSTRINGS,
886 "Signature information for builtins requires docstrings")
887 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100888 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
889 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500890
Pablo Galindod5d2b452019-04-30 02:01:14 +0100891 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
892 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500893
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500894 self.assertFullArgSpecEquals(
895 os.stat,
896 args_e=['path'],
897 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
898 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
899 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
900
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200901 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500902 @unittest.skipIf(MISSING_C_DOCSTRINGS,
903 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800904 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200905 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500906 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindoaee19f52019-05-16 21:08:15 +0100907 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500908 self.assertEqual(spec.defaults[0], 'avocado')
909
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200910 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500911 @unittest.skipIf(MISSING_C_DOCSTRINGS,
912 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800913 def test_getfullargspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200914 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500915 builtin = _testcapi.docstring_no_signature
Pablo Galindoaee19f52019-05-16 21:08:15 +0100916 with self.assertRaises(TypeError):
917 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000918
larryhastingsf36ba122018-01-28 11:13:09 -0800919 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
920 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindoaee19f52019-05-16 21:08:15 +0100921 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800922 l = list(signature.kwonlyargs)
923 sorted_l = sorted(l)
924 self.assertTrue(l)
925 self.assertEqual(l, sorted_l)
Pablo Galindoaee19f52019-05-16 21:08:15 +0100926 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800927 l = list(signature.kwonlyargs)
928 self.assertEqual(l, unsorted_keyword_only_parameters)
929
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500930 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000931 class A(object):
932 def m(self):
933 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500934 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000935
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000936 def test_classify_newstyle(self):
937 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000938
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000939 def s(): pass
940 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000941
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000942 def c(cls): pass
943 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000944
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000945 def getp(self): pass
946 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000947
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000948 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000949
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000950 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000951
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000952 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000953
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100954 dd = _BrokenDataDescriptor()
955 md = _BrokenMethodDescriptor()
956
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000957 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500958
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +0200959 self.assertIn(('__new__', 'static method', object), attrs,
960 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500961 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
962
Benjamin Peterson577473f2010-01-19 00:09:57 +0000963 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
964 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
965 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000966 self.assertIn(('m', 'method', A), attrs,
967 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000968 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
969 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100970 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
971 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000972
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000973 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000974
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000975 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000976
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000977 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000978 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
979 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
980 self.assertIn(('p', 'property', A), attrs, 'missing property')
981 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
982 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
983 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100984 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
985 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000986
987
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000988 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000989
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000990 def m(self): pass
991 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000992
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000993 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000994 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
995 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
996 self.assertIn(('p', 'property', A), attrs, 'missing property')
997 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
998 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
999 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001000 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1001 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001002
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001003 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001004
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001005 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001006
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001007 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001008 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1009 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1010 self.assertIn(('p', 'property', A), attrs, 'missing property')
1011 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1012 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1013 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001014 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1015 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1016
1017 def test_classify_builtin_types(self):
1018 # Simple sanity check that all built-in types can have their
1019 # attributes classified.
1020 for name in dir(__builtins__):
1021 builtin = getattr(__builtins__, name)
1022 if isinstance(builtin, type):
1023 inspect.classify_class_attrs(builtin)
1024
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001025 attrs = attrs_wo_objs(bool)
1026 self.assertIn(('__new__', 'static method', bool), attrs,
1027 'missing __new__')
1028 self.assertIn(('from_bytes', 'class method', int), attrs,
1029 'missing class method')
1030 self.assertIn(('to_bytes', 'method', int), attrs,
1031 'missing plain method')
1032 self.assertIn(('__add__', 'method', int), attrs,
1033 'missing plain method')
1034 self.assertIn(('__and__', 'method', bool), attrs,
1035 'missing plain method')
1036
Ethan Furman63c141c2013-10-18 00:27:39 -07001037 def test_classify_DynamicClassAttribute(self):
1038 class Meta(type):
1039 def __getattr__(self, name):
1040 if name == 'ham':
1041 return 'spam'
1042 return super().__getattr__(name)
1043 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001044 @types.DynamicClassAttribute
1045 def ham(self):
1046 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001047 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1048 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001049 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001050 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1051
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001052 def test_classify_overrides_bool(self):
1053 class NoBool(object):
1054 def __eq__(self, other):
1055 return NoBool()
1056
1057 def __bool__(self):
1058 raise NotImplementedError(
1059 "This object does not specify a boolean value")
1060
1061 class HasNB(object):
1062 dd = NoBool()
1063
1064 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1065 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1066
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001067 def test_classify_metaclass_class_attribute(self):
1068 class Meta(type):
1069 fish = 'slap'
1070 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001071 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001072 class Class(metaclass=Meta):
1073 pass
1074 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1075 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1076
Ethan Furman63c141c2013-10-18 00:27:39 -07001077 def test_classify_VirtualAttribute(self):
1078 class Meta(type):
1079 def __dir__(cls):
1080 return ['__class__', '__module__', '__name__', 'BOOM']
1081 def __getattr__(self, name):
1082 if name =='BOOM':
1083 return 42
1084 return super().__getattr(name)
1085 class Class(metaclass=Meta):
1086 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001087 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001088 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1089
1090 def test_classify_VirtualAttribute_multi_classes(self):
1091 class Meta1(type):
1092 def __dir__(cls):
1093 return ['__class__', '__module__', '__name__', 'one']
1094 def __getattr__(self, name):
1095 if name =='one':
1096 return 1
1097 return super().__getattr__(name)
1098 class Meta2(type):
1099 def __dir__(cls):
1100 return ['__class__', '__module__', '__name__', 'two']
1101 def __getattr__(self, name):
1102 if name =='two':
1103 return 2
1104 return super().__getattr__(name)
1105 class Meta3(Meta1, Meta2):
1106 def __dir__(cls):
1107 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1108 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1109 def __getattr__(self, name):
1110 if name =='three':
1111 return 3
1112 return super().__getattr__(name)
1113 class Class1(metaclass=Meta1):
1114 pass
1115 class Class2(Class1, metaclass=Meta3):
1116 pass
1117
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001118 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1119 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1120 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001121 cca = inspect.classify_class_attrs(Class2)
1122 for sf in (should_find1, should_find2, should_find3):
1123 self.assertIn(sf, cca)
1124
1125 def test_classify_class_attrs_with_buggy_dir(self):
1126 class M(type):
1127 def __dir__(cls):
1128 return ['__class__', '__name__', 'missing']
1129 class C(metaclass=M):
1130 pass
1131 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1132 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001133
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001134 def test_getmembers_descriptors(self):
1135 class A(object):
1136 dd = _BrokenDataDescriptor()
1137 md = _BrokenMethodDescriptor()
1138
1139 def pred_wrapper(pred):
1140 # A quick'n'dirty way to discard standard attributes of new-style
1141 # classes.
1142 class Empty(object):
1143 pass
1144 def wrapped(x):
1145 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1146 return False
1147 return pred(x)
1148 return wrapped
1149
1150 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1151 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1152
1153 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1154 [('md', A.__dict__['md'])])
1155 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1156 [('dd', A.__dict__['dd'])])
1157
1158 class B(A):
1159 pass
1160
1161 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1162 [('md', A.__dict__['md'])])
1163 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1164 [('dd', A.__dict__['dd'])])
1165
Antoine Pitrou0c603812012-01-18 17:40:18 +01001166 def test_getmembers_method(self):
1167 class B:
1168 def f(self):
1169 pass
1170
1171 self.assertIn(('f', B.f), inspect.getmembers(B))
1172 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1173 b = B()
1174 self.assertIn(('f', b.f), inspect.getmembers(b))
1175 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1176
Ethan Furmane03ea372013-09-25 07:14:41 -07001177 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001178 class M(type):
1179 def __getattr__(cls, name):
1180 if name == 'eggs':
1181 return 'scrambled'
1182 return super().__getattr__(name)
1183 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001184 @types.DynamicClassAttribute
1185 def eggs(self):
1186 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001187 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1188 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1189
1190 def test_getmembers_with_buggy_dir(self):
1191 class M(type):
1192 def __dir__(cls):
1193 return ['__class__', '__name__', 'missing']
1194 class C(metaclass=M):
1195 pass
1196 attrs = [a[0] for a in inspect.getmembers(C)]
1197 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001198
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001199class TestIsDataDescriptor(unittest.TestCase):
1200
1201 def test_custom_descriptors(self):
1202 class NonDataDescriptor:
1203 def __get__(self, value, type=None): pass
1204 class DataDescriptor0:
1205 def __set__(self, name, value): pass
1206 class DataDescriptor1:
1207 def __delete__(self, name): pass
1208 class DataDescriptor2:
1209 __set__ = None
1210 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1211 'class with only __get__ not a data descriptor')
1212 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1213 'class with __set__ is a data descriptor')
1214 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1215 'class with __delete__ is a data descriptor')
1216 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1217 'class with __set__ = None is a data descriptor')
1218
1219 def test_slot(self):
1220 class Slotted:
1221 __slots__ = 'foo',
1222 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1223 'a slot is a data descriptor')
1224
1225 def test_property(self):
1226 class Propertied:
1227 @property
1228 def a_property(self):
1229 pass
1230 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1231 'a property is a data descriptor')
1232
1233 def test_functions(self):
1234 class Test(object):
1235 def instance_method(self): pass
1236 @classmethod
1237 def class_method(cls): pass
1238 @staticmethod
1239 def static_method(): pass
1240 def function():
1241 pass
1242 a_lambda = lambda: None
1243 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1244 'a instance method is not a data descriptor')
1245 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1246 'a class method is not a data descriptor')
1247 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1248 'a static method is not a data descriptor')
1249 self.assertFalse(inspect.isdatadescriptor(function),
1250 'a function is not a data descriptor')
1251 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1252 'a lambda is not a data descriptor')
1253
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001254
Nick Coghlan2f92e542012-06-23 19:39:55 +10001255_global_ref = object()
1256class TestGetClosureVars(unittest.TestCase):
1257
1258 def test_name_resolution(self):
1259 # Basic test of the 4 different resolution mechanisms
1260 def f(nonlocal_ref):
1261 def g(local_ref):
1262 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1263 return g
1264 _arg = object()
1265 nonlocal_vars = {"nonlocal_ref": _arg}
1266 global_vars = {"_global_ref": _global_ref}
1267 builtin_vars = {"print": print}
1268 unbound_names = {"unbound_ref"}
1269 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1270 builtin_vars, unbound_names)
1271 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1272
1273 def test_generator_closure(self):
1274 def f(nonlocal_ref):
1275 def g(local_ref):
1276 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1277 yield
1278 return g
1279 _arg = object()
1280 nonlocal_vars = {"nonlocal_ref": _arg}
1281 global_vars = {"_global_ref": _global_ref}
1282 builtin_vars = {"print": print}
1283 unbound_names = {"unbound_ref"}
1284 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1285 builtin_vars, unbound_names)
1286 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1287
1288 def test_method_closure(self):
1289 class C:
1290 def f(self, nonlocal_ref):
1291 def g(local_ref):
1292 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1293 return g
1294 _arg = object()
1295 nonlocal_vars = {"nonlocal_ref": _arg}
1296 global_vars = {"_global_ref": _global_ref}
1297 builtin_vars = {"print": print}
1298 unbound_names = {"unbound_ref"}
1299 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1300 builtin_vars, unbound_names)
1301 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1302
1303 def test_nonlocal_vars(self):
1304 # More complex tests of nonlocal resolution
1305 def _nonlocal_vars(f):
1306 return inspect.getclosurevars(f).nonlocals
1307
1308 def make_adder(x):
1309 def add(y):
1310 return x + y
1311 return add
1312
1313 def curry(func, arg1):
1314 return lambda arg2: func(arg1, arg2)
1315
1316 def less_than(a, b):
1317 return a < b
1318
1319 # The infamous Y combinator.
1320 def Y(le):
1321 def g(f):
1322 return le(lambda x: f(f)(x))
1323 Y.g_ref = g
1324 return g(g)
1325
1326 def check_y_combinator(func):
1327 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1328
1329 inc = make_adder(1)
1330 add_two = make_adder(2)
1331 greater_than_five = curry(less_than, 5)
1332
1333 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1334 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1335 self.assertEqual(_nonlocal_vars(greater_than_five),
1336 {'arg1': 5, 'func': less_than})
1337 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1338 {'x': 3})
1339 Y(check_y_combinator)
1340
1341 def test_getclosurevars_empty(self):
1342 def foo(): pass
1343 _empty = inspect.ClosureVars({}, {}, {}, set())
1344 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1345 self.assertEqual(inspect.getclosurevars(foo), _empty)
1346
1347 def test_getclosurevars_error(self):
1348 class T: pass
1349 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1350 self.assertRaises(TypeError, inspect.getclosurevars, list)
1351 self.assertRaises(TypeError, inspect.getclosurevars, {})
1352
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001353 def _private_globals(self):
1354 code = """def f(): print(path)"""
1355 ns = {}
1356 exec(code, ns)
1357 return ns["f"], ns
1358
1359 def test_builtins_fallback(self):
1360 f, ns = self._private_globals()
1361 ns.pop("__builtins__", None)
1362 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1363 self.assertEqual(inspect.getclosurevars(f), expected)
1364
1365 def test_builtins_as_dict(self):
1366 f, ns = self._private_globals()
1367 ns["__builtins__"] = {"path":1}
1368 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1369 self.assertEqual(inspect.getclosurevars(f), expected)
1370
1371 def test_builtins_as_module(self):
1372 f, ns = self._private_globals()
1373 ns["__builtins__"] = os
1374 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1375 self.assertEqual(inspect.getclosurevars(f), expected)
1376
Nick Coghlan2f92e542012-06-23 19:39:55 +10001377
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001378class TestGetcallargsFunctions(unittest.TestCase):
1379
1380 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1381 locs = dict(locs or {}, func=func)
1382 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001383 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1384 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001385 self.assertEqual(r1, r2)
1386
1387 def assertEqualException(self, func, call_param_string, locs=None):
1388 locs = dict(locs or {}, func=func)
1389 try:
1390 eval('func(%s)' % call_param_string, None, locs)
1391 except Exception as e:
1392 ex1 = e
1393 else:
1394 self.fail('Exception not raised')
1395 try:
Pablo Galindoaee19f52019-05-16 21:08:15 +01001396 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1397 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001398 except Exception as e:
1399 ex2 = e
1400 else:
1401 self.fail('Exception not raised')
1402 self.assertIs(type(ex1), type(ex2))
1403 self.assertEqual(str(ex1), str(ex2))
1404 del ex1, ex2
1405
1406 def makeCallable(self, signature):
1407 """Create a function that returns its locals()"""
1408 code = "lambda %s: locals()"
1409 return eval(code % signature)
1410
1411 def test_plain(self):
1412 f = self.makeCallable('a, b=1')
1413 self.assertEqualCallArgs(f, '2')
1414 self.assertEqualCallArgs(f, '2, 3')
1415 self.assertEqualCallArgs(f, 'a=2')
1416 self.assertEqualCallArgs(f, 'b=3, a=2')
1417 self.assertEqualCallArgs(f, '2, b=3')
1418 # expand *iterable / **mapping
1419 self.assertEqualCallArgs(f, '*(2,)')
1420 self.assertEqualCallArgs(f, '*[2]')
1421 self.assertEqualCallArgs(f, '*(2, 3)')
1422 self.assertEqualCallArgs(f, '*[2, 3]')
1423 self.assertEqualCallArgs(f, '**{"a":2}')
1424 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1425 self.assertEqualCallArgs(f, '2, **{"b":3}')
1426 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1427 # expand UserList / UserDict
1428 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1429 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1430 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1431 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1432 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1433
1434 def test_varargs(self):
1435 f = self.makeCallable('a, b=1, *c')
1436 self.assertEqualCallArgs(f, '2')
1437 self.assertEqualCallArgs(f, '2, 3')
1438 self.assertEqualCallArgs(f, '2, 3, 4')
1439 self.assertEqualCallArgs(f, '*(2,3,4)')
1440 self.assertEqualCallArgs(f, '2, *[3,4]')
1441 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1442
1443 def test_varkw(self):
1444 f = self.makeCallable('a, b=1, **c')
1445 self.assertEqualCallArgs(f, 'a=2')
1446 self.assertEqualCallArgs(f, '2, b=3, c=4')
1447 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1448 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1449 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1450 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1451 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1452 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1453 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1454
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001455 def test_varkw_only(self):
1456 # issue11256:
1457 f = self.makeCallable('**c')
1458 self.assertEqualCallArgs(f, '')
1459 self.assertEqualCallArgs(f, 'a=1')
1460 self.assertEqualCallArgs(f, 'a=1, b=2')
1461 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1462 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1463 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1464
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001465 def test_keyword_only(self):
1466 f = self.makeCallable('a=3, *, c, d=2')
1467 self.assertEqualCallArgs(f, 'c=3')
1468 self.assertEqualCallArgs(f, 'c=3, a=3')
1469 self.assertEqualCallArgs(f, 'a=2, c=4')
1470 self.assertEqualCallArgs(f, '4, c=4')
1471 self.assertEqualException(f, '')
1472 self.assertEqualException(f, '3')
1473 self.assertEqualException(f, 'a=3')
1474 self.assertEqualException(f, 'd=4')
1475
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001476 f = self.makeCallable('*, c, d=2')
1477 self.assertEqualCallArgs(f, 'c=3')
1478 self.assertEqualCallArgs(f, 'c=3, d=4')
1479 self.assertEqualCallArgs(f, 'd=4, c=3')
1480
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001481 def test_multiple_features(self):
1482 f = self.makeCallable('a, b=2, *f, **g')
1483 self.assertEqualCallArgs(f, '2, 3, 7')
1484 self.assertEqualCallArgs(f, '2, 3, x=8')
1485 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1486 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1487 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1488 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1489 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1490 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1491 '(4,[5,6])]), **collections.UserDict('
1492 'y=9, z=10)')
1493
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001494 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1495 self.assertEqualCallArgs(f, '2, 3, x=8')
1496 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1497 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1498 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1499 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1500 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1501 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1502 '(4,[5,6])]), q=0, **collections.UserDict('
1503 'y=9, z=10)')
1504
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001505 def test_errors(self):
1506 f0 = self.makeCallable('')
1507 f1 = self.makeCallable('a, b')
1508 f2 = self.makeCallable('a, b=1')
1509 # f0 takes no arguments
1510 self.assertEqualException(f0, '1')
1511 self.assertEqualException(f0, 'x=1')
1512 self.assertEqualException(f0, '1,x=1')
1513 # f1 takes exactly 2 arguments
1514 self.assertEqualException(f1, '')
1515 self.assertEqualException(f1, '1')
1516 self.assertEqualException(f1, 'a=2')
1517 self.assertEqualException(f1, 'b=3')
1518 # f2 takes at least 1 argument
1519 self.assertEqualException(f2, '')
1520 self.assertEqualException(f2, 'b=3')
1521 for f in f1, f2:
1522 # f1/f2 takes exactly/at most 2 arguments
1523 self.assertEqualException(f, '2, 3, 4')
1524 self.assertEqualException(f, '1, 2, 3, a=1')
1525 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001526 # XXX: success of this one depends on dict order
1527 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001528 # f got an unexpected keyword argument
1529 self.assertEqualException(f, 'c=2')
1530 self.assertEqualException(f, '2, c=3')
1531 self.assertEqualException(f, '2, 3, c=4')
1532 self.assertEqualException(f, '2, c=4, b=3')
1533 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1534 # f got multiple values for keyword argument
1535 self.assertEqualException(f, '1, a=2')
1536 self.assertEqualException(f, '1, **{"a":2}')
1537 self.assertEqualException(f, '1, 2, b=3')
1538 # XXX: Python inconsistency
1539 # - for functions and bound methods: unexpected keyword 'c'
1540 # - for unbound methods: multiple values for keyword 'a'
1541 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001542 # issue11256:
1543 f3 = self.makeCallable('**c')
1544 self.assertEqualException(f3, '1, 2')
1545 self.assertEqualException(f3, '1, 2, a=1, b=2')
1546 f4 = self.makeCallable('*, a, b=0')
1547 self.assertEqualException(f3, '1, 2')
1548 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001549
Yury Selivanov875df202014-03-27 18:23:03 -04001550 # issue #20816: getcallargs() fails to iterate over non-existent
1551 # kwonlydefaults and raises a wrong TypeError
1552 def f5(*, a): pass
1553 with self.assertRaisesRegex(TypeError,
1554 'missing 1 required keyword-only'):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001555 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001556
1557
Yury Selivanovdccfa132014-03-27 18:42:52 -04001558 # issue20817:
1559 def f6(a, b, c):
1560 pass
1561 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001562 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001563
Dong-hee Naa9cab432018-05-30 00:04:08 +09001564 # bpo-33197
1565 with self.assertRaisesRegex(ValueError,
1566 'variadic keyword parameters cannot'
1567 ' have default values'):
1568 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1569 default=42)
1570 with self.assertRaisesRegex(ValueError,
1571 "value 5 is not a valid Parameter.kind"):
1572 inspect.Parameter("bar", kind=5, default=42)
1573
1574 with self.assertRaisesRegex(TypeError,
1575 'name must be a str, not a int'):
1576 inspect.Parameter(123, kind=4)
1577
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001578class TestGetcallargsMethods(TestGetcallargsFunctions):
1579
1580 def setUp(self):
1581 class Foo(object):
1582 pass
1583 self.cls = Foo
1584 self.inst = Foo()
1585
1586 def makeCallable(self, signature):
1587 assert 'self' not in signature
1588 mk = super(TestGetcallargsMethods, self).makeCallable
1589 self.cls.method = mk('self, ' + signature)
1590 return self.inst.method
1591
1592class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1593
1594 def makeCallable(self, signature):
1595 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1596 return self.cls.method
1597
1598 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1599 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1600 *self._getAssertEqualParams(func, call_params_string, locs))
1601
1602 def assertEqualException(self, func, call_params_string, locs=None):
1603 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1604 *self._getAssertEqualParams(func, call_params_string, locs))
1605
1606 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1607 assert 'inst' not in call_params_string
1608 locs = dict(locs or {}, inst=self.inst)
1609 return (func, 'inst,' + call_params_string, locs)
1610
Michael Foord95fc51d2010-11-20 15:07:30 +00001611
1612class TestGetattrStatic(unittest.TestCase):
1613
1614 def test_basic(self):
1615 class Thing(object):
1616 x = object()
1617
1618 thing = Thing()
1619 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1620 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1621 with self.assertRaises(AttributeError):
1622 inspect.getattr_static(thing, 'y')
1623
1624 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1625
1626 def test_inherited(self):
1627 class Thing(object):
1628 x = object()
1629 class OtherThing(Thing):
1630 pass
1631
1632 something = OtherThing()
1633 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1634
1635 def test_instance_attr(self):
1636 class Thing(object):
1637 x = 2
1638 def __init__(self, x):
1639 self.x = x
1640 thing = Thing(3)
1641 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1642 del thing.x
1643 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1644
1645 def test_property(self):
1646 class Thing(object):
1647 @property
1648 def x(self):
1649 raise AttributeError("I'm pretending not to exist")
1650 thing = Thing()
1651 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1652
Ezio Melotti75cbd732011-04-28 00:59:29 +03001653 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001654 class descriptor(object):
1655 def __get__(*_):
1656 raise AttributeError("I'm pretending not to exist")
1657 desc = descriptor()
1658 class Thing(object):
1659 x = desc
1660 thing = Thing()
1661 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1662
1663 def test_classAttribute(self):
1664 class Thing(object):
1665 x = object()
1666
1667 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1668
Ethan Furmane03ea372013-09-25 07:14:41 -07001669 def test_classVirtualAttribute(self):
1670 class Thing(object):
1671 @types.DynamicClassAttribute
1672 def x(self):
1673 return self._x
1674 _x = object()
1675
1676 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1677
Michael Foord95fc51d2010-11-20 15:07:30 +00001678 def test_inherited_classattribute(self):
1679 class Thing(object):
1680 x = object()
1681 class OtherThing(Thing):
1682 pass
1683
1684 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1685
1686 def test_slots(self):
1687 class Thing(object):
1688 y = 'bar'
1689 __slots__ = ['x']
1690 def __init__(self):
1691 self.x = 'foo'
1692 thing = Thing()
1693 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1694 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1695
1696 del thing.x
1697 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1698
1699 def test_metaclass(self):
1700 class meta(type):
1701 attr = 'foo'
1702 class Thing(object, metaclass=meta):
1703 pass
1704 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1705
1706 class sub(meta):
1707 pass
1708 class OtherThing(object, metaclass=sub):
1709 x = 3
1710 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1711
1712 class OtherOtherThing(OtherThing):
1713 pass
1714 # this test is odd, but it was added as it exposed a bug
1715 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1716
1717 def test_no_dict_no_slots(self):
1718 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1719 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1720
1721 def test_no_dict_no_slots_instance_member(self):
1722 # returns descriptor
1723 with open(__file__) as handle:
1724 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1725
1726 def test_inherited_slots(self):
1727 # returns descriptor
1728 class Thing(object):
1729 __slots__ = ['x']
1730 def __init__(self):
1731 self.x = 'foo'
1732
1733 class OtherThing(Thing):
1734 pass
1735 # it would be nice if this worked...
1736 # we get the descriptor instead of the instance attribute
1737 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1738
1739 def test_descriptor(self):
1740 class descriptor(object):
1741 def __get__(self, instance, owner):
1742 return 3
1743 class Foo(object):
1744 d = descriptor()
1745
1746 foo = Foo()
1747
1748 # for a non data descriptor we return the instance attribute
1749 foo.__dict__['d'] = 1
1750 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1751
Mike53f7a7c2017-12-14 14:04:53 +03001752 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001753 # descriptor
1754 descriptor.__set__ = lambda s, i, v: None
1755 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1756
1757
1758 def test_metaclass_with_descriptor(self):
1759 class descriptor(object):
1760 def __get__(self, instance, owner):
1761 return 3
1762 class meta(type):
1763 d = descriptor()
1764 class Thing(object, metaclass=meta):
1765 pass
1766 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1767
1768
Michael Foordcc7ebb82010-11-20 16:20:16 +00001769 def test_class_as_property(self):
1770 class Base(object):
1771 foo = 3
1772
1773 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001774 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001775 @property
1776 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001777 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001778 return object
1779
Michael Foord35184ed2010-11-20 16:58:30 +00001780 instance = Something()
1781 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1782 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001783 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1784
Michael Foorde5162652010-11-20 16:40:44 +00001785 def test_mro_as_property(self):
1786 class Meta(type):
1787 @property
1788 def __mro__(self):
1789 return (object,)
1790
1791 class Base(object):
1792 foo = 3
1793
1794 class Something(Base, metaclass=Meta):
1795 pass
1796
1797 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1798 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1799
Michael Foorddcebe0f2011-03-15 19:20:44 -04001800 def test_dict_as_property(self):
1801 test = self
1802 test.called = False
1803
1804 class Foo(dict):
1805 a = 3
1806 @property
1807 def __dict__(self):
1808 test.called = True
1809 return {}
1810
1811 foo = Foo()
1812 foo.a = 4
1813 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1814 self.assertFalse(test.called)
1815
1816 def test_custom_object_dict(self):
1817 test = self
1818 test.called = False
1819
1820 class Custom(dict):
1821 def get(self, key, default=None):
1822 test.called = True
1823 super().get(key, default)
1824
1825 class Foo(object):
1826 a = 3
1827 foo = Foo()
1828 foo.__dict__ = Custom()
1829 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1830 self.assertFalse(test.called)
1831
1832 def test_metaclass_dict_as_property(self):
1833 class Meta(type):
1834 @property
1835 def __dict__(self):
1836 self.executed = True
1837
1838 class Thing(metaclass=Meta):
1839 executed = False
1840
1841 def __init__(self):
1842 self.spam = 42
1843
1844 instance = Thing()
1845 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1846 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001847
Michael Foorda51623b2011-12-18 22:01:40 +00001848 def test_module(self):
1849 sentinel = object()
1850 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1851 sentinel)
1852
Michael Foord3ba95f82011-12-22 01:13:37 +00001853 def test_metaclass_with_metaclass_with_dict_as_property(self):
1854 class MetaMeta(type):
1855 @property
1856 def __dict__(self):
1857 self.executed = True
1858 return dict(spam=42)
1859
1860 class Meta(type, metaclass=MetaMeta):
1861 executed = False
1862
1863 class Thing(metaclass=Meta):
1864 pass
1865
1866 with self.assertRaises(AttributeError):
1867 inspect.getattr_static(Thing, "spam")
1868 self.assertFalse(Thing.executed)
1869
Nick Coghlane0f04652010-11-21 03:44:04 +00001870class TestGetGeneratorState(unittest.TestCase):
1871
1872 def setUp(self):
1873 def number_generator():
1874 for number in range(5):
1875 yield number
1876 self.generator = number_generator()
1877
1878 def _generatorstate(self):
1879 return inspect.getgeneratorstate(self.generator)
1880
1881 def test_created(self):
1882 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1883
1884 def test_suspended(self):
1885 next(self.generator)
1886 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1887
1888 def test_closed_after_exhaustion(self):
1889 for i in self.generator:
1890 pass
1891 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1892
1893 def test_closed_after_immediate_exception(self):
1894 with self.assertRaises(RuntimeError):
1895 self.generator.throw(RuntimeError)
1896 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1897
1898 def test_running(self):
1899 # As mentioned on issue #10220, checking for the RUNNING state only
1900 # makes sense inside the generator itself.
1901 # The following generator checks for this by using the closure's
1902 # reference to self and the generator state checking helper method
1903 def running_check_generator():
1904 for number in range(5):
1905 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1906 yield number
1907 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1908 self.generator = running_check_generator()
1909 # Running up to the first yield
1910 next(self.generator)
1911 # Running after the first yield
1912 next(self.generator)
1913
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001914 def test_easy_debugging(self):
1915 # repr() and str() of a generator state should contain the state name
1916 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1917 for name in names:
1918 state = getattr(inspect, name)
1919 self.assertIn(name, repr(state))
1920 self.assertIn(name, str(state))
1921
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001922 def test_getgeneratorlocals(self):
1923 def each(lst, a=None):
1924 b=(1, 2, 3)
1925 for v in lst:
1926 if v == 3:
1927 c = 12
1928 yield v
1929
1930 numbers = each([1, 2, 3])
1931 self.assertEqual(inspect.getgeneratorlocals(numbers),
1932 {'a': None, 'lst': [1, 2, 3]})
1933 next(numbers)
1934 self.assertEqual(inspect.getgeneratorlocals(numbers),
1935 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1936 'b': (1, 2, 3)})
1937 next(numbers)
1938 self.assertEqual(inspect.getgeneratorlocals(numbers),
1939 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1940 'b': (1, 2, 3)})
1941 next(numbers)
1942 self.assertEqual(inspect.getgeneratorlocals(numbers),
1943 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1944 'b': (1, 2, 3), 'c': 12})
1945 try:
1946 next(numbers)
1947 except StopIteration:
1948 pass
1949 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1950
1951 def test_getgeneratorlocals_empty(self):
1952 def yield_one():
1953 yield 1
1954 one = yield_one()
1955 self.assertEqual(inspect.getgeneratorlocals(one), {})
1956 try:
1957 next(one)
1958 except StopIteration:
1959 pass
1960 self.assertEqual(inspect.getgeneratorlocals(one), {})
1961
1962 def test_getgeneratorlocals_error(self):
1963 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1964 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1965 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1966 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1967
Nick Coghlane0f04652010-11-21 03:44:04 +00001968
Yury Selivanov5376ba92015-06-22 12:19:30 -04001969class TestGetCoroutineState(unittest.TestCase):
1970
1971 def setUp(self):
1972 @types.coroutine
1973 def number_coroutine():
1974 for number in range(5):
1975 yield number
1976 async def coroutine():
1977 await number_coroutine()
1978 self.coroutine = coroutine()
1979
1980 def tearDown(self):
1981 self.coroutine.close()
1982
1983 def _coroutinestate(self):
1984 return inspect.getcoroutinestate(self.coroutine)
1985
1986 def test_created(self):
1987 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1988
1989 def test_suspended(self):
1990 self.coroutine.send(None)
1991 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1992
1993 def test_closed_after_exhaustion(self):
1994 while True:
1995 try:
1996 self.coroutine.send(None)
1997 except StopIteration:
1998 break
1999
2000 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2001
2002 def test_closed_after_immediate_exception(self):
2003 with self.assertRaises(RuntimeError):
2004 self.coroutine.throw(RuntimeError)
2005 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2006
2007 def test_easy_debugging(self):
2008 # repr() and str() of a coroutine state should contain the state name
2009 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2010 for name in names:
2011 state = getattr(inspect, name)
2012 self.assertIn(name, repr(state))
2013 self.assertIn(name, str(state))
2014
2015 def test_getcoroutinelocals(self):
2016 @types.coroutine
2017 def gencoro():
2018 yield
2019
2020 gencoro = gencoro()
2021 async def func(a=None):
2022 b = 'spam'
2023 await gencoro
2024
2025 coro = func()
2026 self.assertEqual(inspect.getcoroutinelocals(coro),
2027 {'a': None, 'gencoro': gencoro})
2028 coro.send(None)
2029 self.assertEqual(inspect.getcoroutinelocals(coro),
2030 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2031
2032
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002033class MySignature(inspect.Signature):
2034 # Top-level to make it picklable;
2035 # used in test_signature_object_pickle
2036 pass
2037
2038class MyParameter(inspect.Parameter):
2039 # Top-level to make it picklable;
2040 # used in test_signature_object_pickle
2041 pass
2042
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002043
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002044
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002045class TestSignatureObject(unittest.TestCase):
2046 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002047 def signature(func, **kw):
2048 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002049 return (tuple((param.name,
2050 (... if param.default is param.empty else param.default),
2051 (... if param.annotation is param.empty
2052 else param.annotation),
2053 str(param.kind).lower())
2054 for param in sig.parameters.values()),
2055 (... if sig.return_annotation is sig.empty
2056 else sig.return_annotation))
2057
2058 def test_signature_object(self):
2059 S = inspect.Signature
2060 P = inspect.Parameter
2061
2062 self.assertEqual(str(S()), '()')
2063
Yury Selivanov07a9e452014-01-29 10:58:16 -05002064 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002065 pass
2066 sig = inspect.signature(test)
2067 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002068 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002069 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002070 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002071 args = sig.parameters['args']
2072 ko = sig.parameters['ko']
2073 kwargs = sig.parameters['kwargs']
2074
2075 S((po, pk, args, ko, kwargs))
2076
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002077 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002078 S((pk, po, args, ko, kwargs))
2079
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002080 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002081 S((po, args, pk, ko, kwargs))
2082
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002083 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002084 S((args, po, pk, ko, kwargs))
2085
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002086 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002087 S((po, pk, args, kwargs, ko))
2088
2089 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002090 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002091 S((po, pk, args, kwargs2, ko))
2092
Yury Selivanov07a9e452014-01-29 10:58:16 -05002093 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2094 S((pod, po))
2095
2096 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2097 S((po, pkd, pk))
2098
2099 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2100 S((pkd, pk))
2101
Yury Selivanov374375d2014-03-27 12:41:53 -04002102 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002103 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002104
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002105 def test_signature_object_pickle(self):
2106 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2107 foo_partial = functools.partial(foo, a=1)
2108
2109 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002110
2111 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2112 with self.subTest(pickle_ver=ver, subclass=False):
2113 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2114 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002115
2116 # Test that basic sub-classing works
2117 sig = inspect.signature(foo)
2118 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2119 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2120 mysig = MySignature().replace(parameters=myparams.values(),
2121 return_annotation=sig.return_annotation)
2122 self.assertTrue(isinstance(mysig, MySignature))
2123 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2124
2125 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2126 with self.subTest(pickle_ver=ver, subclass=True):
2127 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2128 self.assertEqual(mysig, sig_pickled)
2129 self.assertTrue(isinstance(sig_pickled, MySignature))
2130 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2131 MyParameter))
2132
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002133 def test_signature_immutability(self):
2134 def test(a):
2135 pass
2136 sig = inspect.signature(test)
2137
2138 with self.assertRaises(AttributeError):
2139 sig.foo = 'bar'
2140
2141 with self.assertRaises(TypeError):
2142 sig.parameters['a'] = None
2143
2144 def test_signature_on_noarg(self):
2145 def test():
2146 pass
2147 self.assertEqual(self.signature(test), ((), ...))
2148
2149 def test_signature_on_wargs(self):
2150 def test(a, b:'foo') -> 123:
2151 pass
2152 self.assertEqual(self.signature(test),
2153 ((('a', ..., ..., "positional_or_keyword"),
2154 ('b', ..., 'foo', "positional_or_keyword")),
2155 123))
2156
2157 def test_signature_on_wkwonly(self):
2158 def test(*, a:float, b:str) -> int:
2159 pass
2160 self.assertEqual(self.signature(test),
2161 ((('a', ..., float, "keyword_only"),
2162 ('b', ..., str, "keyword_only")),
2163 int))
2164
2165 def test_signature_on_complex_args(self):
2166 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2167 pass
2168 self.assertEqual(self.signature(test),
2169 ((('a', ..., ..., "positional_or_keyword"),
2170 ('b', 10, 'foo', "positional_or_keyword"),
2171 ('args', ..., 'bar', "var_positional"),
2172 ('spam', ..., 'baz', "keyword_only"),
2173 ('ham', 123, ..., "keyword_only"),
2174 ('kwargs', ..., int, "var_keyword")),
2175 ...))
2176
Dong-hee Na378d7062017-05-18 04:00:51 +09002177 def test_signature_without_self(self):
2178 def test_args_only(*args): # NOQA
2179 pass
2180
2181 def test_args_kwargs_only(*args, **kwargs): # NOQA
2182 pass
2183
2184 class A:
2185 @classmethod
2186 def test_classmethod(*args): # NOQA
2187 pass
2188
2189 @staticmethod
2190 def test_staticmethod(*args): # NOQA
2191 pass
2192
2193 f1 = functools.partialmethod((test_classmethod), 1)
2194 f2 = functools.partialmethod((test_args_only), 1)
2195 f3 = functools.partialmethod((test_staticmethod), 1)
2196 f4 = functools.partialmethod((test_args_kwargs_only),1)
2197
2198 self.assertEqual(self.signature(test_args_only),
2199 ((('args', ..., ..., 'var_positional'),), ...))
2200 self.assertEqual(self.signature(test_args_kwargs_only),
2201 ((('args', ..., ..., 'var_positional'),
2202 ('kwargs', ..., ..., 'var_keyword')), ...))
2203 self.assertEqual(self.signature(A.f1),
2204 ((('args', ..., ..., 'var_positional'),), ...))
2205 self.assertEqual(self.signature(A.f2),
2206 ((('args', ..., ..., 'var_positional'),), ...))
2207 self.assertEqual(self.signature(A.f3),
2208 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002209 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002210 ((('args', ..., ..., 'var_positional'),
2211 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002212 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002213 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2214 "Signature information for builtins requires docstrings")
2215 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002216 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002217
Larry Hastings5c661892014-01-24 06:17:25 -08002218 def test_unbound_method(o):
2219 """Use this to test unbound methods (things that should have a self)"""
2220 signature = inspect.signature(o)
2221 self.assertTrue(isinstance(signature, inspect.Signature))
2222 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2223 return signature
2224
2225 def test_callable(o):
2226 """Use this to test bound methods or normal callables (things that don't expect self)"""
2227 signature = inspect.signature(o)
2228 self.assertTrue(isinstance(signature, inspect.Signature))
2229 if signature.parameters:
2230 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2231 return signature
2232
2233 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002234 def p(name): return signature.parameters[name].default
2235 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002236 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002237 self.assertEqual(p('d'), 3.14)
2238 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002239 self.assertEqual(p('n'), None)
2240 self.assertEqual(p('t'), True)
2241 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002242 self.assertEqual(p('local'), 3)
2243 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002244 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002245
Larry Hastings5c661892014-01-24 06:17:25 -08002246 test_callable(object)
2247
2248 # normal method
2249 # (PyMethodDescr_Type, "method_descriptor")
2250 test_unbound_method(_pickle.Pickler.dump)
2251 d = _pickle.Pickler(io.StringIO())
2252 test_callable(d.dump)
2253
2254 # static method
2255 test_callable(str.maketrans)
2256 test_callable('abc'.maketrans)
2257
2258 # class method
2259 test_callable(dict.fromkeys)
2260 test_callable({}.fromkeys)
2261
2262 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2263 test_unbound_method(type.__call__)
2264 test_unbound_method(int.__add__)
2265 test_callable((3).__add__)
2266
2267 # _PyMethodWrapper_Type
2268 # support for 'method-wrapper'
2269 test_callable(min.__call__)
2270
Larry Hastings2623c8c2014-02-08 22:15:29 -08002271 # This doesn't work now.
2272 # (We don't have a valid signature for "type" in 3.4)
2273 with self.assertRaisesRegex(ValueError, "no signature found"):
2274 class ThisWorksNow:
2275 __call__ = type
2276 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002277
Yury Selivanov056e2652014-03-02 12:25:27 -05002278 # Regression test for issue #20786
2279 test_unbound_method(dict.__delitem__)
2280 test_unbound_method(property.__delete__)
2281
Zachary Ware8ef887c2015-04-13 18:22:35 -05002282 # Regression test for issue #20586
2283 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2284
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002285 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002286 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2287 "Signature information for builtins requires docstrings")
2288 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002289 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002290 func = _testcapi.docstring_with_signature_with_defaults
2291
2292 def decorator(func):
2293 @functools.wraps(func)
2294 def wrapper(*args, **kwargs) -> int:
2295 return func(*args, **kwargs)
2296 return wrapper
2297
2298 decorated_func = decorator(func)
2299
2300 self.assertEqual(inspect.signature(func),
2301 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002302
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002303 def wrapper_like(*args, **kwargs) -> int: pass
2304 self.assertEqual(inspect.signature(decorated_func,
2305 follow_wrapped=False),
2306 inspect.signature(wrapper_like))
2307
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002308 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002309 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002310 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002311 with self.assertRaisesRegex(ValueError,
2312 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002313 inspect.signature(_testcapi.docstring_no_signature)
2314
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002315 with self.assertRaisesRegex(ValueError,
2316 'no signature found for builtin'):
2317 inspect.signature(str)
2318
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002319 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002320 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002321 inspect.signature(42)
2322
Yury Selivanov63da7c72014-01-31 14:48:37 -05002323 def test_signature_from_functionlike_object(self):
2324 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2325 pass
2326
2327 class funclike:
2328 # Has to be callable, and have correct
2329 # __code__, __annotations__, __defaults__, __name__,
2330 # and __kwdefaults__ attributes
2331
2332 def __init__(self, func):
2333 self.__name__ = func.__name__
2334 self.__code__ = func.__code__
2335 self.__annotations__ = func.__annotations__
2336 self.__defaults__ = func.__defaults__
2337 self.__kwdefaults__ = func.__kwdefaults__
2338 self.func = func
2339
2340 def __call__(self, *args, **kwargs):
2341 return self.func(*args, **kwargs)
2342
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002343 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002344
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002345 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002346 self.assertEqual(sig_funclike, sig_func)
2347
2348 sig_funclike = inspect.signature(funclike(func))
2349 self.assertEqual(sig_funclike, sig_func)
2350
2351 # If object is not a duck type of function, then
2352 # signature will try to get a signature for its '__call__'
2353 # method
2354 fl = funclike(func)
2355 del fl.__defaults__
2356 self.assertEqual(self.signature(fl),
2357 ((('args', ..., ..., "var_positional"),
2358 ('kwargs', ..., ..., "var_keyword")),
2359 ...))
2360
Yury Selivanova773de02014-02-21 18:30:53 -05002361 # Test with cython-like builtins:
2362 _orig_isdesc = inspect.ismethoddescriptor
2363 def _isdesc(obj):
2364 if hasattr(obj, '_builtinmock'):
2365 return True
2366 return _orig_isdesc(obj)
2367
2368 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2369 builtin_func = funclike(func)
2370 # Make sure that our mock setup is working
2371 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2372 builtin_func._builtinmock = True
2373 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2374 self.assertEqual(inspect.signature(builtin_func), sig_func)
2375
Yury Selivanov63da7c72014-01-31 14:48:37 -05002376 def test_signature_functionlike_class(self):
2377 # We only want to duck type function-like objects,
2378 # not classes.
2379
2380 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2381 pass
2382
2383 class funclike:
2384 def __init__(self, marker):
2385 pass
2386
2387 __name__ = func.__name__
2388 __code__ = func.__code__
2389 __annotations__ = func.__annotations__
2390 __defaults__ = func.__defaults__
2391 __kwdefaults__ = func.__kwdefaults__
2392
Yury Selivanov63da7c72014-01-31 14:48:37 -05002393 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2394
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002395 def test_signature_on_method(self):
2396 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002397 def __init__(*args):
2398 pass
2399 def m1(self, arg1, arg2=1) -> int:
2400 pass
2401 def m2(*args):
2402 pass
2403 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002404 pass
2405
Yury Selivanov62560fb2014-01-28 12:26:24 -05002406 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002407 ((('arg1', ..., ..., "positional_or_keyword"),
2408 ('arg2', 1, ..., "positional_or_keyword")),
2409 int))
2410
Yury Selivanov62560fb2014-01-28 12:26:24 -05002411 self.assertEqual(self.signature(Test().m2),
2412 ((('args', ..., ..., "var_positional"),),
2413 ...))
2414
2415 self.assertEqual(self.signature(Test),
2416 ((('args', ..., ..., "var_positional"),),
2417 ...))
2418
2419 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2420 self.signature(Test())
2421
Yury Selivanov46c759d2015-05-27 21:56:53 -04002422 def test_signature_wrapped_bound_method(self):
2423 # Issue 24298
2424 class Test:
2425 def m1(self, arg1, arg2=1) -> int:
2426 pass
2427 @functools.wraps(Test().m1)
2428 def m1d(*args, **kwargs):
2429 pass
2430 self.assertEqual(self.signature(m1d),
2431 ((('arg1', ..., ..., "positional_or_keyword"),
2432 ('arg2', 1, ..., "positional_or_keyword")),
2433 int))
2434
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002435 def test_signature_on_classmethod(self):
2436 class Test:
2437 @classmethod
2438 def foo(cls, arg1, *, arg2=1):
2439 pass
2440
2441 meth = Test().foo
2442 self.assertEqual(self.signature(meth),
2443 ((('arg1', ..., ..., "positional_or_keyword"),
2444 ('arg2', 1, ..., "keyword_only")),
2445 ...))
2446
2447 meth = Test.foo
2448 self.assertEqual(self.signature(meth),
2449 ((('arg1', ..., ..., "positional_or_keyword"),
2450 ('arg2', 1, ..., "keyword_only")),
2451 ...))
2452
2453 def test_signature_on_staticmethod(self):
2454 class Test:
2455 @staticmethod
2456 def foo(cls, *, arg):
2457 pass
2458
2459 meth = Test().foo
2460 self.assertEqual(self.signature(meth),
2461 ((('cls', ..., ..., "positional_or_keyword"),
2462 ('arg', ..., ..., "keyword_only")),
2463 ...))
2464
2465 meth = Test.foo
2466 self.assertEqual(self.signature(meth),
2467 ((('cls', ..., ..., "positional_or_keyword"),
2468 ('arg', ..., ..., "keyword_only")),
2469 ...))
2470
2471 def test_signature_on_partial(self):
2472 from functools import partial
2473
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002474 Parameter = inspect.Parameter
2475
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002476 def test():
2477 pass
2478
2479 self.assertEqual(self.signature(partial(test)), ((), ...))
2480
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002481 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002482 inspect.signature(partial(test, 1))
2483
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002484 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002485 inspect.signature(partial(test, a=1))
2486
2487 def test(a, b, *, c, d):
2488 pass
2489
2490 self.assertEqual(self.signature(partial(test)),
2491 ((('a', ..., ..., "positional_or_keyword"),
2492 ('b', ..., ..., "positional_or_keyword"),
2493 ('c', ..., ..., "keyword_only"),
2494 ('d', ..., ..., "keyword_only")),
2495 ...))
2496
2497 self.assertEqual(self.signature(partial(test, 1)),
2498 ((('b', ..., ..., "positional_or_keyword"),
2499 ('c', ..., ..., "keyword_only"),
2500 ('d', ..., ..., "keyword_only")),
2501 ...))
2502
2503 self.assertEqual(self.signature(partial(test, 1, c=2)),
2504 ((('b', ..., ..., "positional_or_keyword"),
2505 ('c', 2, ..., "keyword_only"),
2506 ('d', ..., ..., "keyword_only")),
2507 ...))
2508
2509 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2510 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002511 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002512 ('c', 2, ..., "keyword_only"),
2513 ('d', ..., ..., "keyword_only")),
2514 ...))
2515
2516 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002517 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002518 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002519 ('d', ..., ..., "keyword_only")),
2520 ...))
2521
2522 self.assertEqual(self.signature(partial(test, a=1)),
2523 ((('a', 1, ..., "keyword_only"),
2524 ('b', ..., ..., "keyword_only"),
2525 ('c', ..., ..., "keyword_only"),
2526 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002527 ...))
2528
2529 def test(a, *args, b, **kwargs):
2530 pass
2531
2532 self.assertEqual(self.signature(partial(test, 1)),
2533 ((('args', ..., ..., "var_positional"),
2534 ('b', ..., ..., "keyword_only"),
2535 ('kwargs', ..., ..., "var_keyword")),
2536 ...))
2537
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002538 self.assertEqual(self.signature(partial(test, a=1)),
2539 ((('a', 1, ..., "keyword_only"),
2540 ('b', ..., ..., "keyword_only"),
2541 ('kwargs', ..., ..., "var_keyword")),
2542 ...))
2543
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002544 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2545 ((('args', ..., ..., "var_positional"),
2546 ('b', ..., ..., "keyword_only"),
2547 ('kwargs', ..., ..., "var_keyword")),
2548 ...))
2549
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002550 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2551 ((('args', ..., ..., "var_positional"),
2552 ('b', ..., ..., "keyword_only"),
2553 ('kwargs', ..., ..., "var_keyword")),
2554 ...))
2555
2556 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2557 ((('args', ..., ..., "var_positional"),
2558 ('b', 0, ..., "keyword_only"),
2559 ('kwargs', ..., ..., "var_keyword")),
2560 ...))
2561
2562 self.assertEqual(self.signature(partial(test, b=0)),
2563 ((('a', ..., ..., "positional_or_keyword"),
2564 ('args', ..., ..., "var_positional"),
2565 ('b', 0, ..., "keyword_only"),
2566 ('kwargs', ..., ..., "var_keyword")),
2567 ...))
2568
2569 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2570 ((('a', ..., ..., "positional_or_keyword"),
2571 ('args', ..., ..., "var_positional"),
2572 ('b', 0, ..., "keyword_only"),
2573 ('kwargs', ..., ..., "var_keyword")),
2574 ...))
2575
2576 def test(a, b, c:int) -> 42:
2577 pass
2578
2579 sig = test.__signature__ = inspect.signature(test)
2580
2581 self.assertEqual(self.signature(partial(partial(test, 1))),
2582 ((('b', ..., ..., "positional_or_keyword"),
2583 ('c', ..., int, "positional_or_keyword")),
2584 42))
2585
2586 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2587 ((('c', ..., int, "positional_or_keyword"),),
2588 42))
2589
2590 psig = inspect.signature(partial(partial(test, 1), 2))
2591
2592 def foo(a):
2593 return a
2594 _foo = partial(partial(foo, a=10), a=20)
2595 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002596 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002597 ...))
2598 # check that we don't have any side-effects in signature(),
2599 # and the partial object is still functioning
2600 self.assertEqual(_foo(), 20)
2601
2602 def foo(a, b, c):
2603 return a, b, c
2604 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002605
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002606 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002607 ((('b', 30, ..., "keyword_only"),
2608 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002609 ...))
2610 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002611
2612 def foo(a, b, c, *, d):
2613 return a, b, c, d
2614 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2615 self.assertEqual(self.signature(_foo),
2616 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002617 ('b', 10, ..., "keyword_only"),
2618 ('c', 20, ..., "keyword_only"),
2619 ('d', 30, ..., "keyword_only"),
2620 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002621 ...))
2622 ba = inspect.signature(_foo).bind(a=200, b=11)
2623 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2624
2625 def foo(a=1, b=2, c=3):
2626 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002627 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2628
2629 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002630 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002631
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002632 ba = inspect.signature(_foo).bind(11, 12)
2633 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002634
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002635 ba = inspect.signature(_foo).bind(11, b=12)
2636 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002637
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002638 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002639 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2640
2641 _foo = partial(_foo, b=10, c=20)
2642 ba = inspect.signature(_foo).bind(12)
2643 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2644
2645
2646 def foo(a, b, c, d, **kwargs):
2647 pass
2648 sig = inspect.signature(foo)
2649 params = sig.parameters.copy()
2650 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2651 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2652 foo.__signature__ = inspect.Signature(params.values())
2653 sig = inspect.signature(foo)
2654 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2655
2656 self.assertEqual(self.signature(partial(foo, 1)),
2657 ((('b', ..., ..., 'positional_only'),
2658 ('c', ..., ..., 'positional_or_keyword'),
2659 ('d', ..., ..., 'positional_or_keyword'),
2660 ('kwargs', ..., ..., 'var_keyword')),
2661 ...))
2662
2663 self.assertEqual(self.signature(partial(foo, 1, 2)),
2664 ((('c', ..., ..., 'positional_or_keyword'),
2665 ('d', ..., ..., 'positional_or_keyword'),
2666 ('kwargs', ..., ..., 'var_keyword')),
2667 ...))
2668
2669 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2670 ((('d', ..., ..., 'positional_or_keyword'),
2671 ('kwargs', ..., ..., 'var_keyword')),
2672 ...))
2673
2674 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2675 ((('c', 3, ..., 'keyword_only'),
2676 ('d', ..., ..., 'keyword_only'),
2677 ('kwargs', ..., ..., 'var_keyword')),
2678 ...))
2679
2680 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2681 ((('b', ..., ..., 'positional_only'),
2682 ('c', 3, ..., 'keyword_only'),
2683 ('d', ..., ..., 'keyword_only'),
2684 ('kwargs', ..., ..., 'var_keyword')),
2685 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002686
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002687 def test_signature_on_partialmethod(self):
2688 from functools import partialmethod
2689
2690 class Spam:
2691 def test():
2692 pass
2693 ham = partialmethod(test)
2694
2695 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2696 inspect.signature(Spam.ham)
2697
2698 class Spam:
2699 def test(it, a, *, c) -> 'spam':
2700 pass
2701 ham = partialmethod(test, c=1)
2702
2703 self.assertEqual(self.signature(Spam.ham),
2704 ((('it', ..., ..., 'positional_or_keyword'),
2705 ('a', ..., ..., 'positional_or_keyword'),
2706 ('c', 1, ..., 'keyword_only')),
2707 'spam'))
2708
2709 self.assertEqual(self.signature(Spam().ham),
2710 ((('a', ..., ..., 'positional_or_keyword'),
2711 ('c', 1, ..., 'keyword_only')),
2712 'spam'))
2713
Yury Selivanov8a387212018-03-06 12:59:45 -05002714 class Spam:
2715 def test(self: 'anno', x):
2716 pass
2717
2718 g = partialmethod(test, 1)
2719
2720 self.assertEqual(self.signature(Spam.g),
2721 ((('self', ..., 'anno', 'positional_or_keyword'),),
2722 ...))
2723
Yury Selivanov0486f812014-01-29 12:18:59 -05002724 def test_signature_on_fake_partialmethod(self):
2725 def foo(a): pass
2726 foo._partialmethod = 'spam'
2727 self.assertEqual(str(inspect.signature(foo)), '(a)')
2728
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002729 def test_signature_on_decorated(self):
2730 import functools
2731
2732 def decorator(func):
2733 @functools.wraps(func)
2734 def wrapper(*args, **kwargs) -> int:
2735 return func(*args, **kwargs)
2736 return wrapper
2737
2738 class Foo:
2739 @decorator
2740 def bar(self, a, b):
2741 pass
2742
2743 self.assertEqual(self.signature(Foo.bar),
2744 ((('self', ..., ..., "positional_or_keyword"),
2745 ('a', ..., ..., "positional_or_keyword"),
2746 ('b', ..., ..., "positional_or_keyword")),
2747 ...))
2748
2749 self.assertEqual(self.signature(Foo().bar),
2750 ((('a', ..., ..., "positional_or_keyword"),
2751 ('b', ..., ..., "positional_or_keyword")),
2752 ...))
2753
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002754 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2755 ((('args', ..., ..., "var_positional"),
2756 ('kwargs', ..., ..., "var_keyword")),
2757 ...)) # functools.wraps will copy __annotations__
2758 # from "func" to "wrapper", hence no
2759 # return_annotation
2760
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002761 # Test that we handle method wrappers correctly
2762 def decorator(func):
2763 @functools.wraps(func)
2764 def wrapper(*args, **kwargs) -> int:
2765 return func(42, *args, **kwargs)
2766 sig = inspect.signature(func)
2767 new_params = tuple(sig.parameters.values())[1:]
2768 wrapper.__signature__ = sig.replace(parameters=new_params)
2769 return wrapper
2770
2771 class Foo:
2772 @decorator
2773 def __call__(self, a, b):
2774 pass
2775
2776 self.assertEqual(self.signature(Foo.__call__),
2777 ((('a', ..., ..., "positional_or_keyword"),
2778 ('b', ..., ..., "positional_or_keyword")),
2779 ...))
2780
2781 self.assertEqual(self.signature(Foo().__call__),
2782 ((('b', ..., ..., "positional_or_keyword"),),
2783 ...))
2784
Nick Coghlane8c45d62013-07-28 20:00:01 +10002785 # Test we handle __signature__ partway down the wrapper stack
2786 def wrapped_foo_call():
2787 pass
2788 wrapped_foo_call.__wrapped__ = Foo.__call__
2789
2790 self.assertEqual(self.signature(wrapped_foo_call),
2791 ((('a', ..., ..., "positional_or_keyword"),
2792 ('b', ..., ..., "positional_or_keyword")),
2793 ...))
2794
2795
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002796 def test_signature_on_class(self):
2797 class C:
2798 def __init__(self, a):
2799 pass
2800
2801 self.assertEqual(self.signature(C),
2802 ((('a', ..., ..., "positional_or_keyword"),),
2803 ...))
2804
2805 class CM(type):
2806 def __call__(cls, a):
2807 pass
2808 class C(metaclass=CM):
2809 def __init__(self, b):
2810 pass
2811
2812 self.assertEqual(self.signature(C),
2813 ((('a', ..., ..., "positional_or_keyword"),),
2814 ...))
2815
2816 class CM(type):
2817 def __new__(mcls, name, bases, dct, *, foo=1):
2818 return super().__new__(mcls, name, bases, dct)
2819 class C(metaclass=CM):
2820 def __init__(self, b):
2821 pass
2822
2823 self.assertEqual(self.signature(C),
2824 ((('b', ..., ..., "positional_or_keyword"),),
2825 ...))
2826
2827 self.assertEqual(self.signature(CM),
2828 ((('name', ..., ..., "positional_or_keyword"),
2829 ('bases', ..., ..., "positional_or_keyword"),
2830 ('dct', ..., ..., "positional_or_keyword"),
2831 ('foo', 1, ..., "keyword_only")),
2832 ...))
2833
2834 class CMM(type):
2835 def __new__(mcls, name, bases, dct, *, foo=1):
2836 return super().__new__(mcls, name, bases, dct)
2837 def __call__(cls, nm, bs, dt):
2838 return type(nm, bs, dt)
2839 class CM(type, metaclass=CMM):
2840 def __new__(mcls, name, bases, dct, *, bar=2):
2841 return super().__new__(mcls, name, bases, dct)
2842 class C(metaclass=CM):
2843 def __init__(self, b):
2844 pass
2845
2846 self.assertEqual(self.signature(CMM),
2847 ((('name', ..., ..., "positional_or_keyword"),
2848 ('bases', ..., ..., "positional_or_keyword"),
2849 ('dct', ..., ..., "positional_or_keyword"),
2850 ('foo', 1, ..., "keyword_only")),
2851 ...))
2852
2853 self.assertEqual(self.signature(CM),
2854 ((('nm', ..., ..., "positional_or_keyword"),
2855 ('bs', ..., ..., "positional_or_keyword"),
2856 ('dt', ..., ..., "positional_or_keyword")),
2857 ...))
2858
2859 self.assertEqual(self.signature(C),
2860 ((('b', ..., ..., "positional_or_keyword"),),
2861 ...))
2862
2863 class CM(type):
2864 def __init__(cls, name, bases, dct, *, bar=2):
2865 return super().__init__(name, bases, dct)
2866 class C(metaclass=CM):
2867 def __init__(self, b):
2868 pass
2869
2870 self.assertEqual(self.signature(CM),
2871 ((('name', ..., ..., "positional_or_keyword"),
2872 ('bases', ..., ..., "positional_or_keyword"),
2873 ('dct', ..., ..., "positional_or_keyword"),
2874 ('bar', 2, ..., "keyword_only")),
2875 ...))
2876
Yury Selivanov145dff82014-02-01 13:49:29 -05002877 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2878 "Signature information for builtins requires docstrings")
2879 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002880 # Test classes without user-defined __init__ or __new__
2881 class C: pass
2882 self.assertEqual(str(inspect.signature(C)), '()')
2883 class D(C): pass
2884 self.assertEqual(str(inspect.signature(D)), '()')
2885
2886 # Test meta-classes without user-defined __init__ or __new__
2887 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002888 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002889 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2890 self.assertEqual(inspect.signature(C), None)
2891 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2892 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002893
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002894 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2895 "Signature information for builtins requires docstrings")
2896 def test_signature_on_builtin_class(self):
2897 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2898 '(file, protocol=None, fix_imports=True)')
2899
2900 class P(_pickle.Pickler): pass
2901 class EmptyTrait: pass
2902 class P2(EmptyTrait, P): pass
2903 self.assertEqual(str(inspect.signature(P)),
2904 '(file, protocol=None, fix_imports=True)')
2905 self.assertEqual(str(inspect.signature(P2)),
2906 '(file, protocol=None, fix_imports=True)')
2907
2908 class P3(P2):
2909 def __init__(self, spam):
2910 pass
2911 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2912
2913 class MetaP(type):
2914 def __call__(cls, foo, bar):
2915 pass
2916 class P4(P2, metaclass=MetaP):
2917 pass
2918 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2919
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002920 def test_signature_on_callable_objects(self):
2921 class Foo:
2922 def __call__(self, a):
2923 pass
2924
2925 self.assertEqual(self.signature(Foo()),
2926 ((('a', ..., ..., "positional_or_keyword"),),
2927 ...))
2928
2929 class Spam:
2930 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002931 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002932 inspect.signature(Spam())
2933
2934 class Bar(Spam, Foo):
2935 pass
2936
2937 self.assertEqual(self.signature(Bar()),
2938 ((('a', ..., ..., "positional_or_keyword"),),
2939 ...))
2940
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002941 class Wrapped:
2942 pass
2943 Wrapped.__wrapped__ = lambda a: None
2944 self.assertEqual(self.signature(Wrapped),
2945 ((('a', ..., ..., "positional_or_keyword"),),
2946 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002947 # wrapper loop:
2948 Wrapped.__wrapped__ = Wrapped
2949 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2950 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002951
2952 def test_signature_on_lambdas(self):
2953 self.assertEqual(self.signature((lambda a=10: a)),
2954 ((('a', 10, ..., "positional_or_keyword"),),
2955 ...))
2956
2957 def test_signature_equality(self):
2958 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002959 self.assertFalse(inspect.signature(foo) == 42)
2960 self.assertTrue(inspect.signature(foo) != 42)
2961 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2962 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002963
2964 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002965 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2966 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002967 self.assertEqual(
2968 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002969
2970 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002971 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2972 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002973 self.assertNotEqual(
2974 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002975
2976 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002977 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2978 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002979 self.assertNotEqual(
2980 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002981
2982 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002983 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2984 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002985 self.assertNotEqual(
2986 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002987
2988 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002989 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2990 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002991 self.assertNotEqual(
2992 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002993
2994 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002995 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2996 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002997 self.assertNotEqual(
2998 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002999 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003000 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3001 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003002 self.assertNotEqual(
3003 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003004
3005 def foo(*, a, b, c): pass
3006 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003007 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3008 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003009 self.assertEqual(
3010 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003011
3012 def foo(*, a=1, b, c): pass
3013 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003014 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3015 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003016 self.assertEqual(
3017 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003018
3019 def foo(pos, *, a=1, b, c): pass
3020 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003021 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3022 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003023 self.assertEqual(
3024 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003025
3026 def foo(pos, *, a, b, c): pass
3027 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003028 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3029 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003030 self.assertNotEqual(
3031 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003032
3033 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3034 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003035 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3036 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003037 self.assertEqual(
3038 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003039
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003040 def test_signature_hashable(self):
3041 S = inspect.Signature
3042 P = inspect.Parameter
3043
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003044 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003045 foo_sig = inspect.signature(foo)
3046
3047 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3048
3049 self.assertEqual(hash(foo_sig), hash(manual_sig))
3050 self.assertNotEqual(hash(foo_sig),
3051 hash(manual_sig.replace(return_annotation='spam')))
3052
3053 def bar(a) -> 1: pass
3054 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3055
3056 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003057 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003058 hash(inspect.signature(foo))
3059
3060 def foo(a) -> {}: pass
3061 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3062 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003063
3064 def test_signature_str(self):
3065 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3066 pass
3067 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003068 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003069
3070 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3071 pass
3072 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003073 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003074
3075 def foo():
3076 pass
3077 self.assertEqual(str(inspect.signature(foo)), '()')
3078
3079 def test_signature_str_positional_only(self):
3080 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003081 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003082
3083 def test(a_po, *, b, **kwargs):
3084 return a_po, kwargs
3085
3086 sig = inspect.signature(test)
3087 new_params = list(sig.parameters.values())
3088 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3089 test.__signature__ = sig.replace(parameters=new_params)
3090
3091 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003092 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003093
Yury Selivanov2393dca2014-01-27 15:07:58 -05003094 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3095 '(foo, /)')
3096
3097 self.assertEqual(str(S(parameters=[
3098 P('foo', P.POSITIONAL_ONLY),
3099 P('bar', P.VAR_KEYWORD)])),
3100 '(foo, /, **bar)')
3101
3102 self.assertEqual(str(S(parameters=[
3103 P('foo', P.POSITIONAL_ONLY),
3104 P('bar', P.VAR_POSITIONAL)])),
3105 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003106
3107 def test_signature_replace_anno(self):
3108 def test() -> 42:
3109 pass
3110
3111 sig = inspect.signature(test)
3112 sig = sig.replace(return_annotation=None)
3113 self.assertIs(sig.return_annotation, None)
3114 sig = sig.replace(return_annotation=sig.empty)
3115 self.assertIs(sig.return_annotation, sig.empty)
3116 sig = sig.replace(return_annotation=42)
3117 self.assertEqual(sig.return_annotation, 42)
3118 self.assertEqual(sig, inspect.signature(test))
3119
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003120 def test_signature_on_mangled_parameters(self):
3121 class Spam:
3122 def foo(self, __p1:1=2, *, __p2:2=3):
3123 pass
3124 class Ham(Spam):
3125 pass
3126
3127 self.assertEqual(self.signature(Spam.foo),
3128 ((('self', ..., ..., "positional_or_keyword"),
3129 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3130 ('_Spam__p2', 3, 2, "keyword_only")),
3131 ...))
3132
3133 self.assertEqual(self.signature(Spam.foo),
3134 self.signature(Ham.foo))
3135
Yury Selivanovda396452014-03-27 12:09:24 -04003136 def test_signature_from_callable_python_obj(self):
3137 class MySignature(inspect.Signature): pass
3138 def foo(a, *, b:1): pass
3139 foo_sig = MySignature.from_callable(foo)
3140 self.assertTrue(isinstance(foo_sig, MySignature))
3141
3142 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3143 "Signature information for builtins requires docstrings")
3144 def test_signature_from_callable_builtin_obj(self):
3145 class MySignature(inspect.Signature): pass
3146 sig = MySignature.from_callable(_pickle.Pickler)
3147 self.assertTrue(isinstance(sig, MySignature))
3148
larryhastingsf36ba122018-01-28 11:13:09 -08003149 def test_signature_definition_order_preserved_on_kwonly(self):
3150 for fn in signatures_with_lexicographic_keyword_only_parameters():
3151 signature = inspect.signature(fn)
3152 l = list(signature.parameters)
3153 sorted_l = sorted(l)
3154 self.assertTrue(l)
3155 self.assertEqual(l, sorted_l)
3156 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3157 l = list(signature.parameters)
3158 self.assertEqual(l, unsorted_keyword_only_parameters)
3159
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003160
3161class TestParameterObject(unittest.TestCase):
3162 def test_signature_parameter_kinds(self):
3163 P = inspect.Parameter
3164 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3165 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3166
3167 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3168 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3169
3170 def test_signature_parameter_object(self):
3171 p = inspect.Parameter('foo', default=10,
3172 kind=inspect.Parameter.POSITIONAL_ONLY)
3173 self.assertEqual(p.name, 'foo')
3174 self.assertEqual(p.default, 10)
3175 self.assertIs(p.annotation, p.empty)
3176 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3177
Dong-hee Naa9cab432018-05-30 00:04:08 +09003178 with self.assertRaisesRegex(ValueError, "value '123' is "
3179 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003180 inspect.Parameter('foo', default=10, kind='123')
3181
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003182 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003183 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3184
Yury Selivanov2393dca2014-01-27 15:07:58 -05003185 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003186 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3187
Yury Selivanov2393dca2014-01-27 15:07:58 -05003188 with self.assertRaisesRegex(ValueError,
3189 'is not a valid parameter name'):
3190 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3191
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003192 with self.assertRaisesRegex(ValueError,
3193 'is not a valid parameter name'):
3194 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3195
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003196 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003197 inspect.Parameter('a', default=42,
3198 kind=inspect.Parameter.VAR_KEYWORD)
3199
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003200 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003201 inspect.Parameter('a', default=42,
3202 kind=inspect.Parameter.VAR_POSITIONAL)
3203
3204 p = inspect.Parameter('a', default=42,
3205 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003206 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003207 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3208
3209 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003210 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003211
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003212 def test_signature_parameter_hashable(self):
3213 P = inspect.Parameter
3214 foo = P('foo', kind=P.POSITIONAL_ONLY)
3215 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3216 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3217 default=42)))
3218 self.assertNotEqual(hash(foo),
3219 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3220
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003221 def test_signature_parameter_equality(self):
3222 P = inspect.Parameter
3223 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3224
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003225 self.assertTrue(p == p)
3226 self.assertFalse(p != p)
3227 self.assertFalse(p == 42)
3228 self.assertTrue(p != 42)
3229 self.assertTrue(p == EqualsToAll())
3230 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003231
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003232 self.assertTrue(p == P('foo', default=42,
3233 kind=inspect.Parameter.KEYWORD_ONLY))
3234 self.assertFalse(p != P('foo', default=42,
3235 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003236
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003237 def test_signature_parameter_replace(self):
3238 p = inspect.Parameter('foo', default=42,
3239 kind=inspect.Parameter.KEYWORD_ONLY)
3240
3241 self.assertIsNot(p, p.replace())
3242 self.assertEqual(p, p.replace())
3243
3244 p2 = p.replace(annotation=1)
3245 self.assertEqual(p2.annotation, 1)
3246 p2 = p2.replace(annotation=p2.empty)
3247 self.assertEqual(p, p2)
3248
3249 p2 = p2.replace(name='bar')
3250 self.assertEqual(p2.name, 'bar')
3251 self.assertNotEqual(p2, p)
3252
Yury Selivanov2393dca2014-01-27 15:07:58 -05003253 with self.assertRaisesRegex(ValueError,
3254 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003255 p2 = p2.replace(name=p2.empty)
3256
3257 p2 = p2.replace(name='foo', default=None)
3258 self.assertIs(p2.default, None)
3259 self.assertNotEqual(p2, p)
3260
3261 p2 = p2.replace(name='foo', default=p2.empty)
3262 self.assertIs(p2.default, p2.empty)
3263
3264
3265 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3266 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3267 self.assertNotEqual(p2, p)
3268
Dong-hee Naa9cab432018-05-30 00:04:08 +09003269 with self.assertRaisesRegex(ValueError,
3270 "value <class 'inspect._empty'> "
3271 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003272 p2 = p2.replace(kind=p2.empty)
3273
3274 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3275 self.assertEqual(p2, p)
3276
3277 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003278 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3279 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003280
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003281 @cpython_only
3282 def test_signature_parameter_implicit(self):
3283 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003284 'implicit arguments must be passed as '
3285 'positional or keyword arguments, '
3286 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003287 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3288
3289 param = inspect.Parameter(
3290 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3291 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3292 self.assertEqual(param.name, 'implicit0')
3293
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003294 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003295 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003296
3297 with self.assertRaises(AttributeError):
3298 p.foo = 'bar'
3299
3300 with self.assertRaises(AttributeError):
3301 p.kind = 123
3302
3303
3304class TestSignatureBind(unittest.TestCase):
3305 @staticmethod
3306 def call(func, *args, **kwargs):
3307 sig = inspect.signature(func)
3308 ba = sig.bind(*args, **kwargs)
3309 return func(*ba.args, **ba.kwargs)
3310
3311 def test_signature_bind_empty(self):
3312 def test():
3313 return 42
3314
3315 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003316 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003317 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003318 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003319 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003320 with self.assertRaisesRegex(
3321 TypeError, "got an unexpected keyword argument 'spam'"):
3322
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003323 self.call(test, spam=1)
3324
3325 def test_signature_bind_var(self):
3326 def test(*args, **kwargs):
3327 return args, kwargs
3328
3329 self.assertEqual(self.call(test), ((), {}))
3330 self.assertEqual(self.call(test, 1), ((1,), {}))
3331 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3332 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3333 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3334 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3335 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3336 ((1, 2), {'foo': 'bar'}))
3337
3338 def test_signature_bind_just_args(self):
3339 def test(a, b, c):
3340 return a, b, c
3341
3342 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3343
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003344 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003345 self.call(test, 1, 2, 3, 4)
3346
Yury Selivanov86872752015-05-19 00:27:49 -04003347 with self.assertRaisesRegex(TypeError,
3348 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003349 self.call(test, 1)
3350
Yury Selivanov86872752015-05-19 00:27:49 -04003351 with self.assertRaisesRegex(TypeError,
3352 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003353 self.call(test)
3354
3355 def test(a, b, c=10):
3356 return a, b, c
3357 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3358 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3359
3360 def test(a=1, b=2, c=3):
3361 return a, b, c
3362 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3363 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3364 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3365
3366 def test_signature_bind_varargs_order(self):
3367 def test(*args):
3368 return args
3369
3370 self.assertEqual(self.call(test), ())
3371 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3372
3373 def test_signature_bind_args_and_varargs(self):
3374 def test(a, b, c=3, *args):
3375 return a, b, c, args
3376
3377 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3378 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3379 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3380 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3381
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003382 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003383 "multiple values for argument 'c'"):
3384 self.call(test, 1, 2, 3, c=4)
3385
3386 def test_signature_bind_just_kwargs(self):
3387 def test(**kwargs):
3388 return kwargs
3389
3390 self.assertEqual(self.call(test), {})
3391 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3392 {'foo': 'bar', 'spam': 'ham'})
3393
3394 def test_signature_bind_args_and_kwargs(self):
3395 def test(a, b, c=3, **kwargs):
3396 return a, b, c, kwargs
3397
3398 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3399 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3400 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3401 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3402 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3403 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3404 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3405 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3406 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3407 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3408 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3409 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3410 (1, 2, 4, {'foo': 'bar'}))
3411 self.assertEqual(self.call(test, c=5, a=4, b=3),
3412 (4, 3, 5, {}))
3413
3414 def test_signature_bind_kwonly(self):
3415 def test(*, foo):
3416 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003417 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003418 'too many positional arguments'):
3419 self.call(test, 1)
3420 self.assertEqual(self.call(test, foo=1), 1)
3421
3422 def test(a, *, foo=1, bar):
3423 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003424 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003425 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003426 self.call(test, 1)
3427
3428 def test(foo, *, bar):
3429 return foo, bar
3430 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3431 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3432
Yury Selivanov86872752015-05-19 00:27:49 -04003433 with self.assertRaisesRegex(
3434 TypeError, "got an unexpected keyword argument 'spam'"):
3435
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003436 self.call(test, bar=2, foo=1, spam=10)
3437
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003438 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003439 'too many positional arguments'):
3440 self.call(test, 1, 2)
3441
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003442 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003443 'too many positional arguments'):
3444 self.call(test, 1, 2, bar=2)
3445
Yury Selivanov86872752015-05-19 00:27:49 -04003446 with self.assertRaisesRegex(
3447 TypeError, "got an unexpected keyword argument 'spam'"):
3448
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003449 self.call(test, 1, bar=2, spam='ham')
3450
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, **bin):
3456 return foo, bar, bin
3457 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3458 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3459 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3460 (1, 2, {'spam': 'ham'}))
3461 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3462 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003463 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003464 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003465 self.call(test, spam='ham', bar=2)
3466 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3467 (1, 2, {'bin': 1, 'spam': 10}))
3468
3469 def test_signature_bind_arguments(self):
3470 def test(a, *args, b, z=100, **kwargs):
3471 pass
3472 sig = inspect.signature(test)
3473 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3474 # we won't have 'z' argument in the bound arguments object, as we didn't
3475 # pass it to the 'bind'
3476 self.assertEqual(tuple(ba.arguments.items()),
3477 (('a', 10), ('args', (20,)), ('b', 30),
3478 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3479 self.assertEqual(ba.kwargs,
3480 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3481 self.assertEqual(ba.args, (10, 20))
3482
3483 def test_signature_bind_positional_only(self):
3484 P = inspect.Parameter
3485
3486 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3487 return a_po, b_po, c_po, foo, bar, kwargs
3488
3489 sig = inspect.signature(test)
3490 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3491 for name in ('a_po', 'b_po', 'c_po'):
3492 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3493 new_sig = sig.replace(parameters=new_params.values())
3494 test.__signature__ = new_sig
3495
3496 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3497 (1, 2, 4, 5, 6, {}))
3498
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003499 self.assertEqual(self.call(test, 1, 2),
3500 (1, 2, 3, 42, 50, {}))
3501
3502 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3503 (1, 2, 3, 4, 5, {}))
3504
3505 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3506 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3507
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003508 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003509 self.call(test, 1, 2, c_po=4)
3510
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003511 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003512 self.call(test, a_po=1, b_po=2)
3513
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003514 def test_signature_bind_with_self_arg(self):
3515 # Issue #17071: one of the parameters is named "self
3516 def test(a, self, b):
3517 pass
3518 sig = inspect.signature(test)
3519 ba = sig.bind(1, 2, 3)
3520 self.assertEqual(ba.args, (1, 2, 3))
3521 ba = sig.bind(1, self=2, b=3)
3522 self.assertEqual(ba.args, (1, 2, 3))
3523
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003524 def test_signature_bind_vararg_name(self):
3525 def test(a, *args):
3526 return a, args
3527 sig = inspect.signature(test)
3528
Yury Selivanov86872752015-05-19 00:27:49 -04003529 with self.assertRaisesRegex(
3530 TypeError, "got an unexpected keyword argument 'args'"):
3531
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003532 sig.bind(a=0, args=1)
3533
3534 def test(*args, **kwargs):
3535 return args, kwargs
3536 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3537
3538 sig = inspect.signature(test)
3539 ba = sig.bind(args=1)
3540 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3541
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003542 @cpython_only
3543 def test_signature_bind_implicit_arg(self):
3544 # Issue #19611: getcallargs should work with set comprehensions
3545 def make_set():
3546 return {z * z for z in range(5)}
3547 setcomp_code = make_set.__code__.co_consts[1]
3548 setcomp_func = types.FunctionType(setcomp_code, {})
3549
3550 iterator = iter(range(5))
3551 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3552
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003553
3554class TestBoundArguments(unittest.TestCase):
3555 def test_signature_bound_arguments_unhashable(self):
3556 def foo(a): pass
3557 ba = inspect.signature(foo).bind(1)
3558
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003559 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003560 hash(ba)
3561
3562 def test_signature_bound_arguments_equality(self):
3563 def foo(a): pass
3564 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003565 self.assertTrue(ba == ba)
3566 self.assertFalse(ba != ba)
3567 self.assertTrue(ba == EqualsToAll())
3568 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003569
3570 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003571 self.assertTrue(ba == ba2)
3572 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003573
3574 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003575 self.assertFalse(ba == ba3)
3576 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003577 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003578 self.assertTrue(ba == ba3)
3579 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003580
3581 def bar(b): pass
3582 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003583 self.assertFalse(ba == ba4)
3584 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003585
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003586 def foo(*, a, b): pass
3587 sig = inspect.signature(foo)
3588 ba1 = sig.bind(a=1, b=2)
3589 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003590 self.assertTrue(ba1 == ba2)
3591 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003592
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003593 def test_signature_bound_arguments_pickle(self):
3594 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3595 sig = inspect.signature(foo)
3596 ba = sig.bind(20, 30, z={})
3597
3598 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3599 with self.subTest(pickle_ver=ver):
3600 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3601 self.assertEqual(ba, ba_pickled)
3602
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003603 def test_signature_bound_arguments_repr(self):
3604 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3605 sig = inspect.signature(foo)
3606 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003607 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003608
Yury Selivanovb907a512015-05-16 13:45:09 -04003609 def test_signature_bound_arguments_apply_defaults(self):
3610 def foo(a, b=1, *args, c:1={}, **kw): pass
3611 sig = inspect.signature(foo)
3612
3613 ba = sig.bind(20)
3614 ba.apply_defaults()
3615 self.assertEqual(
3616 list(ba.arguments.items()),
3617 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3618
3619 # Make sure that we preserve the order:
3620 # i.e. 'c' should be *before* 'kw'.
3621 ba = sig.bind(10, 20, 30, d=1)
3622 ba.apply_defaults()
3623 self.assertEqual(
3624 list(ba.arguments.items()),
3625 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3626
3627 # Make sure that BoundArguments produced by bind_partial()
3628 # are supported.
3629 def foo(a, b): pass
3630 sig = inspect.signature(foo)
3631 ba = sig.bind_partial(20)
3632 ba.apply_defaults()
3633 self.assertEqual(
3634 list(ba.arguments.items()),
3635 [('a', 20)])
3636
3637 # Test no args
3638 def foo(): pass
3639 sig = inspect.signature(foo)
3640 ba = sig.bind()
3641 ba.apply_defaults()
3642 self.assertEqual(list(ba.arguments.items()), [])
3643
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003644 # Make sure a no-args binding still acquires proper defaults.
3645 def foo(a='spam'): pass
3646 sig = inspect.signature(foo)
3647 ba = sig.bind()
3648 ba.apply_defaults()
3649 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3650
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003651
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003652class TestSignaturePrivateHelpers(unittest.TestCase):
3653 def test_signature_get_bound_param(self):
3654 getter = inspect._signature_get_bound_param
3655
3656 self.assertEqual(getter('($self)'), 'self')
3657 self.assertEqual(getter('($self, obj)'), 'self')
3658 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3659
Larry Hastings2623c8c2014-02-08 22:15:29 -08003660 def _strip_non_python_syntax(self, input,
3661 clean_signature, self_parameter, last_positional_only):
3662 computed_clean_signature, \
3663 computed_self_parameter, \
3664 computed_last_positional_only = \
3665 inspect._signature_strip_non_python_syntax(input)
3666 self.assertEqual(computed_clean_signature, clean_signature)
3667 self.assertEqual(computed_self_parameter, self_parameter)
3668 self.assertEqual(computed_last_positional_only, last_positional_only)
3669
3670 def test_signature_strip_non_python_syntax(self):
3671 self._strip_non_python_syntax(
3672 "($module, /, path, mode, *, dir_fd=None, " +
3673 "effective_ids=False,\n follow_symlinks=True)",
3674 "(module, path, mode, *, dir_fd=None, " +
3675 "effective_ids=False, follow_symlinks=True)",
3676 0,
3677 0)
3678
3679 self._strip_non_python_syntax(
3680 "($module, word, salt, /)",
3681 "(module, word, salt)",
3682 0,
3683 2)
3684
3685 self._strip_non_python_syntax(
3686 "(x, y=None, z=None, /)",
3687 "(x, y=None, z=None)",
3688 None,
3689 2)
3690
3691 self._strip_non_python_syntax(
3692 "(x, y=None, z=None)",
3693 "(x, y=None, z=None)",
3694 None,
3695 None)
3696
3697 self._strip_non_python_syntax(
3698 "(x,\n y=None,\n z = None )",
3699 "(x, y=None, z=None)",
3700 None,
3701 None)
3702
3703 self._strip_non_python_syntax(
3704 "",
3705 "",
3706 None,
3707 None)
3708
3709 self._strip_non_python_syntax(
3710 None,
3711 None,
3712 None,
3713 None)
3714
Nick Coghlan9c680b02015-04-13 12:54:54 -04003715class TestSignatureDefinitions(unittest.TestCase):
3716 # This test case provides a home for checking that particular APIs
3717 # have signatures available for introspection
3718
3719 @cpython_only
3720 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3721 "Signature information for builtins requires docstrings")
3722 def test_builtins_have_signatures(self):
3723 # This checks all builtin callables in CPython have signatures
3724 # A few have signatures Signature can't yet handle, so we skip those
3725 # since they will have to wait until PEP 457 adds the required
3726 # introspection support to the inspect module
3727 # Some others also haven't been converted yet for various other
3728 # reasons, so we also skip those for the time being, but design
3729 # the test to fail in order to indicate when it needs to be
3730 # updated.
3731 no_signature = set()
3732 # These need PEP 457 groups
3733 needs_groups = {"range", "slice", "dir", "getattr",
3734 "next", "iter", "vars"}
3735 no_signature |= needs_groups
3736 # These need PEP 457 groups or a signature change to accept None
3737 needs_semantic_update = {"round"}
3738 no_signature |= needs_semantic_update
3739 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003740 needs_varargs = {"breakpoint", "min", "max", "print",
3741 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003742 no_signature |= needs_varargs
3743 # These simply weren't covered in the initial AC conversion
3744 # for builtin callables
3745 not_converted_yet = {"open", "__import__"}
3746 no_signature |= not_converted_yet
3747 # These builtin types are expected to provide introspection info
3748 types_with_signatures = set()
3749 # Check the signatures we expect to be there
3750 ns = vars(builtins)
3751 for name, obj in sorted(ns.items()):
3752 if not callable(obj):
3753 continue
3754 # The builtin types haven't been converted to AC yet
3755 if isinstance(obj, type) and (name not in types_with_signatures):
3756 # Note that this also skips all the exception types
3757 no_signature.add(name)
3758 if (name in no_signature):
3759 # Not yet converted
3760 continue
3761 with self.subTest(builtin=name):
3762 self.assertIsNotNone(inspect.signature(obj))
3763 # Check callables that haven't been converted don't claim a signature
3764 # This ensures this test will start failing as more signatures are
3765 # added, so the affected items can be moved into the scope of the
3766 # regression test above
3767 for name in no_signature:
3768 with self.subTest(builtin=name):
3769 self.assertIsNone(obj.__text_signature__)
3770
Serhiy Storchakad53cf992019-05-06 22:40:27 +03003771 def test_python_function_override_signature(self):
3772 def func(*args, **kwargs):
3773 pass
3774 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
3775 sig = inspect.signature(func)
3776 self.assertIsNotNone(sig)
3777 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
3778 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
3779 sig = inspect.signature(func)
3780 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
3781
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003782
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003783class NTimesUnwrappable:
3784 def __init__(self, n):
3785 self.n = n
3786 self._next = None
3787
3788 @property
3789 def __wrapped__(self):
3790 if self.n <= 0:
3791 raise Exception("Unwrapped too many times")
3792 if self._next is None:
3793 self._next = NTimesUnwrappable(self.n - 1)
3794 return self._next
3795
Nick Coghlane8c45d62013-07-28 20:00:01 +10003796class TestUnwrap(unittest.TestCase):
3797
3798 def test_unwrap_one(self):
3799 def func(a, b):
3800 return a + b
3801 wrapper = functools.lru_cache(maxsize=20)(func)
3802 self.assertIs(inspect.unwrap(wrapper), func)
3803
3804 def test_unwrap_several(self):
3805 def func(a, b):
3806 return a + b
3807 wrapper = func
3808 for __ in range(10):
3809 @functools.wraps(wrapper)
3810 def wrapper():
3811 pass
3812 self.assertIsNot(wrapper.__wrapped__, func)
3813 self.assertIs(inspect.unwrap(wrapper), func)
3814
3815 def test_stop(self):
3816 def func1(a, b):
3817 return a + b
3818 @functools.wraps(func1)
3819 def func2():
3820 pass
3821 @functools.wraps(func2)
3822 def wrapper():
3823 pass
3824 func2.stop_here = 1
3825 unwrapped = inspect.unwrap(wrapper,
3826 stop=(lambda f: hasattr(f, "stop_here")))
3827 self.assertIs(unwrapped, func2)
3828
3829 def test_cycle(self):
3830 def func1(): pass
3831 func1.__wrapped__ = func1
3832 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3833 inspect.unwrap(func1)
3834
3835 def func2(): pass
3836 func2.__wrapped__ = func1
3837 func1.__wrapped__ = func2
3838 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3839 inspect.unwrap(func1)
3840 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3841 inspect.unwrap(func2)
3842
3843 def test_unhashable(self):
3844 def func(): pass
3845 func.__wrapped__ = None
3846 class C:
3847 __hash__ = None
3848 __wrapped__ = func
3849 self.assertIsNone(inspect.unwrap(C()))
3850
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003851 def test_recursion_limit(self):
3852 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3853 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3854 inspect.unwrap(obj)
3855
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003856class TestMain(unittest.TestCase):
3857 def test_only_source(self):
3858 module = importlib.import_module('unittest')
3859 rc, out, err = assert_python_ok('-m', 'inspect',
3860 'unittest')
3861 lines = out.decode().splitlines()
3862 # ignore the final newline
3863 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3864 self.assertEqual(err, b'')
3865
Yury Selivanov42407ab2014-06-23 10:23:50 -07003866 def test_custom_getattr(self):
3867 def foo():
3868 pass
3869 foo.__signature__ = 42
3870 with self.assertRaises(TypeError):
3871 inspect.signature(foo)
3872
Brett Cannon634a8fc2013-10-02 10:25:42 -04003873 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003874 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003875 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003876 rc, out, err = assert_python_ok('-m', 'inspect',
3877 'concurrent.futures:ThreadPoolExecutor')
3878 lines = out.decode().splitlines()
3879 # ignore the final newline
3880 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003881 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003882 self.assertEqual(err, b'')
3883
3884 def test_builtins(self):
3885 module = importlib.import_module('unittest')
3886 _, out, err = assert_python_failure('-m', 'inspect',
3887 'sys')
3888 lines = err.decode().splitlines()
3889 self.assertEqual(lines, ["Can't get info for builtin modules."])
3890
3891 def test_details(self):
3892 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003893 args = support.optim_args_from_interpreter_flags()
3894 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003895 'unittest', '--details')
3896 output = out.decode()
3897 # Just a quick sanity check on the output
3898 self.assertIn(module.__name__, output)
3899 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003900 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003901 self.assertEqual(err, b'')
3902
3903
Yury Selivanovef1e7502014-12-08 16:05:34 -05003904class TestReload(unittest.TestCase):
3905
3906 src_before = textwrap.dedent("""\
3907def foo():
3908 print("Bla")
3909 """)
3910
3911 src_after = textwrap.dedent("""\
3912def foo():
3913 print("Oh no!")
3914 """)
3915
3916 def assertInspectEqual(self, path, source):
3917 inspected_src = inspect.getsource(source)
3918 with open(path) as src:
3919 self.assertEqual(
3920 src.read().splitlines(True),
3921 inspected_src.splitlines(True)
3922 )
3923
3924 def test_getsource_reload(self):
3925 # see issue 1218234
3926 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3927 module = importlib.import_module(name)
3928 self.assertInspectEqual(path, module)
3929 with open(path, 'w') as src:
3930 src.write(self.src_after)
3931 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003932
Nick Coghlane8c45d62013-07-28 20:00:01 +10003933
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003934def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003935 run_unittest(
3936 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3937 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3938 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003939 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003940 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003941 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04003942 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003943 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07003944 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00003945 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003946
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003947if __name__ == "__main__":
3948 test_main()