blob: c54cdb23c242ffcaa323292902138ab2af09f35e [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):
753 with self.assertWarns(DeprecationWarning):
754 args, varargs, varkw, defaults = inspect.getargspec(routine)
755 self.assertEqual(args, args_e)
756 self.assertEqual(varargs, varargs_e)
757 self.assertEqual(varkw, varkw_e)
758 self.assertEqual(defaults, defaults_e)
759 if formatted is not None:
Matthias Bussonnier46c5cd02018-06-11 22:08:16 +0200760 with self.assertWarns(DeprecationWarning):
761 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
762 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500763
Christian Heimes3795b532007-11-08 13:48:53 +0000764 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
765 varkw_e=None, defaults_e=None,
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100766 posonlyargs_e=[], kwonlyargs_e=[],
767 kwonlydefaults_e=None,
Christian Heimes3795b532007-11-08 13:48:53 +0000768 ann_e={}, formatted=None):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100769 with self.assertWarns(DeprecationWarning):
770 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
771 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000772 self.assertEqual(args, args_e)
773 self.assertEqual(varargs, varargs_e)
774 self.assertEqual(varkw, varkw_e)
775 self.assertEqual(defaults, defaults_e)
776 self.assertEqual(kwonlyargs, kwonlyargs_e)
777 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
778 self.assertEqual(ann, ann_e)
779 if formatted is not None:
Matthias Bussonnier46c5cd02018-06-11 22:08:16 +0200780 with self.assertWarns(DeprecationWarning):
781 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100782 kwonlyargs, kwonlydefaults, ann),
Christian Heimes3795b532007-11-08 13:48:53 +0000783 formatted)
784
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500785 def test_getargspec(self):
786 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
787
Pablo Galindod5d2b452019-04-30 02:01:14 +0100788 self.assertArgSpecEquals(mod.spam,
789 ['a', 'b', 'c', 'd', 'e', 'f'],
790 'g', 'h', (3, 4, 5),
791 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500792
793 self.assertRaises(ValueError, self.assertArgSpecEquals,
794 mod2.keyworded, [])
795
796 self.assertRaises(ValueError, self.assertArgSpecEquals,
797 mod2.annotated, [])
798 self.assertRaises(ValueError, self.assertArgSpecEquals,
799 mod2.keyword_only_arg, [])
800
801
Christian Heimes3795b532007-11-08 13:48:53 +0000802 def test_getfullargspec(self):
803 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
804 kwonlyargs_e=['arg2'],
805 kwonlydefaults_e={'arg2':1},
806 formatted='(*arg1, arg2=1)')
807
808 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000809 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000810 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000811 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
812 kwonlyargs_e=['arg'],
813 formatted='(*, arg)')
814
Pablo Galindod5d2b452019-04-30 02:01:14 +0100815 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100816 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100817 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100818
819 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100820 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100821 varargs_e='args',
822 varkw_e='kwargs',
823 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100824 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100825
Pablo Galindod5d2b452019-04-30 02:01:14 +0100826 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100827 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100828 kwonlyargs_e=['e', 'f'],
829 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100830 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100831
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500832 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500833 # Issue 20684: low level introspection API must ignore __wrapped__
834 @functools.wraps(mod.spam)
835 def ham(x, y):
836 pass
837 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500838 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500839 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
840 self.assertFullArgSpecEquals(functools.partial(ham),
841 ['x', 'y'], formatted='(x, y)')
842 # Other variants
843 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500844 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
845 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500846 class C:
847 @functools.wraps(mod.spam)
848 def ham(self, x, y):
849 pass
850 pham = functools.partialmethod(ham)
851 @functools.wraps(mod.spam)
852 def __call__(self, x, y):
853 pass
854 check_method(C())
855 check_method(C.ham)
856 check_method(C().ham)
857 check_method(C.pham)
858 check_method(C().pham)
859
860 class C_new:
861 @functools.wraps(mod.spam)
862 def __new__(self, x, y):
863 pass
864 check_method(C_new)
865
866 class C_init:
867 @functools.wraps(mod.spam)
868 def __init__(self, x, y):
869 pass
870 check_method(C_init)
871
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500872 def test_getfullargspec_signature_attr(self):
873 def test():
874 pass
875 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
876 test.__signature__ = inspect.Signature(parameters=(spam_param,))
877
Pablo Galindod5d2b452019-04-30 02:01:14 +0100878 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500879
Yury Selivanov4cb93912014-01-29 11:54:12 -0500880 def test_getfullargspec_signature_annos(self):
881 def test(a:'spam') -> 'ham': pass
Pablo Galindod5d2b452019-04-30 02:01:14 +0100882 with self.assertWarns(DeprecationWarning):
883 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500884 self.assertEqual(test.__annotations__, spec.annotations)
885
886 def test(): pass
Pablo Galindod5d2b452019-04-30 02:01:14 +0100887 with self.assertWarns(DeprecationWarning):
888 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500889 self.assertEqual(test.__annotations__, spec.annotations)
890
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500891 @unittest.skipIf(MISSING_C_DOCSTRINGS,
892 "Signature information for builtins requires docstrings")
893 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100894 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
895 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500896
Pablo Galindod5d2b452019-04-30 02:01:14 +0100897 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
898 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500899
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500900 self.assertFullArgSpecEquals(
901 os.stat,
902 args_e=['path'],
903 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
904 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
905 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
906
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200907 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500908 @unittest.skipIf(MISSING_C_DOCSTRINGS,
909 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800910 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200911 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500912 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindod5d2b452019-04-30 02:01:14 +0100913 with self.assertWarns(DeprecationWarning):
914 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500915 self.assertEqual(spec.defaults[0], 'avocado')
916
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200917 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500918 @unittest.skipIf(MISSING_C_DOCSTRINGS,
919 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800920 def test_getfullargspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200921 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500922 builtin = _testcapi.docstring_no_signature
Pablo Galindod5d2b452019-04-30 02:01:14 +0100923 with self.assertWarns(DeprecationWarning):
924 with self.assertRaises(TypeError):
925 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000926
larryhastingsf36ba122018-01-28 11:13:09 -0800927 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
928 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindod5d2b452019-04-30 02:01:14 +0100929 with self.assertWarns(DeprecationWarning):
930 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800931 l = list(signature.kwonlyargs)
932 sorted_l = sorted(l)
933 self.assertTrue(l)
934 self.assertEqual(l, sorted_l)
Pablo Galindod5d2b452019-04-30 02:01:14 +0100935 with self.assertWarns(DeprecationWarning):
936 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800937 l = list(signature.kwonlyargs)
938 self.assertEqual(l, unsorted_keyword_only_parameters)
939
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500940 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000941 class A(object):
942 def m(self):
943 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500944 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000945
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000946 def test_classify_newstyle(self):
947 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000948
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000949 def s(): pass
950 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000951
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000952 def c(cls): pass
953 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000954
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000955 def getp(self): pass
956 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000957
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000958 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000959
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000960 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000961
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000962 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000963
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100964 dd = _BrokenDataDescriptor()
965 md = _BrokenMethodDescriptor()
966
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000967 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500968
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +0200969 self.assertIn(('__new__', 'static method', object), attrs,
970 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500971 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
972
Benjamin Peterson577473f2010-01-19 00:09:57 +0000973 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
974 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
975 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000976 self.assertIn(('m', 'method', A), attrs,
977 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000978 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
979 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100980 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
981 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000982
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000983 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000984
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000985 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000986
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000987 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000988 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
989 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
990 self.assertIn(('p', 'property', A), attrs, 'missing property')
991 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
992 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
993 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100994 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
995 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000996
997
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000998 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000999
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001000 def m(self): pass
1001 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001002
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001003 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001004 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1005 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1006 self.assertIn(('p', 'property', A), attrs, 'missing property')
1007 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
1008 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1009 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001010 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1011 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001012
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001013 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001014
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001015 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001016
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001017 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001018 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1019 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1020 self.assertIn(('p', 'property', A), attrs, 'missing property')
1021 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1022 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1023 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001024 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1025 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1026
1027 def test_classify_builtin_types(self):
1028 # Simple sanity check that all built-in types can have their
1029 # attributes classified.
1030 for name in dir(__builtins__):
1031 builtin = getattr(__builtins__, name)
1032 if isinstance(builtin, type):
1033 inspect.classify_class_attrs(builtin)
1034
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001035 attrs = attrs_wo_objs(bool)
1036 self.assertIn(('__new__', 'static method', bool), attrs,
1037 'missing __new__')
1038 self.assertIn(('from_bytes', 'class method', int), attrs,
1039 'missing class method')
1040 self.assertIn(('to_bytes', 'method', int), attrs,
1041 'missing plain method')
1042 self.assertIn(('__add__', 'method', int), attrs,
1043 'missing plain method')
1044 self.assertIn(('__and__', 'method', bool), attrs,
1045 'missing plain method')
1046
Ethan Furman63c141c2013-10-18 00:27:39 -07001047 def test_classify_DynamicClassAttribute(self):
1048 class Meta(type):
1049 def __getattr__(self, name):
1050 if name == 'ham':
1051 return 'spam'
1052 return super().__getattr__(name)
1053 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001054 @types.DynamicClassAttribute
1055 def ham(self):
1056 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001057 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1058 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001059 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001060 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1061
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001062 def test_classify_overrides_bool(self):
1063 class NoBool(object):
1064 def __eq__(self, other):
1065 return NoBool()
1066
1067 def __bool__(self):
1068 raise NotImplementedError(
1069 "This object does not specify a boolean value")
1070
1071 class HasNB(object):
1072 dd = NoBool()
1073
1074 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1075 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1076
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001077 def test_classify_metaclass_class_attribute(self):
1078 class Meta(type):
1079 fish = 'slap'
1080 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001081 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001082 class Class(metaclass=Meta):
1083 pass
1084 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1085 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1086
Ethan Furman63c141c2013-10-18 00:27:39 -07001087 def test_classify_VirtualAttribute(self):
1088 class Meta(type):
1089 def __dir__(cls):
1090 return ['__class__', '__module__', '__name__', 'BOOM']
1091 def __getattr__(self, name):
1092 if name =='BOOM':
1093 return 42
1094 return super().__getattr(name)
1095 class Class(metaclass=Meta):
1096 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001097 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001098 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1099
1100 def test_classify_VirtualAttribute_multi_classes(self):
1101 class Meta1(type):
1102 def __dir__(cls):
1103 return ['__class__', '__module__', '__name__', 'one']
1104 def __getattr__(self, name):
1105 if name =='one':
1106 return 1
1107 return super().__getattr__(name)
1108 class Meta2(type):
1109 def __dir__(cls):
1110 return ['__class__', '__module__', '__name__', 'two']
1111 def __getattr__(self, name):
1112 if name =='two':
1113 return 2
1114 return super().__getattr__(name)
1115 class Meta3(Meta1, Meta2):
1116 def __dir__(cls):
1117 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1118 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1119 def __getattr__(self, name):
1120 if name =='three':
1121 return 3
1122 return super().__getattr__(name)
1123 class Class1(metaclass=Meta1):
1124 pass
1125 class Class2(Class1, metaclass=Meta3):
1126 pass
1127
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001128 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1129 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1130 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001131 cca = inspect.classify_class_attrs(Class2)
1132 for sf in (should_find1, should_find2, should_find3):
1133 self.assertIn(sf, cca)
1134
1135 def test_classify_class_attrs_with_buggy_dir(self):
1136 class M(type):
1137 def __dir__(cls):
1138 return ['__class__', '__name__', 'missing']
1139 class C(metaclass=M):
1140 pass
1141 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1142 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001143
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001144 def test_getmembers_descriptors(self):
1145 class A(object):
1146 dd = _BrokenDataDescriptor()
1147 md = _BrokenMethodDescriptor()
1148
1149 def pred_wrapper(pred):
1150 # A quick'n'dirty way to discard standard attributes of new-style
1151 # classes.
1152 class Empty(object):
1153 pass
1154 def wrapped(x):
1155 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1156 return False
1157 return pred(x)
1158 return wrapped
1159
1160 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1161 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1162
1163 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1164 [('md', A.__dict__['md'])])
1165 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1166 [('dd', A.__dict__['dd'])])
1167
1168 class B(A):
1169 pass
1170
1171 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1172 [('md', A.__dict__['md'])])
1173 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1174 [('dd', A.__dict__['dd'])])
1175
Antoine Pitrou0c603812012-01-18 17:40:18 +01001176 def test_getmembers_method(self):
1177 class B:
1178 def f(self):
1179 pass
1180
1181 self.assertIn(('f', B.f), inspect.getmembers(B))
1182 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1183 b = B()
1184 self.assertIn(('f', b.f), inspect.getmembers(b))
1185 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1186
Ethan Furmane03ea372013-09-25 07:14:41 -07001187 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001188 class M(type):
1189 def __getattr__(cls, name):
1190 if name == 'eggs':
1191 return 'scrambled'
1192 return super().__getattr__(name)
1193 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001194 @types.DynamicClassAttribute
1195 def eggs(self):
1196 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001197 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1198 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1199
1200 def test_getmembers_with_buggy_dir(self):
1201 class M(type):
1202 def __dir__(cls):
1203 return ['__class__', '__name__', 'missing']
1204 class C(metaclass=M):
1205 pass
1206 attrs = [a[0] for a in inspect.getmembers(C)]
1207 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001208
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001209class TestIsDataDescriptor(unittest.TestCase):
1210
1211 def test_custom_descriptors(self):
1212 class NonDataDescriptor:
1213 def __get__(self, value, type=None): pass
1214 class DataDescriptor0:
1215 def __set__(self, name, value): pass
1216 class DataDescriptor1:
1217 def __delete__(self, name): pass
1218 class DataDescriptor2:
1219 __set__ = None
1220 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1221 'class with only __get__ not a data descriptor')
1222 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1223 'class with __set__ is a data descriptor')
1224 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1225 'class with __delete__ is a data descriptor')
1226 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1227 'class with __set__ = None is a data descriptor')
1228
1229 def test_slot(self):
1230 class Slotted:
1231 __slots__ = 'foo',
1232 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1233 'a slot is a data descriptor')
1234
1235 def test_property(self):
1236 class Propertied:
1237 @property
1238 def a_property(self):
1239 pass
1240 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1241 'a property is a data descriptor')
1242
1243 def test_functions(self):
1244 class Test(object):
1245 def instance_method(self): pass
1246 @classmethod
1247 def class_method(cls): pass
1248 @staticmethod
1249 def static_method(): pass
1250 def function():
1251 pass
1252 a_lambda = lambda: None
1253 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1254 'a instance method is not a data descriptor')
1255 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1256 'a class method is not a data descriptor')
1257 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1258 'a static method is not a data descriptor')
1259 self.assertFalse(inspect.isdatadescriptor(function),
1260 'a function is not a data descriptor')
1261 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1262 'a lambda is not a data descriptor')
1263
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001264
Nick Coghlan2f92e542012-06-23 19:39:55 +10001265_global_ref = object()
1266class TestGetClosureVars(unittest.TestCase):
1267
1268 def test_name_resolution(self):
1269 # Basic test of the 4 different resolution mechanisms
1270 def f(nonlocal_ref):
1271 def g(local_ref):
1272 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1273 return g
1274 _arg = object()
1275 nonlocal_vars = {"nonlocal_ref": _arg}
1276 global_vars = {"_global_ref": _global_ref}
1277 builtin_vars = {"print": print}
1278 unbound_names = {"unbound_ref"}
1279 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1280 builtin_vars, unbound_names)
1281 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1282
1283 def test_generator_closure(self):
1284 def f(nonlocal_ref):
1285 def g(local_ref):
1286 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1287 yield
1288 return g
1289 _arg = object()
1290 nonlocal_vars = {"nonlocal_ref": _arg}
1291 global_vars = {"_global_ref": _global_ref}
1292 builtin_vars = {"print": print}
1293 unbound_names = {"unbound_ref"}
1294 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1295 builtin_vars, unbound_names)
1296 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1297
1298 def test_method_closure(self):
1299 class C:
1300 def f(self, nonlocal_ref):
1301 def g(local_ref):
1302 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1303 return g
1304 _arg = object()
1305 nonlocal_vars = {"nonlocal_ref": _arg}
1306 global_vars = {"_global_ref": _global_ref}
1307 builtin_vars = {"print": print}
1308 unbound_names = {"unbound_ref"}
1309 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1310 builtin_vars, unbound_names)
1311 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1312
1313 def test_nonlocal_vars(self):
1314 # More complex tests of nonlocal resolution
1315 def _nonlocal_vars(f):
1316 return inspect.getclosurevars(f).nonlocals
1317
1318 def make_adder(x):
1319 def add(y):
1320 return x + y
1321 return add
1322
1323 def curry(func, arg1):
1324 return lambda arg2: func(arg1, arg2)
1325
1326 def less_than(a, b):
1327 return a < b
1328
1329 # The infamous Y combinator.
1330 def Y(le):
1331 def g(f):
1332 return le(lambda x: f(f)(x))
1333 Y.g_ref = g
1334 return g(g)
1335
1336 def check_y_combinator(func):
1337 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1338
1339 inc = make_adder(1)
1340 add_two = make_adder(2)
1341 greater_than_five = curry(less_than, 5)
1342
1343 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1344 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1345 self.assertEqual(_nonlocal_vars(greater_than_five),
1346 {'arg1': 5, 'func': less_than})
1347 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1348 {'x': 3})
1349 Y(check_y_combinator)
1350
1351 def test_getclosurevars_empty(self):
1352 def foo(): pass
1353 _empty = inspect.ClosureVars({}, {}, {}, set())
1354 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1355 self.assertEqual(inspect.getclosurevars(foo), _empty)
1356
1357 def test_getclosurevars_error(self):
1358 class T: pass
1359 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1360 self.assertRaises(TypeError, inspect.getclosurevars, list)
1361 self.assertRaises(TypeError, inspect.getclosurevars, {})
1362
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001363 def _private_globals(self):
1364 code = """def f(): print(path)"""
1365 ns = {}
1366 exec(code, ns)
1367 return ns["f"], ns
1368
1369 def test_builtins_fallback(self):
1370 f, ns = self._private_globals()
1371 ns.pop("__builtins__", None)
1372 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1373 self.assertEqual(inspect.getclosurevars(f), expected)
1374
1375 def test_builtins_as_dict(self):
1376 f, ns = self._private_globals()
1377 ns["__builtins__"] = {"path":1}
1378 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1379 self.assertEqual(inspect.getclosurevars(f), expected)
1380
1381 def test_builtins_as_module(self):
1382 f, ns = self._private_globals()
1383 ns["__builtins__"] = os
1384 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1385 self.assertEqual(inspect.getclosurevars(f), expected)
1386
Nick Coghlan2f92e542012-06-23 19:39:55 +10001387
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001388class TestGetcallargsFunctions(unittest.TestCase):
1389
1390 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1391 locs = dict(locs or {}, func=func)
1392 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindod5d2b452019-04-30 02:01:14 +01001393 with self.assertWarns(DeprecationWarning):
1394 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1395 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001396 self.assertEqual(r1, r2)
1397
1398 def assertEqualException(self, func, call_param_string, locs=None):
1399 locs = dict(locs or {}, func=func)
1400 try:
1401 eval('func(%s)' % call_param_string, None, locs)
1402 except Exception as e:
1403 ex1 = e
1404 else:
1405 self.fail('Exception not raised')
1406 try:
Pablo Galindod5d2b452019-04-30 02:01:14 +01001407 with self.assertWarns(DeprecationWarning):
1408 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1409 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001410 except Exception as e:
1411 ex2 = e
1412 else:
1413 self.fail('Exception not raised')
1414 self.assertIs(type(ex1), type(ex2))
1415 self.assertEqual(str(ex1), str(ex2))
1416 del ex1, ex2
1417
1418 def makeCallable(self, signature):
1419 """Create a function that returns its locals()"""
1420 code = "lambda %s: locals()"
1421 return eval(code % signature)
1422
1423 def test_plain(self):
1424 f = self.makeCallable('a, b=1')
1425 self.assertEqualCallArgs(f, '2')
1426 self.assertEqualCallArgs(f, '2, 3')
1427 self.assertEqualCallArgs(f, 'a=2')
1428 self.assertEqualCallArgs(f, 'b=3, a=2')
1429 self.assertEqualCallArgs(f, '2, b=3')
1430 # expand *iterable / **mapping
1431 self.assertEqualCallArgs(f, '*(2,)')
1432 self.assertEqualCallArgs(f, '*[2]')
1433 self.assertEqualCallArgs(f, '*(2, 3)')
1434 self.assertEqualCallArgs(f, '*[2, 3]')
1435 self.assertEqualCallArgs(f, '**{"a":2}')
1436 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1437 self.assertEqualCallArgs(f, '2, **{"b":3}')
1438 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1439 # expand UserList / UserDict
1440 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1441 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1442 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1443 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1444 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1445
1446 def test_varargs(self):
1447 f = self.makeCallable('a, b=1, *c')
1448 self.assertEqualCallArgs(f, '2')
1449 self.assertEqualCallArgs(f, '2, 3')
1450 self.assertEqualCallArgs(f, '2, 3, 4')
1451 self.assertEqualCallArgs(f, '*(2,3,4)')
1452 self.assertEqualCallArgs(f, '2, *[3,4]')
1453 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1454
1455 def test_varkw(self):
1456 f = self.makeCallable('a, b=1, **c')
1457 self.assertEqualCallArgs(f, 'a=2')
1458 self.assertEqualCallArgs(f, '2, b=3, c=4')
1459 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1460 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1461 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1462 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1463 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1464 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1465 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1466
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001467 def test_varkw_only(self):
1468 # issue11256:
1469 f = self.makeCallable('**c')
1470 self.assertEqualCallArgs(f, '')
1471 self.assertEqualCallArgs(f, 'a=1')
1472 self.assertEqualCallArgs(f, 'a=1, b=2')
1473 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1474 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1475 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1476
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001477 def test_keyword_only(self):
1478 f = self.makeCallable('a=3, *, c, d=2')
1479 self.assertEqualCallArgs(f, 'c=3')
1480 self.assertEqualCallArgs(f, 'c=3, a=3')
1481 self.assertEqualCallArgs(f, 'a=2, c=4')
1482 self.assertEqualCallArgs(f, '4, c=4')
1483 self.assertEqualException(f, '')
1484 self.assertEqualException(f, '3')
1485 self.assertEqualException(f, 'a=3')
1486 self.assertEqualException(f, 'd=4')
1487
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001488 f = self.makeCallable('*, c, d=2')
1489 self.assertEqualCallArgs(f, 'c=3')
1490 self.assertEqualCallArgs(f, 'c=3, d=4')
1491 self.assertEqualCallArgs(f, 'd=4, c=3')
1492
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001493 def test_multiple_features(self):
1494 f = self.makeCallable('a, b=2, *f, **g')
1495 self.assertEqualCallArgs(f, '2, 3, 7')
1496 self.assertEqualCallArgs(f, '2, 3, x=8')
1497 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1498 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1499 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1500 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1501 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1502 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1503 '(4,[5,6])]), **collections.UserDict('
1504 'y=9, z=10)')
1505
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001506 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1507 self.assertEqualCallArgs(f, '2, 3, x=8')
1508 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1509 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1510 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1511 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1512 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1513 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1514 '(4,[5,6])]), q=0, **collections.UserDict('
1515 'y=9, z=10)')
1516
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001517 def test_errors(self):
1518 f0 = self.makeCallable('')
1519 f1 = self.makeCallable('a, b')
1520 f2 = self.makeCallable('a, b=1')
1521 # f0 takes no arguments
1522 self.assertEqualException(f0, '1')
1523 self.assertEqualException(f0, 'x=1')
1524 self.assertEqualException(f0, '1,x=1')
1525 # f1 takes exactly 2 arguments
1526 self.assertEqualException(f1, '')
1527 self.assertEqualException(f1, '1')
1528 self.assertEqualException(f1, 'a=2')
1529 self.assertEqualException(f1, 'b=3')
1530 # f2 takes at least 1 argument
1531 self.assertEqualException(f2, '')
1532 self.assertEqualException(f2, 'b=3')
1533 for f in f1, f2:
1534 # f1/f2 takes exactly/at most 2 arguments
1535 self.assertEqualException(f, '2, 3, 4')
1536 self.assertEqualException(f, '1, 2, 3, a=1')
1537 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001538 # XXX: success of this one depends on dict order
1539 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001540 # f got an unexpected keyword argument
1541 self.assertEqualException(f, 'c=2')
1542 self.assertEqualException(f, '2, c=3')
1543 self.assertEqualException(f, '2, 3, c=4')
1544 self.assertEqualException(f, '2, c=4, b=3')
1545 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1546 # f got multiple values for keyword argument
1547 self.assertEqualException(f, '1, a=2')
1548 self.assertEqualException(f, '1, **{"a":2}')
1549 self.assertEqualException(f, '1, 2, b=3')
1550 # XXX: Python inconsistency
1551 # - for functions and bound methods: unexpected keyword 'c'
1552 # - for unbound methods: multiple values for keyword 'a'
1553 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001554 # issue11256:
1555 f3 = self.makeCallable('**c')
1556 self.assertEqualException(f3, '1, 2')
1557 self.assertEqualException(f3, '1, 2, a=1, b=2')
1558 f4 = self.makeCallable('*, a, b=0')
1559 self.assertEqualException(f3, '1, 2')
1560 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001561
Yury Selivanov875df202014-03-27 18:23:03 -04001562 # issue #20816: getcallargs() fails to iterate over non-existent
1563 # kwonlydefaults and raises a wrong TypeError
1564 def f5(*, a): pass
1565 with self.assertRaisesRegex(TypeError,
1566 'missing 1 required keyword-only'):
Pablo Galindod5d2b452019-04-30 02:01:14 +01001567 with self.assertWarns(DeprecationWarning):
1568 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001569
1570
Yury Selivanovdccfa132014-03-27 18:42:52 -04001571 # issue20817:
1572 def f6(a, b, c):
1573 pass
1574 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindod5d2b452019-04-30 02:01:14 +01001575 with self.assertWarns(DeprecationWarning):
1576 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001577
Dong-hee Naa9cab432018-05-30 00:04:08 +09001578 # bpo-33197
1579 with self.assertRaisesRegex(ValueError,
1580 'variadic keyword parameters cannot'
1581 ' have default values'):
1582 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1583 default=42)
1584 with self.assertRaisesRegex(ValueError,
1585 "value 5 is not a valid Parameter.kind"):
1586 inspect.Parameter("bar", kind=5, default=42)
1587
1588 with self.assertRaisesRegex(TypeError,
1589 'name must be a str, not a int'):
1590 inspect.Parameter(123, kind=4)
1591
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001592class TestGetcallargsMethods(TestGetcallargsFunctions):
1593
1594 def setUp(self):
1595 class Foo(object):
1596 pass
1597 self.cls = Foo
1598 self.inst = Foo()
1599
1600 def makeCallable(self, signature):
1601 assert 'self' not in signature
1602 mk = super(TestGetcallargsMethods, self).makeCallable
1603 self.cls.method = mk('self, ' + signature)
1604 return self.inst.method
1605
1606class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1607
1608 def makeCallable(self, signature):
1609 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1610 return self.cls.method
1611
1612 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1613 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1614 *self._getAssertEqualParams(func, call_params_string, locs))
1615
1616 def assertEqualException(self, func, call_params_string, locs=None):
1617 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1618 *self._getAssertEqualParams(func, call_params_string, locs))
1619
1620 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1621 assert 'inst' not in call_params_string
1622 locs = dict(locs or {}, inst=self.inst)
1623 return (func, 'inst,' + call_params_string, locs)
1624
Michael Foord95fc51d2010-11-20 15:07:30 +00001625
1626class TestGetattrStatic(unittest.TestCase):
1627
1628 def test_basic(self):
1629 class Thing(object):
1630 x = object()
1631
1632 thing = Thing()
1633 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1634 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1635 with self.assertRaises(AttributeError):
1636 inspect.getattr_static(thing, 'y')
1637
1638 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1639
1640 def test_inherited(self):
1641 class Thing(object):
1642 x = object()
1643 class OtherThing(Thing):
1644 pass
1645
1646 something = OtherThing()
1647 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1648
1649 def test_instance_attr(self):
1650 class Thing(object):
1651 x = 2
1652 def __init__(self, x):
1653 self.x = x
1654 thing = Thing(3)
1655 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1656 del thing.x
1657 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1658
1659 def test_property(self):
1660 class Thing(object):
1661 @property
1662 def x(self):
1663 raise AttributeError("I'm pretending not to exist")
1664 thing = Thing()
1665 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1666
Ezio Melotti75cbd732011-04-28 00:59:29 +03001667 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001668 class descriptor(object):
1669 def __get__(*_):
1670 raise AttributeError("I'm pretending not to exist")
1671 desc = descriptor()
1672 class Thing(object):
1673 x = desc
1674 thing = Thing()
1675 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1676
1677 def test_classAttribute(self):
1678 class Thing(object):
1679 x = object()
1680
1681 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1682
Ethan Furmane03ea372013-09-25 07:14:41 -07001683 def test_classVirtualAttribute(self):
1684 class Thing(object):
1685 @types.DynamicClassAttribute
1686 def x(self):
1687 return self._x
1688 _x = object()
1689
1690 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1691
Michael Foord95fc51d2010-11-20 15:07:30 +00001692 def test_inherited_classattribute(self):
1693 class Thing(object):
1694 x = object()
1695 class OtherThing(Thing):
1696 pass
1697
1698 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1699
1700 def test_slots(self):
1701 class Thing(object):
1702 y = 'bar'
1703 __slots__ = ['x']
1704 def __init__(self):
1705 self.x = 'foo'
1706 thing = Thing()
1707 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1708 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1709
1710 del thing.x
1711 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1712
1713 def test_metaclass(self):
1714 class meta(type):
1715 attr = 'foo'
1716 class Thing(object, metaclass=meta):
1717 pass
1718 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1719
1720 class sub(meta):
1721 pass
1722 class OtherThing(object, metaclass=sub):
1723 x = 3
1724 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1725
1726 class OtherOtherThing(OtherThing):
1727 pass
1728 # this test is odd, but it was added as it exposed a bug
1729 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1730
1731 def test_no_dict_no_slots(self):
1732 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1733 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1734
1735 def test_no_dict_no_slots_instance_member(self):
1736 # returns descriptor
1737 with open(__file__) as handle:
1738 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1739
1740 def test_inherited_slots(self):
1741 # returns descriptor
1742 class Thing(object):
1743 __slots__ = ['x']
1744 def __init__(self):
1745 self.x = 'foo'
1746
1747 class OtherThing(Thing):
1748 pass
1749 # it would be nice if this worked...
1750 # we get the descriptor instead of the instance attribute
1751 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1752
1753 def test_descriptor(self):
1754 class descriptor(object):
1755 def __get__(self, instance, owner):
1756 return 3
1757 class Foo(object):
1758 d = descriptor()
1759
1760 foo = Foo()
1761
1762 # for a non data descriptor we return the instance attribute
1763 foo.__dict__['d'] = 1
1764 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1765
Mike53f7a7c2017-12-14 14:04:53 +03001766 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001767 # descriptor
1768 descriptor.__set__ = lambda s, i, v: None
1769 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1770
1771
1772 def test_metaclass_with_descriptor(self):
1773 class descriptor(object):
1774 def __get__(self, instance, owner):
1775 return 3
1776 class meta(type):
1777 d = descriptor()
1778 class Thing(object, metaclass=meta):
1779 pass
1780 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1781
1782
Michael Foordcc7ebb82010-11-20 16:20:16 +00001783 def test_class_as_property(self):
1784 class Base(object):
1785 foo = 3
1786
1787 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001788 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001789 @property
1790 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001791 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001792 return object
1793
Michael Foord35184ed2010-11-20 16:58:30 +00001794 instance = Something()
1795 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1796 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001797 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1798
Michael Foorde5162652010-11-20 16:40:44 +00001799 def test_mro_as_property(self):
1800 class Meta(type):
1801 @property
1802 def __mro__(self):
1803 return (object,)
1804
1805 class Base(object):
1806 foo = 3
1807
1808 class Something(Base, metaclass=Meta):
1809 pass
1810
1811 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1812 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1813
Michael Foorddcebe0f2011-03-15 19:20:44 -04001814 def test_dict_as_property(self):
1815 test = self
1816 test.called = False
1817
1818 class Foo(dict):
1819 a = 3
1820 @property
1821 def __dict__(self):
1822 test.called = True
1823 return {}
1824
1825 foo = Foo()
1826 foo.a = 4
1827 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1828 self.assertFalse(test.called)
1829
1830 def test_custom_object_dict(self):
1831 test = self
1832 test.called = False
1833
1834 class Custom(dict):
1835 def get(self, key, default=None):
1836 test.called = True
1837 super().get(key, default)
1838
1839 class Foo(object):
1840 a = 3
1841 foo = Foo()
1842 foo.__dict__ = Custom()
1843 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1844 self.assertFalse(test.called)
1845
1846 def test_metaclass_dict_as_property(self):
1847 class Meta(type):
1848 @property
1849 def __dict__(self):
1850 self.executed = True
1851
1852 class Thing(metaclass=Meta):
1853 executed = False
1854
1855 def __init__(self):
1856 self.spam = 42
1857
1858 instance = Thing()
1859 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1860 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001861
Michael Foorda51623b2011-12-18 22:01:40 +00001862 def test_module(self):
1863 sentinel = object()
1864 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1865 sentinel)
1866
Michael Foord3ba95f82011-12-22 01:13:37 +00001867 def test_metaclass_with_metaclass_with_dict_as_property(self):
1868 class MetaMeta(type):
1869 @property
1870 def __dict__(self):
1871 self.executed = True
1872 return dict(spam=42)
1873
1874 class Meta(type, metaclass=MetaMeta):
1875 executed = False
1876
1877 class Thing(metaclass=Meta):
1878 pass
1879
1880 with self.assertRaises(AttributeError):
1881 inspect.getattr_static(Thing, "spam")
1882 self.assertFalse(Thing.executed)
1883
Nick Coghlane0f04652010-11-21 03:44:04 +00001884class TestGetGeneratorState(unittest.TestCase):
1885
1886 def setUp(self):
1887 def number_generator():
1888 for number in range(5):
1889 yield number
1890 self.generator = number_generator()
1891
1892 def _generatorstate(self):
1893 return inspect.getgeneratorstate(self.generator)
1894
1895 def test_created(self):
1896 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1897
1898 def test_suspended(self):
1899 next(self.generator)
1900 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1901
1902 def test_closed_after_exhaustion(self):
1903 for i in self.generator:
1904 pass
1905 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1906
1907 def test_closed_after_immediate_exception(self):
1908 with self.assertRaises(RuntimeError):
1909 self.generator.throw(RuntimeError)
1910 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1911
1912 def test_running(self):
1913 # As mentioned on issue #10220, checking for the RUNNING state only
1914 # makes sense inside the generator itself.
1915 # The following generator checks for this by using the closure's
1916 # reference to self and the generator state checking helper method
1917 def running_check_generator():
1918 for number in range(5):
1919 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1920 yield number
1921 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1922 self.generator = running_check_generator()
1923 # Running up to the first yield
1924 next(self.generator)
1925 # Running after the first yield
1926 next(self.generator)
1927
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001928 def test_easy_debugging(self):
1929 # repr() and str() of a generator state should contain the state name
1930 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1931 for name in names:
1932 state = getattr(inspect, name)
1933 self.assertIn(name, repr(state))
1934 self.assertIn(name, str(state))
1935
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001936 def test_getgeneratorlocals(self):
1937 def each(lst, a=None):
1938 b=(1, 2, 3)
1939 for v in lst:
1940 if v == 3:
1941 c = 12
1942 yield v
1943
1944 numbers = each([1, 2, 3])
1945 self.assertEqual(inspect.getgeneratorlocals(numbers),
1946 {'a': None, 'lst': [1, 2, 3]})
1947 next(numbers)
1948 self.assertEqual(inspect.getgeneratorlocals(numbers),
1949 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1950 'b': (1, 2, 3)})
1951 next(numbers)
1952 self.assertEqual(inspect.getgeneratorlocals(numbers),
1953 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1954 'b': (1, 2, 3)})
1955 next(numbers)
1956 self.assertEqual(inspect.getgeneratorlocals(numbers),
1957 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1958 'b': (1, 2, 3), 'c': 12})
1959 try:
1960 next(numbers)
1961 except StopIteration:
1962 pass
1963 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1964
1965 def test_getgeneratorlocals_empty(self):
1966 def yield_one():
1967 yield 1
1968 one = yield_one()
1969 self.assertEqual(inspect.getgeneratorlocals(one), {})
1970 try:
1971 next(one)
1972 except StopIteration:
1973 pass
1974 self.assertEqual(inspect.getgeneratorlocals(one), {})
1975
1976 def test_getgeneratorlocals_error(self):
1977 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1978 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1979 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1980 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1981
Nick Coghlane0f04652010-11-21 03:44:04 +00001982
Yury Selivanov5376ba92015-06-22 12:19:30 -04001983class TestGetCoroutineState(unittest.TestCase):
1984
1985 def setUp(self):
1986 @types.coroutine
1987 def number_coroutine():
1988 for number in range(5):
1989 yield number
1990 async def coroutine():
1991 await number_coroutine()
1992 self.coroutine = coroutine()
1993
1994 def tearDown(self):
1995 self.coroutine.close()
1996
1997 def _coroutinestate(self):
1998 return inspect.getcoroutinestate(self.coroutine)
1999
2000 def test_created(self):
2001 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
2002
2003 def test_suspended(self):
2004 self.coroutine.send(None)
2005 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
2006
2007 def test_closed_after_exhaustion(self):
2008 while True:
2009 try:
2010 self.coroutine.send(None)
2011 except StopIteration:
2012 break
2013
2014 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2015
2016 def test_closed_after_immediate_exception(self):
2017 with self.assertRaises(RuntimeError):
2018 self.coroutine.throw(RuntimeError)
2019 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2020
2021 def test_easy_debugging(self):
2022 # repr() and str() of a coroutine state should contain the state name
2023 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2024 for name in names:
2025 state = getattr(inspect, name)
2026 self.assertIn(name, repr(state))
2027 self.assertIn(name, str(state))
2028
2029 def test_getcoroutinelocals(self):
2030 @types.coroutine
2031 def gencoro():
2032 yield
2033
2034 gencoro = gencoro()
2035 async def func(a=None):
2036 b = 'spam'
2037 await gencoro
2038
2039 coro = func()
2040 self.assertEqual(inspect.getcoroutinelocals(coro),
2041 {'a': None, 'gencoro': gencoro})
2042 coro.send(None)
2043 self.assertEqual(inspect.getcoroutinelocals(coro),
2044 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2045
2046
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002047class MySignature(inspect.Signature):
2048 # Top-level to make it picklable;
2049 # used in test_signature_object_pickle
2050 pass
2051
2052class MyParameter(inspect.Parameter):
2053 # Top-level to make it picklable;
2054 # used in test_signature_object_pickle
2055 pass
2056
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002057
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002058
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002059class TestSignatureObject(unittest.TestCase):
2060 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002061 def signature(func, **kw):
2062 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002063 return (tuple((param.name,
2064 (... if param.default is param.empty else param.default),
2065 (... if param.annotation is param.empty
2066 else param.annotation),
2067 str(param.kind).lower())
2068 for param in sig.parameters.values()),
2069 (... if sig.return_annotation is sig.empty
2070 else sig.return_annotation))
2071
2072 def test_signature_object(self):
2073 S = inspect.Signature
2074 P = inspect.Parameter
2075
2076 self.assertEqual(str(S()), '()')
2077
Yury Selivanov07a9e452014-01-29 10:58:16 -05002078 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002079 pass
2080 sig = inspect.signature(test)
2081 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002082 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002083 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002084 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002085 args = sig.parameters['args']
2086 ko = sig.parameters['ko']
2087 kwargs = sig.parameters['kwargs']
2088
2089 S((po, pk, args, ko, kwargs))
2090
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002091 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002092 S((pk, po, args, ko, kwargs))
2093
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002094 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002095 S((po, args, pk, ko, kwargs))
2096
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002097 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002098 S((args, po, pk, ko, kwargs))
2099
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002100 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002101 S((po, pk, args, kwargs, ko))
2102
2103 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002104 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002105 S((po, pk, args, kwargs2, ko))
2106
Yury Selivanov07a9e452014-01-29 10:58:16 -05002107 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2108 S((pod, po))
2109
2110 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2111 S((po, pkd, pk))
2112
2113 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2114 S((pkd, pk))
2115
Yury Selivanov374375d2014-03-27 12:41:53 -04002116 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002117 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002118
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002119 def test_signature_object_pickle(self):
2120 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2121 foo_partial = functools.partial(foo, a=1)
2122
2123 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002124
2125 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2126 with self.subTest(pickle_ver=ver, subclass=False):
2127 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2128 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002129
2130 # Test that basic sub-classing works
2131 sig = inspect.signature(foo)
2132 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2133 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2134 mysig = MySignature().replace(parameters=myparams.values(),
2135 return_annotation=sig.return_annotation)
2136 self.assertTrue(isinstance(mysig, MySignature))
2137 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2138
2139 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2140 with self.subTest(pickle_ver=ver, subclass=True):
2141 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2142 self.assertEqual(mysig, sig_pickled)
2143 self.assertTrue(isinstance(sig_pickled, MySignature))
2144 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2145 MyParameter))
2146
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002147 def test_signature_immutability(self):
2148 def test(a):
2149 pass
2150 sig = inspect.signature(test)
2151
2152 with self.assertRaises(AttributeError):
2153 sig.foo = 'bar'
2154
2155 with self.assertRaises(TypeError):
2156 sig.parameters['a'] = None
2157
2158 def test_signature_on_noarg(self):
2159 def test():
2160 pass
2161 self.assertEqual(self.signature(test), ((), ...))
2162
2163 def test_signature_on_wargs(self):
2164 def test(a, b:'foo') -> 123:
2165 pass
2166 self.assertEqual(self.signature(test),
2167 ((('a', ..., ..., "positional_or_keyword"),
2168 ('b', ..., 'foo', "positional_or_keyword")),
2169 123))
2170
2171 def test_signature_on_wkwonly(self):
2172 def test(*, a:float, b:str) -> int:
2173 pass
2174 self.assertEqual(self.signature(test),
2175 ((('a', ..., float, "keyword_only"),
2176 ('b', ..., str, "keyword_only")),
2177 int))
2178
2179 def test_signature_on_complex_args(self):
2180 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2181 pass
2182 self.assertEqual(self.signature(test),
2183 ((('a', ..., ..., "positional_or_keyword"),
2184 ('b', 10, 'foo', "positional_or_keyword"),
2185 ('args', ..., 'bar', "var_positional"),
2186 ('spam', ..., 'baz', "keyword_only"),
2187 ('ham', 123, ..., "keyword_only"),
2188 ('kwargs', ..., int, "var_keyword")),
2189 ...))
2190
Dong-hee Na378d7062017-05-18 04:00:51 +09002191 def test_signature_without_self(self):
2192 def test_args_only(*args): # NOQA
2193 pass
2194
2195 def test_args_kwargs_only(*args, **kwargs): # NOQA
2196 pass
2197
2198 class A:
2199 @classmethod
2200 def test_classmethod(*args): # NOQA
2201 pass
2202
2203 @staticmethod
2204 def test_staticmethod(*args): # NOQA
2205 pass
2206
2207 f1 = functools.partialmethod((test_classmethod), 1)
2208 f2 = functools.partialmethod((test_args_only), 1)
2209 f3 = functools.partialmethod((test_staticmethod), 1)
2210 f4 = functools.partialmethod((test_args_kwargs_only),1)
2211
2212 self.assertEqual(self.signature(test_args_only),
2213 ((('args', ..., ..., 'var_positional'),), ...))
2214 self.assertEqual(self.signature(test_args_kwargs_only),
2215 ((('args', ..., ..., 'var_positional'),
2216 ('kwargs', ..., ..., 'var_keyword')), ...))
2217 self.assertEqual(self.signature(A.f1),
2218 ((('args', ..., ..., 'var_positional'),), ...))
2219 self.assertEqual(self.signature(A.f2),
2220 ((('args', ..., ..., 'var_positional'),), ...))
2221 self.assertEqual(self.signature(A.f3),
2222 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002223 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002224 ((('args', ..., ..., 'var_positional'),
2225 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002226 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002227 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2228 "Signature information for builtins requires docstrings")
2229 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002230 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002231
Larry Hastings5c661892014-01-24 06:17:25 -08002232 def test_unbound_method(o):
2233 """Use this to test unbound methods (things that should have a self)"""
2234 signature = inspect.signature(o)
2235 self.assertTrue(isinstance(signature, inspect.Signature))
2236 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2237 return signature
2238
2239 def test_callable(o):
2240 """Use this to test bound methods or normal callables (things that don't expect self)"""
2241 signature = inspect.signature(o)
2242 self.assertTrue(isinstance(signature, inspect.Signature))
2243 if signature.parameters:
2244 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2245 return signature
2246
2247 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002248 def p(name): return signature.parameters[name].default
2249 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002250 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002251 self.assertEqual(p('d'), 3.14)
2252 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002253 self.assertEqual(p('n'), None)
2254 self.assertEqual(p('t'), True)
2255 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002256 self.assertEqual(p('local'), 3)
2257 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002258 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002259
Larry Hastings5c661892014-01-24 06:17:25 -08002260 test_callable(object)
2261
2262 # normal method
2263 # (PyMethodDescr_Type, "method_descriptor")
2264 test_unbound_method(_pickle.Pickler.dump)
2265 d = _pickle.Pickler(io.StringIO())
2266 test_callable(d.dump)
2267
2268 # static method
2269 test_callable(str.maketrans)
2270 test_callable('abc'.maketrans)
2271
2272 # class method
2273 test_callable(dict.fromkeys)
2274 test_callable({}.fromkeys)
2275
2276 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2277 test_unbound_method(type.__call__)
2278 test_unbound_method(int.__add__)
2279 test_callable((3).__add__)
2280
2281 # _PyMethodWrapper_Type
2282 # support for 'method-wrapper'
2283 test_callable(min.__call__)
2284
Larry Hastings2623c8c2014-02-08 22:15:29 -08002285 # This doesn't work now.
2286 # (We don't have a valid signature for "type" in 3.4)
2287 with self.assertRaisesRegex(ValueError, "no signature found"):
2288 class ThisWorksNow:
2289 __call__ = type
2290 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002291
Yury Selivanov056e2652014-03-02 12:25:27 -05002292 # Regression test for issue #20786
2293 test_unbound_method(dict.__delitem__)
2294 test_unbound_method(property.__delete__)
2295
Zachary Ware8ef887c2015-04-13 18:22:35 -05002296 # Regression test for issue #20586
2297 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2298
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002299 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002300 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2301 "Signature information for builtins requires docstrings")
2302 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002303 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002304 func = _testcapi.docstring_with_signature_with_defaults
2305
2306 def decorator(func):
2307 @functools.wraps(func)
2308 def wrapper(*args, **kwargs) -> int:
2309 return func(*args, **kwargs)
2310 return wrapper
2311
2312 decorated_func = decorator(func)
2313
2314 self.assertEqual(inspect.signature(func),
2315 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002316
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002317 def wrapper_like(*args, **kwargs) -> int: pass
2318 self.assertEqual(inspect.signature(decorated_func,
2319 follow_wrapped=False),
2320 inspect.signature(wrapper_like))
2321
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002322 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002323 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002324 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002325 with self.assertRaisesRegex(ValueError,
2326 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002327 inspect.signature(_testcapi.docstring_no_signature)
2328
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002329 with self.assertRaisesRegex(ValueError,
2330 'no signature found for builtin'):
2331 inspect.signature(str)
2332
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002333 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002334 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002335 inspect.signature(42)
2336
Yury Selivanov63da7c72014-01-31 14:48:37 -05002337 def test_signature_from_functionlike_object(self):
2338 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2339 pass
2340
2341 class funclike:
2342 # Has to be callable, and have correct
2343 # __code__, __annotations__, __defaults__, __name__,
2344 # and __kwdefaults__ attributes
2345
2346 def __init__(self, func):
2347 self.__name__ = func.__name__
2348 self.__code__ = func.__code__
2349 self.__annotations__ = func.__annotations__
2350 self.__defaults__ = func.__defaults__
2351 self.__kwdefaults__ = func.__kwdefaults__
2352 self.func = func
2353
2354 def __call__(self, *args, **kwargs):
2355 return self.func(*args, **kwargs)
2356
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002357 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002358
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002359 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002360 self.assertEqual(sig_funclike, sig_func)
2361
2362 sig_funclike = inspect.signature(funclike(func))
2363 self.assertEqual(sig_funclike, sig_func)
2364
2365 # If object is not a duck type of function, then
2366 # signature will try to get a signature for its '__call__'
2367 # method
2368 fl = funclike(func)
2369 del fl.__defaults__
2370 self.assertEqual(self.signature(fl),
2371 ((('args', ..., ..., "var_positional"),
2372 ('kwargs', ..., ..., "var_keyword")),
2373 ...))
2374
Yury Selivanova773de02014-02-21 18:30:53 -05002375 # Test with cython-like builtins:
2376 _orig_isdesc = inspect.ismethoddescriptor
2377 def _isdesc(obj):
2378 if hasattr(obj, '_builtinmock'):
2379 return True
2380 return _orig_isdesc(obj)
2381
2382 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2383 builtin_func = funclike(func)
2384 # Make sure that our mock setup is working
2385 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2386 builtin_func._builtinmock = True
2387 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2388 self.assertEqual(inspect.signature(builtin_func), sig_func)
2389
Yury Selivanov63da7c72014-01-31 14:48:37 -05002390 def test_signature_functionlike_class(self):
2391 # We only want to duck type function-like objects,
2392 # not classes.
2393
2394 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2395 pass
2396
2397 class funclike:
2398 def __init__(self, marker):
2399 pass
2400
2401 __name__ = func.__name__
2402 __code__ = func.__code__
2403 __annotations__ = func.__annotations__
2404 __defaults__ = func.__defaults__
2405 __kwdefaults__ = func.__kwdefaults__
2406
Yury Selivanov63da7c72014-01-31 14:48:37 -05002407 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2408
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002409 def test_signature_on_method(self):
2410 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002411 def __init__(*args):
2412 pass
2413 def m1(self, arg1, arg2=1) -> int:
2414 pass
2415 def m2(*args):
2416 pass
2417 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002418 pass
2419
Yury Selivanov62560fb2014-01-28 12:26:24 -05002420 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002421 ((('arg1', ..., ..., "positional_or_keyword"),
2422 ('arg2', 1, ..., "positional_or_keyword")),
2423 int))
2424
Yury Selivanov62560fb2014-01-28 12:26:24 -05002425 self.assertEqual(self.signature(Test().m2),
2426 ((('args', ..., ..., "var_positional"),),
2427 ...))
2428
2429 self.assertEqual(self.signature(Test),
2430 ((('args', ..., ..., "var_positional"),),
2431 ...))
2432
2433 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2434 self.signature(Test())
2435
Yury Selivanov46c759d2015-05-27 21:56:53 -04002436 def test_signature_wrapped_bound_method(self):
2437 # Issue 24298
2438 class Test:
2439 def m1(self, arg1, arg2=1) -> int:
2440 pass
2441 @functools.wraps(Test().m1)
2442 def m1d(*args, **kwargs):
2443 pass
2444 self.assertEqual(self.signature(m1d),
2445 ((('arg1', ..., ..., "positional_or_keyword"),
2446 ('arg2', 1, ..., "positional_or_keyword")),
2447 int))
2448
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002449 def test_signature_on_classmethod(self):
2450 class Test:
2451 @classmethod
2452 def foo(cls, arg1, *, arg2=1):
2453 pass
2454
2455 meth = Test().foo
2456 self.assertEqual(self.signature(meth),
2457 ((('arg1', ..., ..., "positional_or_keyword"),
2458 ('arg2', 1, ..., "keyword_only")),
2459 ...))
2460
2461 meth = Test.foo
2462 self.assertEqual(self.signature(meth),
2463 ((('arg1', ..., ..., "positional_or_keyword"),
2464 ('arg2', 1, ..., "keyword_only")),
2465 ...))
2466
2467 def test_signature_on_staticmethod(self):
2468 class Test:
2469 @staticmethod
2470 def foo(cls, *, arg):
2471 pass
2472
2473 meth = Test().foo
2474 self.assertEqual(self.signature(meth),
2475 ((('cls', ..., ..., "positional_or_keyword"),
2476 ('arg', ..., ..., "keyword_only")),
2477 ...))
2478
2479 meth = Test.foo
2480 self.assertEqual(self.signature(meth),
2481 ((('cls', ..., ..., "positional_or_keyword"),
2482 ('arg', ..., ..., "keyword_only")),
2483 ...))
2484
2485 def test_signature_on_partial(self):
2486 from functools import partial
2487
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002488 Parameter = inspect.Parameter
2489
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002490 def test():
2491 pass
2492
2493 self.assertEqual(self.signature(partial(test)), ((), ...))
2494
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002495 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002496 inspect.signature(partial(test, 1))
2497
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002498 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002499 inspect.signature(partial(test, a=1))
2500
2501 def test(a, b, *, c, d):
2502 pass
2503
2504 self.assertEqual(self.signature(partial(test)),
2505 ((('a', ..., ..., "positional_or_keyword"),
2506 ('b', ..., ..., "positional_or_keyword"),
2507 ('c', ..., ..., "keyword_only"),
2508 ('d', ..., ..., "keyword_only")),
2509 ...))
2510
2511 self.assertEqual(self.signature(partial(test, 1)),
2512 ((('b', ..., ..., "positional_or_keyword"),
2513 ('c', ..., ..., "keyword_only"),
2514 ('d', ..., ..., "keyword_only")),
2515 ...))
2516
2517 self.assertEqual(self.signature(partial(test, 1, c=2)),
2518 ((('b', ..., ..., "positional_or_keyword"),
2519 ('c', 2, ..., "keyword_only"),
2520 ('d', ..., ..., "keyword_only")),
2521 ...))
2522
2523 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2524 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002525 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002526 ('c', 2, ..., "keyword_only"),
2527 ('d', ..., ..., "keyword_only")),
2528 ...))
2529
2530 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002531 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002532 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002533 ('d', ..., ..., "keyword_only")),
2534 ...))
2535
2536 self.assertEqual(self.signature(partial(test, a=1)),
2537 ((('a', 1, ..., "keyword_only"),
2538 ('b', ..., ..., "keyword_only"),
2539 ('c', ..., ..., "keyword_only"),
2540 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002541 ...))
2542
2543 def test(a, *args, b, **kwargs):
2544 pass
2545
2546 self.assertEqual(self.signature(partial(test, 1)),
2547 ((('args', ..., ..., "var_positional"),
2548 ('b', ..., ..., "keyword_only"),
2549 ('kwargs', ..., ..., "var_keyword")),
2550 ...))
2551
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002552 self.assertEqual(self.signature(partial(test, a=1)),
2553 ((('a', 1, ..., "keyword_only"),
2554 ('b', ..., ..., "keyword_only"),
2555 ('kwargs', ..., ..., "var_keyword")),
2556 ...))
2557
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002558 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2559 ((('args', ..., ..., "var_positional"),
2560 ('b', ..., ..., "keyword_only"),
2561 ('kwargs', ..., ..., "var_keyword")),
2562 ...))
2563
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002564 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2565 ((('args', ..., ..., "var_positional"),
2566 ('b', ..., ..., "keyword_only"),
2567 ('kwargs', ..., ..., "var_keyword")),
2568 ...))
2569
2570 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2571 ((('args', ..., ..., "var_positional"),
2572 ('b', 0, ..., "keyword_only"),
2573 ('kwargs', ..., ..., "var_keyword")),
2574 ...))
2575
2576 self.assertEqual(self.signature(partial(test, b=0)),
2577 ((('a', ..., ..., "positional_or_keyword"),
2578 ('args', ..., ..., "var_positional"),
2579 ('b', 0, ..., "keyword_only"),
2580 ('kwargs', ..., ..., "var_keyword")),
2581 ...))
2582
2583 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2584 ((('a', ..., ..., "positional_or_keyword"),
2585 ('args', ..., ..., "var_positional"),
2586 ('b', 0, ..., "keyword_only"),
2587 ('kwargs', ..., ..., "var_keyword")),
2588 ...))
2589
2590 def test(a, b, c:int) -> 42:
2591 pass
2592
2593 sig = test.__signature__ = inspect.signature(test)
2594
2595 self.assertEqual(self.signature(partial(partial(test, 1))),
2596 ((('b', ..., ..., "positional_or_keyword"),
2597 ('c', ..., int, "positional_or_keyword")),
2598 42))
2599
2600 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2601 ((('c', ..., int, "positional_or_keyword"),),
2602 42))
2603
2604 psig = inspect.signature(partial(partial(test, 1), 2))
2605
2606 def foo(a):
2607 return a
2608 _foo = partial(partial(foo, a=10), a=20)
2609 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002610 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002611 ...))
2612 # check that we don't have any side-effects in signature(),
2613 # and the partial object is still functioning
2614 self.assertEqual(_foo(), 20)
2615
2616 def foo(a, b, c):
2617 return a, b, c
2618 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002619
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002620 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002621 ((('b', 30, ..., "keyword_only"),
2622 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002623 ...))
2624 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002625
2626 def foo(a, b, c, *, d):
2627 return a, b, c, d
2628 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2629 self.assertEqual(self.signature(_foo),
2630 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002631 ('b', 10, ..., "keyword_only"),
2632 ('c', 20, ..., "keyword_only"),
2633 ('d', 30, ..., "keyword_only"),
2634 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002635 ...))
2636 ba = inspect.signature(_foo).bind(a=200, b=11)
2637 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2638
2639 def foo(a=1, b=2, c=3):
2640 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002641 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2642
2643 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002644 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002645
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002646 ba = inspect.signature(_foo).bind(11, 12)
2647 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002648
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002649 ba = inspect.signature(_foo).bind(11, b=12)
2650 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002651
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002652 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002653 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2654
2655 _foo = partial(_foo, b=10, c=20)
2656 ba = inspect.signature(_foo).bind(12)
2657 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2658
2659
2660 def foo(a, b, c, d, **kwargs):
2661 pass
2662 sig = inspect.signature(foo)
2663 params = sig.parameters.copy()
2664 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2665 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2666 foo.__signature__ = inspect.Signature(params.values())
2667 sig = inspect.signature(foo)
2668 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2669
2670 self.assertEqual(self.signature(partial(foo, 1)),
2671 ((('b', ..., ..., 'positional_only'),
2672 ('c', ..., ..., 'positional_or_keyword'),
2673 ('d', ..., ..., 'positional_or_keyword'),
2674 ('kwargs', ..., ..., 'var_keyword')),
2675 ...))
2676
2677 self.assertEqual(self.signature(partial(foo, 1, 2)),
2678 ((('c', ..., ..., 'positional_or_keyword'),
2679 ('d', ..., ..., 'positional_or_keyword'),
2680 ('kwargs', ..., ..., 'var_keyword')),
2681 ...))
2682
2683 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2684 ((('d', ..., ..., 'positional_or_keyword'),
2685 ('kwargs', ..., ..., 'var_keyword')),
2686 ...))
2687
2688 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2689 ((('c', 3, ..., 'keyword_only'),
2690 ('d', ..., ..., 'keyword_only'),
2691 ('kwargs', ..., ..., 'var_keyword')),
2692 ...))
2693
2694 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2695 ((('b', ..., ..., 'positional_only'),
2696 ('c', 3, ..., 'keyword_only'),
2697 ('d', ..., ..., 'keyword_only'),
2698 ('kwargs', ..., ..., 'var_keyword')),
2699 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002700
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002701 def test_signature_on_partialmethod(self):
2702 from functools import partialmethod
2703
2704 class Spam:
2705 def test():
2706 pass
2707 ham = partialmethod(test)
2708
2709 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2710 inspect.signature(Spam.ham)
2711
2712 class Spam:
2713 def test(it, a, *, c) -> 'spam':
2714 pass
2715 ham = partialmethod(test, c=1)
2716
2717 self.assertEqual(self.signature(Spam.ham),
2718 ((('it', ..., ..., 'positional_or_keyword'),
2719 ('a', ..., ..., 'positional_or_keyword'),
2720 ('c', 1, ..., 'keyword_only')),
2721 'spam'))
2722
2723 self.assertEqual(self.signature(Spam().ham),
2724 ((('a', ..., ..., 'positional_or_keyword'),
2725 ('c', 1, ..., 'keyword_only')),
2726 'spam'))
2727
Yury Selivanov8a387212018-03-06 12:59:45 -05002728 class Spam:
2729 def test(self: 'anno', x):
2730 pass
2731
2732 g = partialmethod(test, 1)
2733
2734 self.assertEqual(self.signature(Spam.g),
2735 ((('self', ..., 'anno', 'positional_or_keyword'),),
2736 ...))
2737
Yury Selivanov0486f812014-01-29 12:18:59 -05002738 def test_signature_on_fake_partialmethod(self):
2739 def foo(a): pass
2740 foo._partialmethod = 'spam'
2741 self.assertEqual(str(inspect.signature(foo)), '(a)')
2742
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002743 def test_signature_on_decorated(self):
2744 import functools
2745
2746 def decorator(func):
2747 @functools.wraps(func)
2748 def wrapper(*args, **kwargs) -> int:
2749 return func(*args, **kwargs)
2750 return wrapper
2751
2752 class Foo:
2753 @decorator
2754 def bar(self, a, b):
2755 pass
2756
2757 self.assertEqual(self.signature(Foo.bar),
2758 ((('self', ..., ..., "positional_or_keyword"),
2759 ('a', ..., ..., "positional_or_keyword"),
2760 ('b', ..., ..., "positional_or_keyword")),
2761 ...))
2762
2763 self.assertEqual(self.signature(Foo().bar),
2764 ((('a', ..., ..., "positional_or_keyword"),
2765 ('b', ..., ..., "positional_or_keyword")),
2766 ...))
2767
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002768 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2769 ((('args', ..., ..., "var_positional"),
2770 ('kwargs', ..., ..., "var_keyword")),
2771 ...)) # functools.wraps will copy __annotations__
2772 # from "func" to "wrapper", hence no
2773 # return_annotation
2774
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002775 # Test that we handle method wrappers correctly
2776 def decorator(func):
2777 @functools.wraps(func)
2778 def wrapper(*args, **kwargs) -> int:
2779 return func(42, *args, **kwargs)
2780 sig = inspect.signature(func)
2781 new_params = tuple(sig.parameters.values())[1:]
2782 wrapper.__signature__ = sig.replace(parameters=new_params)
2783 return wrapper
2784
2785 class Foo:
2786 @decorator
2787 def __call__(self, a, b):
2788 pass
2789
2790 self.assertEqual(self.signature(Foo.__call__),
2791 ((('a', ..., ..., "positional_or_keyword"),
2792 ('b', ..., ..., "positional_or_keyword")),
2793 ...))
2794
2795 self.assertEqual(self.signature(Foo().__call__),
2796 ((('b', ..., ..., "positional_or_keyword"),),
2797 ...))
2798
Nick Coghlane8c45d62013-07-28 20:00:01 +10002799 # Test we handle __signature__ partway down the wrapper stack
2800 def wrapped_foo_call():
2801 pass
2802 wrapped_foo_call.__wrapped__ = Foo.__call__
2803
2804 self.assertEqual(self.signature(wrapped_foo_call),
2805 ((('a', ..., ..., "positional_or_keyword"),
2806 ('b', ..., ..., "positional_or_keyword")),
2807 ...))
2808
2809
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002810 def test_signature_on_class(self):
2811 class C:
2812 def __init__(self, a):
2813 pass
2814
2815 self.assertEqual(self.signature(C),
2816 ((('a', ..., ..., "positional_or_keyword"),),
2817 ...))
2818
2819 class CM(type):
2820 def __call__(cls, a):
2821 pass
2822 class C(metaclass=CM):
2823 def __init__(self, b):
2824 pass
2825
2826 self.assertEqual(self.signature(C),
2827 ((('a', ..., ..., "positional_or_keyword"),),
2828 ...))
2829
2830 class CM(type):
2831 def __new__(mcls, name, bases, dct, *, foo=1):
2832 return super().__new__(mcls, name, bases, dct)
2833 class C(metaclass=CM):
2834 def __init__(self, b):
2835 pass
2836
2837 self.assertEqual(self.signature(C),
2838 ((('b', ..., ..., "positional_or_keyword"),),
2839 ...))
2840
2841 self.assertEqual(self.signature(CM),
2842 ((('name', ..., ..., "positional_or_keyword"),
2843 ('bases', ..., ..., "positional_or_keyword"),
2844 ('dct', ..., ..., "positional_or_keyword"),
2845 ('foo', 1, ..., "keyword_only")),
2846 ...))
2847
2848 class CMM(type):
2849 def __new__(mcls, name, bases, dct, *, foo=1):
2850 return super().__new__(mcls, name, bases, dct)
2851 def __call__(cls, nm, bs, dt):
2852 return type(nm, bs, dt)
2853 class CM(type, metaclass=CMM):
2854 def __new__(mcls, name, bases, dct, *, bar=2):
2855 return super().__new__(mcls, name, bases, dct)
2856 class C(metaclass=CM):
2857 def __init__(self, b):
2858 pass
2859
2860 self.assertEqual(self.signature(CMM),
2861 ((('name', ..., ..., "positional_or_keyword"),
2862 ('bases', ..., ..., "positional_or_keyword"),
2863 ('dct', ..., ..., "positional_or_keyword"),
2864 ('foo', 1, ..., "keyword_only")),
2865 ...))
2866
2867 self.assertEqual(self.signature(CM),
2868 ((('nm', ..., ..., "positional_or_keyword"),
2869 ('bs', ..., ..., "positional_or_keyword"),
2870 ('dt', ..., ..., "positional_or_keyword")),
2871 ...))
2872
2873 self.assertEqual(self.signature(C),
2874 ((('b', ..., ..., "positional_or_keyword"),),
2875 ...))
2876
2877 class CM(type):
2878 def __init__(cls, name, bases, dct, *, bar=2):
2879 return super().__init__(name, bases, dct)
2880 class C(metaclass=CM):
2881 def __init__(self, b):
2882 pass
2883
2884 self.assertEqual(self.signature(CM),
2885 ((('name', ..., ..., "positional_or_keyword"),
2886 ('bases', ..., ..., "positional_or_keyword"),
2887 ('dct', ..., ..., "positional_or_keyword"),
2888 ('bar', 2, ..., "keyword_only")),
2889 ...))
2890
Yury Selivanov145dff82014-02-01 13:49:29 -05002891 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2892 "Signature information for builtins requires docstrings")
2893 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002894 # Test classes without user-defined __init__ or __new__
2895 class C: pass
2896 self.assertEqual(str(inspect.signature(C)), '()')
2897 class D(C): pass
2898 self.assertEqual(str(inspect.signature(D)), '()')
2899
2900 # Test meta-classes without user-defined __init__ or __new__
2901 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002902 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002903 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2904 self.assertEqual(inspect.signature(C), None)
2905 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2906 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002907
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002908 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2909 "Signature information for builtins requires docstrings")
2910 def test_signature_on_builtin_class(self):
2911 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2912 '(file, protocol=None, fix_imports=True)')
2913
2914 class P(_pickle.Pickler): pass
2915 class EmptyTrait: pass
2916 class P2(EmptyTrait, P): pass
2917 self.assertEqual(str(inspect.signature(P)),
2918 '(file, protocol=None, fix_imports=True)')
2919 self.assertEqual(str(inspect.signature(P2)),
2920 '(file, protocol=None, fix_imports=True)')
2921
2922 class P3(P2):
2923 def __init__(self, spam):
2924 pass
2925 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2926
2927 class MetaP(type):
2928 def __call__(cls, foo, bar):
2929 pass
2930 class P4(P2, metaclass=MetaP):
2931 pass
2932 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2933
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002934 def test_signature_on_callable_objects(self):
2935 class Foo:
2936 def __call__(self, a):
2937 pass
2938
2939 self.assertEqual(self.signature(Foo()),
2940 ((('a', ..., ..., "positional_or_keyword"),),
2941 ...))
2942
2943 class Spam:
2944 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002945 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002946 inspect.signature(Spam())
2947
2948 class Bar(Spam, Foo):
2949 pass
2950
2951 self.assertEqual(self.signature(Bar()),
2952 ((('a', ..., ..., "positional_or_keyword"),),
2953 ...))
2954
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002955 class Wrapped:
2956 pass
2957 Wrapped.__wrapped__ = lambda a: None
2958 self.assertEqual(self.signature(Wrapped),
2959 ((('a', ..., ..., "positional_or_keyword"),),
2960 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002961 # wrapper loop:
2962 Wrapped.__wrapped__ = Wrapped
2963 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2964 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002965
2966 def test_signature_on_lambdas(self):
2967 self.assertEqual(self.signature((lambda a=10: a)),
2968 ((('a', 10, ..., "positional_or_keyword"),),
2969 ...))
2970
2971 def test_signature_equality(self):
2972 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002973 self.assertFalse(inspect.signature(foo) == 42)
2974 self.assertTrue(inspect.signature(foo) != 42)
2975 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2976 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002977
2978 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002979 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2980 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002981 self.assertEqual(
2982 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002983
2984 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002985 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2986 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002987 self.assertNotEqual(
2988 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002989
2990 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002991 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2992 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002993 self.assertNotEqual(
2994 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002995
2996 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002997 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2998 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002999 self.assertNotEqual(
3000 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003001
3002 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003003 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3004 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003005 self.assertNotEqual(
3006 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003007
3008 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003009 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3010 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003011 self.assertNotEqual(
3012 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003013 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003014 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3015 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003016 self.assertNotEqual(
3017 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003018
3019 def foo(*, a, b, c): pass
3020 def bar(*, c, b, a): 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(*, a=1, b, c): pass
3027 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003028 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3029 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003030 self.assertEqual(
3031 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003032
3033 def foo(pos, *, a=1, b, c): pass
3034 def bar(pos, *, c, b, a=1): 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
3040 def foo(pos, *, a, b, c): pass
3041 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003042 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3043 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003044 self.assertNotEqual(
3045 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003046
3047 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3048 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003049 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3050 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003051 self.assertEqual(
3052 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003053
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003054 def test_signature_hashable(self):
3055 S = inspect.Signature
3056 P = inspect.Parameter
3057
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003058 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003059 foo_sig = inspect.signature(foo)
3060
3061 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3062
3063 self.assertEqual(hash(foo_sig), hash(manual_sig))
3064 self.assertNotEqual(hash(foo_sig),
3065 hash(manual_sig.replace(return_annotation='spam')))
3066
3067 def bar(a) -> 1: pass
3068 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3069
3070 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003071 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003072 hash(inspect.signature(foo))
3073
3074 def foo(a) -> {}: pass
3075 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3076 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003077
3078 def test_signature_str(self):
3079 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3080 pass
3081 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003082 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003083
3084 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3085 pass
3086 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003087 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003088
3089 def foo():
3090 pass
3091 self.assertEqual(str(inspect.signature(foo)), '()')
3092
3093 def test_signature_str_positional_only(self):
3094 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003095 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003096
3097 def test(a_po, *, b, **kwargs):
3098 return a_po, kwargs
3099
3100 sig = inspect.signature(test)
3101 new_params = list(sig.parameters.values())
3102 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3103 test.__signature__ = sig.replace(parameters=new_params)
3104
3105 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003106 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003107
Yury Selivanov2393dca2014-01-27 15:07:58 -05003108 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3109 '(foo, /)')
3110
3111 self.assertEqual(str(S(parameters=[
3112 P('foo', P.POSITIONAL_ONLY),
3113 P('bar', P.VAR_KEYWORD)])),
3114 '(foo, /, **bar)')
3115
3116 self.assertEqual(str(S(parameters=[
3117 P('foo', P.POSITIONAL_ONLY),
3118 P('bar', P.VAR_POSITIONAL)])),
3119 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003120
3121 def test_signature_replace_anno(self):
3122 def test() -> 42:
3123 pass
3124
3125 sig = inspect.signature(test)
3126 sig = sig.replace(return_annotation=None)
3127 self.assertIs(sig.return_annotation, None)
3128 sig = sig.replace(return_annotation=sig.empty)
3129 self.assertIs(sig.return_annotation, sig.empty)
3130 sig = sig.replace(return_annotation=42)
3131 self.assertEqual(sig.return_annotation, 42)
3132 self.assertEqual(sig, inspect.signature(test))
3133
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003134 def test_signature_on_mangled_parameters(self):
3135 class Spam:
3136 def foo(self, __p1:1=2, *, __p2:2=3):
3137 pass
3138 class Ham(Spam):
3139 pass
3140
3141 self.assertEqual(self.signature(Spam.foo),
3142 ((('self', ..., ..., "positional_or_keyword"),
3143 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3144 ('_Spam__p2', 3, 2, "keyword_only")),
3145 ...))
3146
3147 self.assertEqual(self.signature(Spam.foo),
3148 self.signature(Ham.foo))
3149
Yury Selivanovda396452014-03-27 12:09:24 -04003150 def test_signature_from_callable_python_obj(self):
3151 class MySignature(inspect.Signature): pass
3152 def foo(a, *, b:1): pass
3153 foo_sig = MySignature.from_callable(foo)
3154 self.assertTrue(isinstance(foo_sig, MySignature))
3155
3156 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3157 "Signature information for builtins requires docstrings")
3158 def test_signature_from_callable_builtin_obj(self):
3159 class MySignature(inspect.Signature): pass
3160 sig = MySignature.from_callable(_pickle.Pickler)
3161 self.assertTrue(isinstance(sig, MySignature))
3162
larryhastingsf36ba122018-01-28 11:13:09 -08003163 def test_signature_definition_order_preserved_on_kwonly(self):
3164 for fn in signatures_with_lexicographic_keyword_only_parameters():
3165 signature = inspect.signature(fn)
3166 l = list(signature.parameters)
3167 sorted_l = sorted(l)
3168 self.assertTrue(l)
3169 self.assertEqual(l, sorted_l)
3170 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3171 l = list(signature.parameters)
3172 self.assertEqual(l, unsorted_keyword_only_parameters)
3173
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003174
3175class TestParameterObject(unittest.TestCase):
3176 def test_signature_parameter_kinds(self):
3177 P = inspect.Parameter
3178 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3179 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3180
3181 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3182 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3183
3184 def test_signature_parameter_object(self):
3185 p = inspect.Parameter('foo', default=10,
3186 kind=inspect.Parameter.POSITIONAL_ONLY)
3187 self.assertEqual(p.name, 'foo')
3188 self.assertEqual(p.default, 10)
3189 self.assertIs(p.annotation, p.empty)
3190 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3191
Dong-hee Naa9cab432018-05-30 00:04:08 +09003192 with self.assertRaisesRegex(ValueError, "value '123' is "
3193 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003194 inspect.Parameter('foo', default=10, kind='123')
3195
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003196 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003197 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3198
Yury Selivanov2393dca2014-01-27 15:07:58 -05003199 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003200 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3201
Yury Selivanov2393dca2014-01-27 15:07:58 -05003202 with self.assertRaisesRegex(ValueError,
3203 'is not a valid parameter name'):
3204 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3205
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003206 with self.assertRaisesRegex(ValueError,
3207 'is not a valid parameter name'):
3208 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3209
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003210 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003211 inspect.Parameter('a', default=42,
3212 kind=inspect.Parameter.VAR_KEYWORD)
3213
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003214 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003215 inspect.Parameter('a', default=42,
3216 kind=inspect.Parameter.VAR_POSITIONAL)
3217
3218 p = inspect.Parameter('a', default=42,
3219 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003220 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003221 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3222
3223 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003224 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003225
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003226 def test_signature_parameter_hashable(self):
3227 P = inspect.Parameter
3228 foo = P('foo', kind=P.POSITIONAL_ONLY)
3229 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3230 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3231 default=42)))
3232 self.assertNotEqual(hash(foo),
3233 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3234
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003235 def test_signature_parameter_equality(self):
3236 P = inspect.Parameter
3237 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3238
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003239 self.assertTrue(p == p)
3240 self.assertFalse(p != p)
3241 self.assertFalse(p == 42)
3242 self.assertTrue(p != 42)
3243 self.assertTrue(p == EqualsToAll())
3244 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003245
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003246 self.assertTrue(p == P('foo', default=42,
3247 kind=inspect.Parameter.KEYWORD_ONLY))
3248 self.assertFalse(p != P('foo', default=42,
3249 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003250
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003251 def test_signature_parameter_replace(self):
3252 p = inspect.Parameter('foo', default=42,
3253 kind=inspect.Parameter.KEYWORD_ONLY)
3254
3255 self.assertIsNot(p, p.replace())
3256 self.assertEqual(p, p.replace())
3257
3258 p2 = p.replace(annotation=1)
3259 self.assertEqual(p2.annotation, 1)
3260 p2 = p2.replace(annotation=p2.empty)
3261 self.assertEqual(p, p2)
3262
3263 p2 = p2.replace(name='bar')
3264 self.assertEqual(p2.name, 'bar')
3265 self.assertNotEqual(p2, p)
3266
Yury Selivanov2393dca2014-01-27 15:07:58 -05003267 with self.assertRaisesRegex(ValueError,
3268 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003269 p2 = p2.replace(name=p2.empty)
3270
3271 p2 = p2.replace(name='foo', default=None)
3272 self.assertIs(p2.default, None)
3273 self.assertNotEqual(p2, p)
3274
3275 p2 = p2.replace(name='foo', default=p2.empty)
3276 self.assertIs(p2.default, p2.empty)
3277
3278
3279 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3280 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3281 self.assertNotEqual(p2, p)
3282
Dong-hee Naa9cab432018-05-30 00:04:08 +09003283 with self.assertRaisesRegex(ValueError,
3284 "value <class 'inspect._empty'> "
3285 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003286 p2 = p2.replace(kind=p2.empty)
3287
3288 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3289 self.assertEqual(p2, p)
3290
3291 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003292 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3293 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003294
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003295 @cpython_only
3296 def test_signature_parameter_implicit(self):
3297 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003298 'implicit arguments must be passed as '
3299 'positional or keyword arguments, '
3300 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003301 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3302
3303 param = inspect.Parameter(
3304 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3305 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3306 self.assertEqual(param.name, 'implicit0')
3307
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003308 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003309 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003310
3311 with self.assertRaises(AttributeError):
3312 p.foo = 'bar'
3313
3314 with self.assertRaises(AttributeError):
3315 p.kind = 123
3316
3317
3318class TestSignatureBind(unittest.TestCase):
3319 @staticmethod
3320 def call(func, *args, **kwargs):
3321 sig = inspect.signature(func)
3322 ba = sig.bind(*args, **kwargs)
3323 return func(*ba.args, **ba.kwargs)
3324
3325 def test_signature_bind_empty(self):
3326 def test():
3327 return 42
3328
3329 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003330 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003331 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003332 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003333 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003334 with self.assertRaisesRegex(
3335 TypeError, "got an unexpected keyword argument 'spam'"):
3336
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003337 self.call(test, spam=1)
3338
3339 def test_signature_bind_var(self):
3340 def test(*args, **kwargs):
3341 return args, kwargs
3342
3343 self.assertEqual(self.call(test), ((), {}))
3344 self.assertEqual(self.call(test, 1), ((1,), {}))
3345 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3346 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3347 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3348 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3349 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3350 ((1, 2), {'foo': 'bar'}))
3351
3352 def test_signature_bind_just_args(self):
3353 def test(a, b, c):
3354 return a, b, c
3355
3356 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3357
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003358 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003359 self.call(test, 1, 2, 3, 4)
3360
Yury Selivanov86872752015-05-19 00:27:49 -04003361 with self.assertRaisesRegex(TypeError,
3362 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003363 self.call(test, 1)
3364
Yury Selivanov86872752015-05-19 00:27:49 -04003365 with self.assertRaisesRegex(TypeError,
3366 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003367 self.call(test)
3368
3369 def test(a, b, c=10):
3370 return a, b, c
3371 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3372 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3373
3374 def test(a=1, b=2, c=3):
3375 return a, b, c
3376 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3377 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3378 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3379
3380 def test_signature_bind_varargs_order(self):
3381 def test(*args):
3382 return args
3383
3384 self.assertEqual(self.call(test), ())
3385 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3386
3387 def test_signature_bind_args_and_varargs(self):
3388 def test(a, b, c=3, *args):
3389 return a, b, c, args
3390
3391 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3392 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3393 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3394 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3395
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003396 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003397 "multiple values for argument 'c'"):
3398 self.call(test, 1, 2, 3, c=4)
3399
3400 def test_signature_bind_just_kwargs(self):
3401 def test(**kwargs):
3402 return kwargs
3403
3404 self.assertEqual(self.call(test), {})
3405 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3406 {'foo': 'bar', 'spam': 'ham'})
3407
3408 def test_signature_bind_args_and_kwargs(self):
3409 def test(a, b, c=3, **kwargs):
3410 return a, b, c, kwargs
3411
3412 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3413 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3414 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3415 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3416 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3417 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3418 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3419 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3420 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3421 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3422 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3423 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3424 (1, 2, 4, {'foo': 'bar'}))
3425 self.assertEqual(self.call(test, c=5, a=4, b=3),
3426 (4, 3, 5, {}))
3427
3428 def test_signature_bind_kwonly(self):
3429 def test(*, foo):
3430 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003431 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003432 'too many positional arguments'):
3433 self.call(test, 1)
3434 self.assertEqual(self.call(test, foo=1), 1)
3435
3436 def test(a, *, foo=1, bar):
3437 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003438 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003439 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003440 self.call(test, 1)
3441
3442 def test(foo, *, bar):
3443 return foo, bar
3444 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3445 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3446
Yury Selivanov86872752015-05-19 00:27:49 -04003447 with self.assertRaisesRegex(
3448 TypeError, "got an unexpected keyword argument 'spam'"):
3449
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003450 self.call(test, bar=2, foo=1, spam=10)
3451
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003452 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003453 'too many positional arguments'):
3454 self.call(test, 1, 2)
3455
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003456 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003457 'too many positional arguments'):
3458 self.call(test, 1, 2, bar=2)
3459
Yury Selivanov86872752015-05-19 00:27:49 -04003460 with self.assertRaisesRegex(
3461 TypeError, "got an unexpected keyword argument 'spam'"):
3462
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003463 self.call(test, 1, bar=2, spam='ham')
3464
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003465 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003466 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003467 self.call(test, 1)
3468
3469 def test(foo, *, bar, **bin):
3470 return foo, bar, bin
3471 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3472 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3473 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3474 (1, 2, {'spam': 'ham'}))
3475 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3476 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003477 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003478 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003479 self.call(test, spam='ham', bar=2)
3480 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3481 (1, 2, {'bin': 1, 'spam': 10}))
3482
3483 def test_signature_bind_arguments(self):
3484 def test(a, *args, b, z=100, **kwargs):
3485 pass
3486 sig = inspect.signature(test)
3487 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3488 # we won't have 'z' argument in the bound arguments object, as we didn't
3489 # pass it to the 'bind'
3490 self.assertEqual(tuple(ba.arguments.items()),
3491 (('a', 10), ('args', (20,)), ('b', 30),
3492 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3493 self.assertEqual(ba.kwargs,
3494 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3495 self.assertEqual(ba.args, (10, 20))
3496
3497 def test_signature_bind_positional_only(self):
3498 P = inspect.Parameter
3499
3500 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3501 return a_po, b_po, c_po, foo, bar, kwargs
3502
3503 sig = inspect.signature(test)
3504 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3505 for name in ('a_po', 'b_po', 'c_po'):
3506 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3507 new_sig = sig.replace(parameters=new_params.values())
3508 test.__signature__ = new_sig
3509
3510 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3511 (1, 2, 4, 5, 6, {}))
3512
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003513 self.assertEqual(self.call(test, 1, 2),
3514 (1, 2, 3, 42, 50, {}))
3515
3516 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3517 (1, 2, 3, 4, 5, {}))
3518
3519 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3520 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3521
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003522 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003523 self.call(test, 1, 2, c_po=4)
3524
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003525 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003526 self.call(test, a_po=1, b_po=2)
3527
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003528 def test_signature_bind_with_self_arg(self):
3529 # Issue #17071: one of the parameters is named "self
3530 def test(a, self, b):
3531 pass
3532 sig = inspect.signature(test)
3533 ba = sig.bind(1, 2, 3)
3534 self.assertEqual(ba.args, (1, 2, 3))
3535 ba = sig.bind(1, self=2, b=3)
3536 self.assertEqual(ba.args, (1, 2, 3))
3537
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003538 def test_signature_bind_vararg_name(self):
3539 def test(a, *args):
3540 return a, args
3541 sig = inspect.signature(test)
3542
Yury Selivanov86872752015-05-19 00:27:49 -04003543 with self.assertRaisesRegex(
3544 TypeError, "got an unexpected keyword argument 'args'"):
3545
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003546 sig.bind(a=0, args=1)
3547
3548 def test(*args, **kwargs):
3549 return args, kwargs
3550 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3551
3552 sig = inspect.signature(test)
3553 ba = sig.bind(args=1)
3554 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3555
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003556 @cpython_only
3557 def test_signature_bind_implicit_arg(self):
3558 # Issue #19611: getcallargs should work with set comprehensions
3559 def make_set():
3560 return {z * z for z in range(5)}
3561 setcomp_code = make_set.__code__.co_consts[1]
3562 setcomp_func = types.FunctionType(setcomp_code, {})
3563
3564 iterator = iter(range(5))
3565 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3566
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003567
3568class TestBoundArguments(unittest.TestCase):
3569 def test_signature_bound_arguments_unhashable(self):
3570 def foo(a): pass
3571 ba = inspect.signature(foo).bind(1)
3572
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003573 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003574 hash(ba)
3575
3576 def test_signature_bound_arguments_equality(self):
3577 def foo(a): pass
3578 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003579 self.assertTrue(ba == ba)
3580 self.assertFalse(ba != ba)
3581 self.assertTrue(ba == EqualsToAll())
3582 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003583
3584 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003585 self.assertTrue(ba == ba2)
3586 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003587
3588 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003589 self.assertFalse(ba == ba3)
3590 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003591 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003592 self.assertTrue(ba == ba3)
3593 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003594
3595 def bar(b): pass
3596 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003597 self.assertFalse(ba == ba4)
3598 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003599
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003600 def foo(*, a, b): pass
3601 sig = inspect.signature(foo)
3602 ba1 = sig.bind(a=1, b=2)
3603 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003604 self.assertTrue(ba1 == ba2)
3605 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003606
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003607 def test_signature_bound_arguments_pickle(self):
3608 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3609 sig = inspect.signature(foo)
3610 ba = sig.bind(20, 30, z={})
3611
3612 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3613 with self.subTest(pickle_ver=ver):
3614 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3615 self.assertEqual(ba, ba_pickled)
3616
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003617 def test_signature_bound_arguments_repr(self):
3618 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3619 sig = inspect.signature(foo)
3620 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003621 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003622
Yury Selivanovb907a512015-05-16 13:45:09 -04003623 def test_signature_bound_arguments_apply_defaults(self):
3624 def foo(a, b=1, *args, c:1={}, **kw): pass
3625 sig = inspect.signature(foo)
3626
3627 ba = sig.bind(20)
3628 ba.apply_defaults()
3629 self.assertEqual(
3630 list(ba.arguments.items()),
3631 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3632
3633 # Make sure that we preserve the order:
3634 # i.e. 'c' should be *before* 'kw'.
3635 ba = sig.bind(10, 20, 30, d=1)
3636 ba.apply_defaults()
3637 self.assertEqual(
3638 list(ba.arguments.items()),
3639 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3640
3641 # Make sure that BoundArguments produced by bind_partial()
3642 # are supported.
3643 def foo(a, b): pass
3644 sig = inspect.signature(foo)
3645 ba = sig.bind_partial(20)
3646 ba.apply_defaults()
3647 self.assertEqual(
3648 list(ba.arguments.items()),
3649 [('a', 20)])
3650
3651 # Test no args
3652 def foo(): pass
3653 sig = inspect.signature(foo)
3654 ba = sig.bind()
3655 ba.apply_defaults()
3656 self.assertEqual(list(ba.arguments.items()), [])
3657
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003658 # Make sure a no-args binding still acquires proper defaults.
3659 def foo(a='spam'): pass
3660 sig = inspect.signature(foo)
3661 ba = sig.bind()
3662 ba.apply_defaults()
3663 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3664
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003665
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003666class TestSignaturePrivateHelpers(unittest.TestCase):
3667 def test_signature_get_bound_param(self):
3668 getter = inspect._signature_get_bound_param
3669
3670 self.assertEqual(getter('($self)'), 'self')
3671 self.assertEqual(getter('($self, obj)'), 'self')
3672 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3673
Larry Hastings2623c8c2014-02-08 22:15:29 -08003674 def _strip_non_python_syntax(self, input,
3675 clean_signature, self_parameter, last_positional_only):
3676 computed_clean_signature, \
3677 computed_self_parameter, \
3678 computed_last_positional_only = \
3679 inspect._signature_strip_non_python_syntax(input)
3680 self.assertEqual(computed_clean_signature, clean_signature)
3681 self.assertEqual(computed_self_parameter, self_parameter)
3682 self.assertEqual(computed_last_positional_only, last_positional_only)
3683
3684 def test_signature_strip_non_python_syntax(self):
3685 self._strip_non_python_syntax(
3686 "($module, /, path, mode, *, dir_fd=None, " +
3687 "effective_ids=False,\n follow_symlinks=True)",
3688 "(module, path, mode, *, dir_fd=None, " +
3689 "effective_ids=False, follow_symlinks=True)",
3690 0,
3691 0)
3692
3693 self._strip_non_python_syntax(
3694 "($module, word, salt, /)",
3695 "(module, word, salt)",
3696 0,
3697 2)
3698
3699 self._strip_non_python_syntax(
3700 "(x, y=None, z=None, /)",
3701 "(x, y=None, z=None)",
3702 None,
3703 2)
3704
3705 self._strip_non_python_syntax(
3706 "(x, y=None, z=None)",
3707 "(x, y=None, z=None)",
3708 None,
3709 None)
3710
3711 self._strip_non_python_syntax(
3712 "(x,\n y=None,\n z = None )",
3713 "(x, y=None, z=None)",
3714 None,
3715 None)
3716
3717 self._strip_non_python_syntax(
3718 "",
3719 "",
3720 None,
3721 None)
3722
3723 self._strip_non_python_syntax(
3724 None,
3725 None,
3726 None,
3727 None)
3728
Nick Coghlan9c680b02015-04-13 12:54:54 -04003729class TestSignatureDefinitions(unittest.TestCase):
3730 # This test case provides a home for checking that particular APIs
3731 # have signatures available for introspection
3732
3733 @cpython_only
3734 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3735 "Signature information for builtins requires docstrings")
3736 def test_builtins_have_signatures(self):
3737 # This checks all builtin callables in CPython have signatures
3738 # A few have signatures Signature can't yet handle, so we skip those
3739 # since they will have to wait until PEP 457 adds the required
3740 # introspection support to the inspect module
3741 # Some others also haven't been converted yet for various other
3742 # reasons, so we also skip those for the time being, but design
3743 # the test to fail in order to indicate when it needs to be
3744 # updated.
3745 no_signature = set()
3746 # These need PEP 457 groups
3747 needs_groups = {"range", "slice", "dir", "getattr",
3748 "next", "iter", "vars"}
3749 no_signature |= needs_groups
3750 # These need PEP 457 groups or a signature change to accept None
3751 needs_semantic_update = {"round"}
3752 no_signature |= needs_semantic_update
3753 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003754 needs_varargs = {"breakpoint", "min", "max", "print",
3755 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003756 no_signature |= needs_varargs
3757 # These simply weren't covered in the initial AC conversion
3758 # for builtin callables
3759 not_converted_yet = {"open", "__import__"}
3760 no_signature |= not_converted_yet
3761 # These builtin types are expected to provide introspection info
3762 types_with_signatures = set()
3763 # Check the signatures we expect to be there
3764 ns = vars(builtins)
3765 for name, obj in sorted(ns.items()):
3766 if not callable(obj):
3767 continue
3768 # The builtin types haven't been converted to AC yet
3769 if isinstance(obj, type) and (name not in types_with_signatures):
3770 # Note that this also skips all the exception types
3771 no_signature.add(name)
3772 if (name in no_signature):
3773 # Not yet converted
3774 continue
3775 with self.subTest(builtin=name):
3776 self.assertIsNotNone(inspect.signature(obj))
3777 # Check callables that haven't been converted don't claim a signature
3778 # This ensures this test will start failing as more signatures are
3779 # added, so the affected items can be moved into the scope of the
3780 # regression test above
3781 for name in no_signature:
3782 with self.subTest(builtin=name):
3783 self.assertIsNone(obj.__text_signature__)
3784
Serhiy Storchakad53cf992019-05-06 22:40:27 +03003785 def test_python_function_override_signature(self):
3786 def func(*args, **kwargs):
3787 pass
3788 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
3789 sig = inspect.signature(func)
3790 self.assertIsNotNone(sig)
3791 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
3792 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
3793 sig = inspect.signature(func)
3794 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
3795
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003796
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003797class NTimesUnwrappable:
3798 def __init__(self, n):
3799 self.n = n
3800 self._next = None
3801
3802 @property
3803 def __wrapped__(self):
3804 if self.n <= 0:
3805 raise Exception("Unwrapped too many times")
3806 if self._next is None:
3807 self._next = NTimesUnwrappable(self.n - 1)
3808 return self._next
3809
Nick Coghlane8c45d62013-07-28 20:00:01 +10003810class TestUnwrap(unittest.TestCase):
3811
3812 def test_unwrap_one(self):
3813 def func(a, b):
3814 return a + b
3815 wrapper = functools.lru_cache(maxsize=20)(func)
3816 self.assertIs(inspect.unwrap(wrapper), func)
3817
3818 def test_unwrap_several(self):
3819 def func(a, b):
3820 return a + b
3821 wrapper = func
3822 for __ in range(10):
3823 @functools.wraps(wrapper)
3824 def wrapper():
3825 pass
3826 self.assertIsNot(wrapper.__wrapped__, func)
3827 self.assertIs(inspect.unwrap(wrapper), func)
3828
3829 def test_stop(self):
3830 def func1(a, b):
3831 return a + b
3832 @functools.wraps(func1)
3833 def func2():
3834 pass
3835 @functools.wraps(func2)
3836 def wrapper():
3837 pass
3838 func2.stop_here = 1
3839 unwrapped = inspect.unwrap(wrapper,
3840 stop=(lambda f: hasattr(f, "stop_here")))
3841 self.assertIs(unwrapped, func2)
3842
3843 def test_cycle(self):
3844 def func1(): pass
3845 func1.__wrapped__ = func1
3846 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3847 inspect.unwrap(func1)
3848
3849 def func2(): pass
3850 func2.__wrapped__ = func1
3851 func1.__wrapped__ = func2
3852 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3853 inspect.unwrap(func1)
3854 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3855 inspect.unwrap(func2)
3856
3857 def test_unhashable(self):
3858 def func(): pass
3859 func.__wrapped__ = None
3860 class C:
3861 __hash__ = None
3862 __wrapped__ = func
3863 self.assertIsNone(inspect.unwrap(C()))
3864
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003865 def test_recursion_limit(self):
3866 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3867 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3868 inspect.unwrap(obj)
3869
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003870class TestMain(unittest.TestCase):
3871 def test_only_source(self):
3872 module = importlib.import_module('unittest')
3873 rc, out, err = assert_python_ok('-m', 'inspect',
3874 'unittest')
3875 lines = out.decode().splitlines()
3876 # ignore the final newline
3877 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3878 self.assertEqual(err, b'')
3879
Yury Selivanov42407ab2014-06-23 10:23:50 -07003880 def test_custom_getattr(self):
3881 def foo():
3882 pass
3883 foo.__signature__ = 42
3884 with self.assertRaises(TypeError):
3885 inspect.signature(foo)
3886
Brett Cannon634a8fc2013-10-02 10:25:42 -04003887 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003888 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003889 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003890 rc, out, err = assert_python_ok('-m', 'inspect',
3891 'concurrent.futures:ThreadPoolExecutor')
3892 lines = out.decode().splitlines()
3893 # ignore the final newline
3894 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003895 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003896 self.assertEqual(err, b'')
3897
3898 def test_builtins(self):
3899 module = importlib.import_module('unittest')
3900 _, out, err = assert_python_failure('-m', 'inspect',
3901 'sys')
3902 lines = err.decode().splitlines()
3903 self.assertEqual(lines, ["Can't get info for builtin modules."])
3904
3905 def test_details(self):
3906 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003907 args = support.optim_args_from_interpreter_flags()
3908 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003909 'unittest', '--details')
3910 output = out.decode()
3911 # Just a quick sanity check on the output
3912 self.assertIn(module.__name__, output)
3913 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003914 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003915 self.assertEqual(err, b'')
3916
3917
Yury Selivanovef1e7502014-12-08 16:05:34 -05003918class TestReload(unittest.TestCase):
3919
3920 src_before = textwrap.dedent("""\
3921def foo():
3922 print("Bla")
3923 """)
3924
3925 src_after = textwrap.dedent("""\
3926def foo():
3927 print("Oh no!")
3928 """)
3929
3930 def assertInspectEqual(self, path, source):
3931 inspected_src = inspect.getsource(source)
3932 with open(path) as src:
3933 self.assertEqual(
3934 src.read().splitlines(True),
3935 inspected_src.splitlines(True)
3936 )
3937
3938 def test_getsource_reload(self):
3939 # see issue 1218234
3940 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3941 module = importlib.import_module(name)
3942 self.assertInspectEqual(path, module)
3943 with open(path, 'w') as src:
3944 src.write(self.src_after)
3945 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003946
Nick Coghlane8c45d62013-07-28 20:00:01 +10003947
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003948def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003949 run_unittest(
3950 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3951 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3952 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003953 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003954 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003955 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04003956 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003957 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07003958 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00003959 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003960
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003961if __name__ == "__main__":
3962 test_main()