blob: 83a5f7ec1f5385d58eab68e5875764f39a329499 [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):
Xtreak6d0b7472019-05-30 17:31:39 +0530753 with self.assertWarns(DeprecationWarning):
754 args, varargs, varkw, defaults = inspect.getargspec(routine)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500755 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:
Xtreak6d0b7472019-05-30 17:31:39 +0530760 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 Galindoaee19f52019-05-16 21:08:15 +0100769 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
770 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000771 self.assertEqual(args, args_e)
772 self.assertEqual(varargs, varargs_e)
773 self.assertEqual(varkw, varkw_e)
774 self.assertEqual(defaults, defaults_e)
775 self.assertEqual(kwonlyargs, kwonlyargs_e)
776 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
777 self.assertEqual(ann, ann_e)
778 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530779 with self.assertWarns(DeprecationWarning):
780 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
781 kwonlyargs, kwonlydefaults, ann),
782 formatted)
Christian Heimes3795b532007-11-08 13:48:53 +0000783
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500784 def test_getargspec(self):
785 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
786
Pablo Galindod5d2b452019-04-30 02:01:14 +0100787 self.assertArgSpecEquals(mod.spam,
788 ['a', 'b', 'c', 'd', 'e', 'f'],
789 'g', 'h', (3, 4, 5),
790 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500791
792 self.assertRaises(ValueError, self.assertArgSpecEquals,
793 mod2.keyworded, [])
794
795 self.assertRaises(ValueError, self.assertArgSpecEquals,
796 mod2.annotated, [])
797 self.assertRaises(ValueError, self.assertArgSpecEquals,
798 mod2.keyword_only_arg, [])
799
800
Christian Heimes3795b532007-11-08 13:48:53 +0000801 def test_getfullargspec(self):
802 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
803 kwonlyargs_e=['arg2'],
804 kwonlydefaults_e={'arg2':1},
805 formatted='(*arg1, arg2=1)')
806
807 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000808 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000809 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000810 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
811 kwonlyargs_e=['arg'],
812 formatted='(*, arg)')
813
Pablo Galindod5d2b452019-04-30 02:01:14 +0100814 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100815 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100816 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100817
818 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100819 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100820 varargs_e='args',
821 varkw_e='kwargs',
822 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100823 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100824
Pablo Galindod5d2b452019-04-30 02:01:14 +0100825 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100826 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100827 kwonlyargs_e=['e', 'f'],
828 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100829 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100830
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500831 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500832 # Issue 20684: low level introspection API must ignore __wrapped__
833 @functools.wraps(mod.spam)
834 def ham(x, y):
835 pass
836 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500837 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500838 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
839 self.assertFullArgSpecEquals(functools.partial(ham),
840 ['x', 'y'], formatted='(x, y)')
841 # Other variants
842 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500843 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
844 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500845 class C:
846 @functools.wraps(mod.spam)
847 def ham(self, x, y):
848 pass
849 pham = functools.partialmethod(ham)
850 @functools.wraps(mod.spam)
851 def __call__(self, x, y):
852 pass
853 check_method(C())
854 check_method(C.ham)
855 check_method(C().ham)
856 check_method(C.pham)
857 check_method(C().pham)
858
859 class C_new:
860 @functools.wraps(mod.spam)
861 def __new__(self, x, y):
862 pass
863 check_method(C_new)
864
865 class C_init:
866 @functools.wraps(mod.spam)
867 def __init__(self, x, y):
868 pass
869 check_method(C_init)
870
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500871 def test_getfullargspec_signature_attr(self):
872 def test():
873 pass
874 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
875 test.__signature__ = inspect.Signature(parameters=(spam_param,))
876
Pablo Galindod5d2b452019-04-30 02:01:14 +0100877 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500878
Yury Selivanov4cb93912014-01-29 11:54:12 -0500879 def test_getfullargspec_signature_annos(self):
880 def test(a:'spam') -> 'ham': pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100881 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500882 self.assertEqual(test.__annotations__, spec.annotations)
883
884 def test(): pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100885 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500886 self.assertEqual(test.__annotations__, spec.annotations)
887
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500888 @unittest.skipIf(MISSING_C_DOCSTRINGS,
889 "Signature information for builtins requires docstrings")
890 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100891 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
892 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500893
Pablo Galindod5d2b452019-04-30 02:01:14 +0100894 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
895 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500896
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500897 self.assertFullArgSpecEquals(
898 os.stat,
899 args_e=['path'],
900 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
901 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
902 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
903
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200904 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500905 @unittest.skipIf(MISSING_C_DOCSTRINGS,
906 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800907 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200908 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500909 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindoaee19f52019-05-16 21:08:15 +0100910 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500911 self.assertEqual(spec.defaults[0], 'avocado')
912
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200913 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500914 @unittest.skipIf(MISSING_C_DOCSTRINGS,
915 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800916 def test_getfullargspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200917 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500918 builtin = _testcapi.docstring_no_signature
Pablo Galindoaee19f52019-05-16 21:08:15 +0100919 with self.assertRaises(TypeError):
920 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000921
larryhastingsf36ba122018-01-28 11:13:09 -0800922 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
923 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindoaee19f52019-05-16 21:08:15 +0100924 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800925 l = list(signature.kwonlyargs)
926 sorted_l = sorted(l)
927 self.assertTrue(l)
928 self.assertEqual(l, sorted_l)
Pablo Galindoaee19f52019-05-16 21:08:15 +0100929 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800930 l = list(signature.kwonlyargs)
931 self.assertEqual(l, unsorted_keyword_only_parameters)
932
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500933 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000934 class A(object):
935 def m(self):
936 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500937 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000938
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000939 def test_classify_newstyle(self):
940 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000941
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000942 def s(): pass
943 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000944
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000945 def c(cls): pass
946 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000947
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000948 def getp(self): pass
949 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000950
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000951 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000952
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000953 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000954
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000955 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000956
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100957 dd = _BrokenDataDescriptor()
958 md = _BrokenMethodDescriptor()
959
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000960 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500961
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +0200962 self.assertIn(('__new__', 'static method', object), attrs,
963 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500964 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
965
Benjamin Peterson577473f2010-01-19 00:09:57 +0000966 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
967 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
968 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000969 self.assertIn(('m', 'method', A), attrs,
970 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000971 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
972 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100973 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
974 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000975
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000976 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000977
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000978 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000979
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000980 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000981 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
982 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
983 self.assertIn(('p', 'property', A), attrs, 'missing property')
984 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
985 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
986 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100987 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
988 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000989
990
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000991 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000992
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000993 def m(self): pass
994 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000995
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000996 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000997 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
998 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
999 self.assertIn(('p', 'property', A), attrs, 'missing property')
1000 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
1001 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1002 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001003 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1004 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001005
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001006 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001007
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001008 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001009
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001010 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001011 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1012 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1013 self.assertIn(('p', 'property', A), attrs, 'missing property')
1014 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1015 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1016 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001017 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1018 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1019
1020 def test_classify_builtin_types(self):
1021 # Simple sanity check that all built-in types can have their
1022 # attributes classified.
1023 for name in dir(__builtins__):
1024 builtin = getattr(__builtins__, name)
1025 if isinstance(builtin, type):
1026 inspect.classify_class_attrs(builtin)
1027
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001028 attrs = attrs_wo_objs(bool)
1029 self.assertIn(('__new__', 'static method', bool), attrs,
1030 'missing __new__')
1031 self.assertIn(('from_bytes', 'class method', int), attrs,
1032 'missing class method')
1033 self.assertIn(('to_bytes', 'method', int), attrs,
1034 'missing plain method')
1035 self.assertIn(('__add__', 'method', int), attrs,
1036 'missing plain method')
1037 self.assertIn(('__and__', 'method', bool), attrs,
1038 'missing plain method')
1039
Ethan Furman63c141c2013-10-18 00:27:39 -07001040 def test_classify_DynamicClassAttribute(self):
1041 class Meta(type):
1042 def __getattr__(self, name):
1043 if name == 'ham':
1044 return 'spam'
1045 return super().__getattr__(name)
1046 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001047 @types.DynamicClassAttribute
1048 def ham(self):
1049 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001050 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1051 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001052 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001053 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1054
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001055 def test_classify_overrides_bool(self):
1056 class NoBool(object):
1057 def __eq__(self, other):
1058 return NoBool()
1059
1060 def __bool__(self):
1061 raise NotImplementedError(
1062 "This object does not specify a boolean value")
1063
1064 class HasNB(object):
1065 dd = NoBool()
1066
1067 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1068 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1069
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001070 def test_classify_metaclass_class_attribute(self):
1071 class Meta(type):
1072 fish = 'slap'
1073 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001074 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001075 class Class(metaclass=Meta):
1076 pass
1077 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1078 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1079
Ethan Furman63c141c2013-10-18 00:27:39 -07001080 def test_classify_VirtualAttribute(self):
1081 class Meta(type):
1082 def __dir__(cls):
1083 return ['__class__', '__module__', '__name__', 'BOOM']
1084 def __getattr__(self, name):
1085 if name =='BOOM':
1086 return 42
1087 return super().__getattr(name)
1088 class Class(metaclass=Meta):
1089 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001090 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001091 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1092
1093 def test_classify_VirtualAttribute_multi_classes(self):
1094 class Meta1(type):
1095 def __dir__(cls):
1096 return ['__class__', '__module__', '__name__', 'one']
1097 def __getattr__(self, name):
1098 if name =='one':
1099 return 1
1100 return super().__getattr__(name)
1101 class Meta2(type):
1102 def __dir__(cls):
1103 return ['__class__', '__module__', '__name__', 'two']
1104 def __getattr__(self, name):
1105 if name =='two':
1106 return 2
1107 return super().__getattr__(name)
1108 class Meta3(Meta1, Meta2):
1109 def __dir__(cls):
1110 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1111 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1112 def __getattr__(self, name):
1113 if name =='three':
1114 return 3
1115 return super().__getattr__(name)
1116 class Class1(metaclass=Meta1):
1117 pass
1118 class Class2(Class1, metaclass=Meta3):
1119 pass
1120
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001121 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1122 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1123 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001124 cca = inspect.classify_class_attrs(Class2)
1125 for sf in (should_find1, should_find2, should_find3):
1126 self.assertIn(sf, cca)
1127
1128 def test_classify_class_attrs_with_buggy_dir(self):
1129 class M(type):
1130 def __dir__(cls):
1131 return ['__class__', '__name__', 'missing']
1132 class C(metaclass=M):
1133 pass
1134 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1135 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001136
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001137 def test_getmembers_descriptors(self):
1138 class A(object):
1139 dd = _BrokenDataDescriptor()
1140 md = _BrokenMethodDescriptor()
1141
1142 def pred_wrapper(pred):
1143 # A quick'n'dirty way to discard standard attributes of new-style
1144 # classes.
1145 class Empty(object):
1146 pass
1147 def wrapped(x):
1148 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1149 return False
1150 return pred(x)
1151 return wrapped
1152
1153 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1154 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1155
1156 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1157 [('md', A.__dict__['md'])])
1158 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1159 [('dd', A.__dict__['dd'])])
1160
1161 class B(A):
1162 pass
1163
1164 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1165 [('md', A.__dict__['md'])])
1166 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1167 [('dd', A.__dict__['dd'])])
1168
Antoine Pitrou0c603812012-01-18 17:40:18 +01001169 def test_getmembers_method(self):
1170 class B:
1171 def f(self):
1172 pass
1173
1174 self.assertIn(('f', B.f), inspect.getmembers(B))
1175 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1176 b = B()
1177 self.assertIn(('f', b.f), inspect.getmembers(b))
1178 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1179
Ethan Furmane03ea372013-09-25 07:14:41 -07001180 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001181 class M(type):
1182 def __getattr__(cls, name):
1183 if name == 'eggs':
1184 return 'scrambled'
1185 return super().__getattr__(name)
1186 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001187 @types.DynamicClassAttribute
1188 def eggs(self):
1189 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001190 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1191 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1192
1193 def test_getmembers_with_buggy_dir(self):
1194 class M(type):
1195 def __dir__(cls):
1196 return ['__class__', '__name__', 'missing']
1197 class C(metaclass=M):
1198 pass
1199 attrs = [a[0] for a in inspect.getmembers(C)]
1200 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001201
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001202class TestIsDataDescriptor(unittest.TestCase):
1203
1204 def test_custom_descriptors(self):
1205 class NonDataDescriptor:
1206 def __get__(self, value, type=None): pass
1207 class DataDescriptor0:
1208 def __set__(self, name, value): pass
1209 class DataDescriptor1:
1210 def __delete__(self, name): pass
1211 class DataDescriptor2:
1212 __set__ = None
1213 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1214 'class with only __get__ not a data descriptor')
1215 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1216 'class with __set__ is a data descriptor')
1217 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1218 'class with __delete__ is a data descriptor')
1219 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1220 'class with __set__ = None is a data descriptor')
1221
1222 def test_slot(self):
1223 class Slotted:
1224 __slots__ = 'foo',
1225 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1226 'a slot is a data descriptor')
1227
1228 def test_property(self):
1229 class Propertied:
1230 @property
1231 def a_property(self):
1232 pass
1233 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1234 'a property is a data descriptor')
1235
1236 def test_functions(self):
1237 class Test(object):
1238 def instance_method(self): pass
1239 @classmethod
1240 def class_method(cls): pass
1241 @staticmethod
1242 def static_method(): pass
1243 def function():
1244 pass
1245 a_lambda = lambda: None
1246 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1247 'a instance method is not a data descriptor')
1248 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1249 'a class method is not a data descriptor')
1250 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1251 'a static method is not a data descriptor')
1252 self.assertFalse(inspect.isdatadescriptor(function),
1253 'a function is not a data descriptor')
1254 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1255 'a lambda is not a data descriptor')
1256
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001257
Nick Coghlan2f92e542012-06-23 19:39:55 +10001258_global_ref = object()
1259class TestGetClosureVars(unittest.TestCase):
1260
1261 def test_name_resolution(self):
1262 # Basic test of the 4 different resolution mechanisms
1263 def f(nonlocal_ref):
1264 def g(local_ref):
1265 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1266 return g
1267 _arg = object()
1268 nonlocal_vars = {"nonlocal_ref": _arg}
1269 global_vars = {"_global_ref": _global_ref}
1270 builtin_vars = {"print": print}
1271 unbound_names = {"unbound_ref"}
1272 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1273 builtin_vars, unbound_names)
1274 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1275
1276 def test_generator_closure(self):
1277 def f(nonlocal_ref):
1278 def g(local_ref):
1279 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1280 yield
1281 return g
1282 _arg = object()
1283 nonlocal_vars = {"nonlocal_ref": _arg}
1284 global_vars = {"_global_ref": _global_ref}
1285 builtin_vars = {"print": print}
1286 unbound_names = {"unbound_ref"}
1287 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1288 builtin_vars, unbound_names)
1289 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1290
1291 def test_method_closure(self):
1292 class C:
1293 def f(self, nonlocal_ref):
1294 def g(local_ref):
1295 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1296 return g
1297 _arg = object()
1298 nonlocal_vars = {"nonlocal_ref": _arg}
1299 global_vars = {"_global_ref": _global_ref}
1300 builtin_vars = {"print": print}
1301 unbound_names = {"unbound_ref"}
1302 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1303 builtin_vars, unbound_names)
1304 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1305
1306 def test_nonlocal_vars(self):
1307 # More complex tests of nonlocal resolution
1308 def _nonlocal_vars(f):
1309 return inspect.getclosurevars(f).nonlocals
1310
1311 def make_adder(x):
1312 def add(y):
1313 return x + y
1314 return add
1315
1316 def curry(func, arg1):
1317 return lambda arg2: func(arg1, arg2)
1318
1319 def less_than(a, b):
1320 return a < b
1321
1322 # The infamous Y combinator.
1323 def Y(le):
1324 def g(f):
1325 return le(lambda x: f(f)(x))
1326 Y.g_ref = g
1327 return g(g)
1328
1329 def check_y_combinator(func):
1330 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1331
1332 inc = make_adder(1)
1333 add_two = make_adder(2)
1334 greater_than_five = curry(less_than, 5)
1335
1336 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1337 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1338 self.assertEqual(_nonlocal_vars(greater_than_five),
1339 {'arg1': 5, 'func': less_than})
1340 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1341 {'x': 3})
1342 Y(check_y_combinator)
1343
1344 def test_getclosurevars_empty(self):
1345 def foo(): pass
1346 _empty = inspect.ClosureVars({}, {}, {}, set())
1347 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1348 self.assertEqual(inspect.getclosurevars(foo), _empty)
1349
1350 def test_getclosurevars_error(self):
1351 class T: pass
1352 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1353 self.assertRaises(TypeError, inspect.getclosurevars, list)
1354 self.assertRaises(TypeError, inspect.getclosurevars, {})
1355
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001356 def _private_globals(self):
1357 code = """def f(): print(path)"""
1358 ns = {}
1359 exec(code, ns)
1360 return ns["f"], ns
1361
1362 def test_builtins_fallback(self):
1363 f, ns = self._private_globals()
1364 ns.pop("__builtins__", None)
1365 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1366 self.assertEqual(inspect.getclosurevars(f), expected)
1367
1368 def test_builtins_as_dict(self):
1369 f, ns = self._private_globals()
1370 ns["__builtins__"] = {"path":1}
1371 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1372 self.assertEqual(inspect.getclosurevars(f), expected)
1373
1374 def test_builtins_as_module(self):
1375 f, ns = self._private_globals()
1376 ns["__builtins__"] = os
1377 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1378 self.assertEqual(inspect.getclosurevars(f), expected)
1379
Nick Coghlan2f92e542012-06-23 19:39:55 +10001380
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001381class TestGetcallargsFunctions(unittest.TestCase):
1382
1383 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1384 locs = dict(locs or {}, func=func)
1385 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001386 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1387 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001388 self.assertEqual(r1, r2)
1389
1390 def assertEqualException(self, func, call_param_string, locs=None):
1391 locs = dict(locs or {}, func=func)
1392 try:
1393 eval('func(%s)' % call_param_string, None, locs)
1394 except Exception as e:
1395 ex1 = e
1396 else:
1397 self.fail('Exception not raised')
1398 try:
Pablo Galindoaee19f52019-05-16 21:08:15 +01001399 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1400 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001401 except Exception as e:
1402 ex2 = e
1403 else:
1404 self.fail('Exception not raised')
1405 self.assertIs(type(ex1), type(ex2))
1406 self.assertEqual(str(ex1), str(ex2))
1407 del ex1, ex2
1408
1409 def makeCallable(self, signature):
1410 """Create a function that returns its locals()"""
1411 code = "lambda %s: locals()"
1412 return eval(code % signature)
1413
1414 def test_plain(self):
1415 f = self.makeCallable('a, b=1')
1416 self.assertEqualCallArgs(f, '2')
1417 self.assertEqualCallArgs(f, '2, 3')
1418 self.assertEqualCallArgs(f, 'a=2')
1419 self.assertEqualCallArgs(f, 'b=3, a=2')
1420 self.assertEqualCallArgs(f, '2, b=3')
1421 # expand *iterable / **mapping
1422 self.assertEqualCallArgs(f, '*(2,)')
1423 self.assertEqualCallArgs(f, '*[2]')
1424 self.assertEqualCallArgs(f, '*(2, 3)')
1425 self.assertEqualCallArgs(f, '*[2, 3]')
1426 self.assertEqualCallArgs(f, '**{"a":2}')
1427 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1428 self.assertEqualCallArgs(f, '2, **{"b":3}')
1429 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1430 # expand UserList / UserDict
1431 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1432 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1433 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1434 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1435 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1436
1437 def test_varargs(self):
1438 f = self.makeCallable('a, b=1, *c')
1439 self.assertEqualCallArgs(f, '2')
1440 self.assertEqualCallArgs(f, '2, 3')
1441 self.assertEqualCallArgs(f, '2, 3, 4')
1442 self.assertEqualCallArgs(f, '*(2,3,4)')
1443 self.assertEqualCallArgs(f, '2, *[3,4]')
1444 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1445
1446 def test_varkw(self):
1447 f = self.makeCallable('a, b=1, **c')
1448 self.assertEqualCallArgs(f, 'a=2')
1449 self.assertEqualCallArgs(f, '2, b=3, c=4')
1450 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1451 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1452 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1453 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1454 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1455 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1456 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1457
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001458 def test_varkw_only(self):
1459 # issue11256:
1460 f = self.makeCallable('**c')
1461 self.assertEqualCallArgs(f, '')
1462 self.assertEqualCallArgs(f, 'a=1')
1463 self.assertEqualCallArgs(f, 'a=1, b=2')
1464 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1465 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1466 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1467
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001468 def test_keyword_only(self):
1469 f = self.makeCallable('a=3, *, c, d=2')
1470 self.assertEqualCallArgs(f, 'c=3')
1471 self.assertEqualCallArgs(f, 'c=3, a=3')
1472 self.assertEqualCallArgs(f, 'a=2, c=4')
1473 self.assertEqualCallArgs(f, '4, c=4')
1474 self.assertEqualException(f, '')
1475 self.assertEqualException(f, '3')
1476 self.assertEqualException(f, 'a=3')
1477 self.assertEqualException(f, 'd=4')
1478
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001479 f = self.makeCallable('*, c, d=2')
1480 self.assertEqualCallArgs(f, 'c=3')
1481 self.assertEqualCallArgs(f, 'c=3, d=4')
1482 self.assertEqualCallArgs(f, 'd=4, c=3')
1483
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001484 def test_multiple_features(self):
1485 f = self.makeCallable('a, b=2, *f, **g')
1486 self.assertEqualCallArgs(f, '2, 3, 7')
1487 self.assertEqualCallArgs(f, '2, 3, x=8')
1488 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1489 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1490 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1491 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1492 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1493 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1494 '(4,[5,6])]), **collections.UserDict('
1495 'y=9, z=10)')
1496
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001497 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1498 self.assertEqualCallArgs(f, '2, 3, x=8')
1499 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1500 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1501 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1502 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1503 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1504 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1505 '(4,[5,6])]), q=0, **collections.UserDict('
1506 'y=9, z=10)')
1507
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001508 def test_errors(self):
1509 f0 = self.makeCallable('')
1510 f1 = self.makeCallable('a, b')
1511 f2 = self.makeCallable('a, b=1')
1512 # f0 takes no arguments
1513 self.assertEqualException(f0, '1')
1514 self.assertEqualException(f0, 'x=1')
1515 self.assertEqualException(f0, '1,x=1')
1516 # f1 takes exactly 2 arguments
1517 self.assertEqualException(f1, '')
1518 self.assertEqualException(f1, '1')
1519 self.assertEqualException(f1, 'a=2')
1520 self.assertEqualException(f1, 'b=3')
1521 # f2 takes at least 1 argument
1522 self.assertEqualException(f2, '')
1523 self.assertEqualException(f2, 'b=3')
1524 for f in f1, f2:
1525 # f1/f2 takes exactly/at most 2 arguments
1526 self.assertEqualException(f, '2, 3, 4')
1527 self.assertEqualException(f, '1, 2, 3, a=1')
1528 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001529 # XXX: success of this one depends on dict order
1530 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001531 # f got an unexpected keyword argument
1532 self.assertEqualException(f, 'c=2')
1533 self.assertEqualException(f, '2, c=3')
1534 self.assertEqualException(f, '2, 3, c=4')
1535 self.assertEqualException(f, '2, c=4, b=3')
1536 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1537 # f got multiple values for keyword argument
1538 self.assertEqualException(f, '1, a=2')
1539 self.assertEqualException(f, '1, **{"a":2}')
1540 self.assertEqualException(f, '1, 2, b=3')
1541 # XXX: Python inconsistency
1542 # - for functions and bound methods: unexpected keyword 'c'
1543 # - for unbound methods: multiple values for keyword 'a'
1544 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001545 # issue11256:
1546 f3 = self.makeCallable('**c')
1547 self.assertEqualException(f3, '1, 2')
1548 self.assertEqualException(f3, '1, 2, a=1, b=2')
1549 f4 = self.makeCallable('*, a, b=0')
1550 self.assertEqualException(f3, '1, 2')
1551 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001552
Yury Selivanov875df202014-03-27 18:23:03 -04001553 # issue #20816: getcallargs() fails to iterate over non-existent
1554 # kwonlydefaults and raises a wrong TypeError
1555 def f5(*, a): pass
1556 with self.assertRaisesRegex(TypeError,
1557 'missing 1 required keyword-only'):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001558 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001559
1560
Yury Selivanovdccfa132014-03-27 18:42:52 -04001561 # issue20817:
1562 def f6(a, b, c):
1563 pass
1564 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001565 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001566
Dong-hee Naa9cab432018-05-30 00:04:08 +09001567 # bpo-33197
1568 with self.assertRaisesRegex(ValueError,
1569 'variadic keyword parameters cannot'
1570 ' have default values'):
1571 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1572 default=42)
1573 with self.assertRaisesRegex(ValueError,
1574 "value 5 is not a valid Parameter.kind"):
1575 inspect.Parameter("bar", kind=5, default=42)
1576
1577 with self.assertRaisesRegex(TypeError,
1578 'name must be a str, not a int'):
1579 inspect.Parameter(123, kind=4)
1580
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001581class TestGetcallargsMethods(TestGetcallargsFunctions):
1582
1583 def setUp(self):
1584 class Foo(object):
1585 pass
1586 self.cls = Foo
1587 self.inst = Foo()
1588
1589 def makeCallable(self, signature):
1590 assert 'self' not in signature
1591 mk = super(TestGetcallargsMethods, self).makeCallable
1592 self.cls.method = mk('self, ' + signature)
1593 return self.inst.method
1594
1595class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1596
1597 def makeCallable(self, signature):
1598 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1599 return self.cls.method
1600
1601 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1602 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1603 *self._getAssertEqualParams(func, call_params_string, locs))
1604
1605 def assertEqualException(self, func, call_params_string, locs=None):
1606 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1607 *self._getAssertEqualParams(func, call_params_string, locs))
1608
1609 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1610 assert 'inst' not in call_params_string
1611 locs = dict(locs or {}, inst=self.inst)
1612 return (func, 'inst,' + call_params_string, locs)
1613
Michael Foord95fc51d2010-11-20 15:07:30 +00001614
1615class TestGetattrStatic(unittest.TestCase):
1616
1617 def test_basic(self):
1618 class Thing(object):
1619 x = object()
1620
1621 thing = Thing()
1622 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1623 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1624 with self.assertRaises(AttributeError):
1625 inspect.getattr_static(thing, 'y')
1626
1627 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1628
1629 def test_inherited(self):
1630 class Thing(object):
1631 x = object()
1632 class OtherThing(Thing):
1633 pass
1634
1635 something = OtherThing()
1636 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1637
1638 def test_instance_attr(self):
1639 class Thing(object):
1640 x = 2
1641 def __init__(self, x):
1642 self.x = x
1643 thing = Thing(3)
1644 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1645 del thing.x
1646 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1647
1648 def test_property(self):
1649 class Thing(object):
1650 @property
1651 def x(self):
1652 raise AttributeError("I'm pretending not to exist")
1653 thing = Thing()
1654 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1655
Ezio Melotti75cbd732011-04-28 00:59:29 +03001656 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001657 class descriptor(object):
1658 def __get__(*_):
1659 raise AttributeError("I'm pretending not to exist")
1660 desc = descriptor()
1661 class Thing(object):
1662 x = desc
1663 thing = Thing()
1664 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1665
1666 def test_classAttribute(self):
1667 class Thing(object):
1668 x = object()
1669
1670 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1671
Ethan Furmane03ea372013-09-25 07:14:41 -07001672 def test_classVirtualAttribute(self):
1673 class Thing(object):
1674 @types.DynamicClassAttribute
1675 def x(self):
1676 return self._x
1677 _x = object()
1678
1679 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1680
Michael Foord95fc51d2010-11-20 15:07:30 +00001681 def test_inherited_classattribute(self):
1682 class Thing(object):
1683 x = object()
1684 class OtherThing(Thing):
1685 pass
1686
1687 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1688
1689 def test_slots(self):
1690 class Thing(object):
1691 y = 'bar'
1692 __slots__ = ['x']
1693 def __init__(self):
1694 self.x = 'foo'
1695 thing = Thing()
1696 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1697 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1698
1699 del thing.x
1700 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1701
1702 def test_metaclass(self):
1703 class meta(type):
1704 attr = 'foo'
1705 class Thing(object, metaclass=meta):
1706 pass
1707 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1708
1709 class sub(meta):
1710 pass
1711 class OtherThing(object, metaclass=sub):
1712 x = 3
1713 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1714
1715 class OtherOtherThing(OtherThing):
1716 pass
1717 # this test is odd, but it was added as it exposed a bug
1718 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1719
1720 def test_no_dict_no_slots(self):
1721 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1722 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1723
1724 def test_no_dict_no_slots_instance_member(self):
1725 # returns descriptor
1726 with open(__file__) as handle:
1727 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1728
1729 def test_inherited_slots(self):
1730 # returns descriptor
1731 class Thing(object):
1732 __slots__ = ['x']
1733 def __init__(self):
1734 self.x = 'foo'
1735
1736 class OtherThing(Thing):
1737 pass
1738 # it would be nice if this worked...
1739 # we get the descriptor instead of the instance attribute
1740 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1741
1742 def test_descriptor(self):
1743 class descriptor(object):
1744 def __get__(self, instance, owner):
1745 return 3
1746 class Foo(object):
1747 d = descriptor()
1748
1749 foo = Foo()
1750
1751 # for a non data descriptor we return the instance attribute
1752 foo.__dict__['d'] = 1
1753 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1754
Mike53f7a7c2017-12-14 14:04:53 +03001755 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001756 # descriptor
1757 descriptor.__set__ = lambda s, i, v: None
1758 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1759
1760
1761 def test_metaclass_with_descriptor(self):
1762 class descriptor(object):
1763 def __get__(self, instance, owner):
1764 return 3
1765 class meta(type):
1766 d = descriptor()
1767 class Thing(object, metaclass=meta):
1768 pass
1769 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1770
1771
Michael Foordcc7ebb82010-11-20 16:20:16 +00001772 def test_class_as_property(self):
1773 class Base(object):
1774 foo = 3
1775
1776 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001777 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001778 @property
1779 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001780 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001781 return object
1782
Michael Foord35184ed2010-11-20 16:58:30 +00001783 instance = Something()
1784 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1785 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001786 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1787
Michael Foorde5162652010-11-20 16:40:44 +00001788 def test_mro_as_property(self):
1789 class Meta(type):
1790 @property
1791 def __mro__(self):
1792 return (object,)
1793
1794 class Base(object):
1795 foo = 3
1796
1797 class Something(Base, metaclass=Meta):
1798 pass
1799
1800 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1801 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1802
Michael Foorddcebe0f2011-03-15 19:20:44 -04001803 def test_dict_as_property(self):
1804 test = self
1805 test.called = False
1806
1807 class Foo(dict):
1808 a = 3
1809 @property
1810 def __dict__(self):
1811 test.called = True
1812 return {}
1813
1814 foo = Foo()
1815 foo.a = 4
1816 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1817 self.assertFalse(test.called)
1818
1819 def test_custom_object_dict(self):
1820 test = self
1821 test.called = False
1822
1823 class Custom(dict):
1824 def get(self, key, default=None):
1825 test.called = True
1826 super().get(key, default)
1827
1828 class Foo(object):
1829 a = 3
1830 foo = Foo()
1831 foo.__dict__ = Custom()
1832 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1833 self.assertFalse(test.called)
1834
1835 def test_metaclass_dict_as_property(self):
1836 class Meta(type):
1837 @property
1838 def __dict__(self):
1839 self.executed = True
1840
1841 class Thing(metaclass=Meta):
1842 executed = False
1843
1844 def __init__(self):
1845 self.spam = 42
1846
1847 instance = Thing()
1848 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1849 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001850
Michael Foorda51623b2011-12-18 22:01:40 +00001851 def test_module(self):
1852 sentinel = object()
1853 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1854 sentinel)
1855
Michael Foord3ba95f82011-12-22 01:13:37 +00001856 def test_metaclass_with_metaclass_with_dict_as_property(self):
1857 class MetaMeta(type):
1858 @property
1859 def __dict__(self):
1860 self.executed = True
1861 return dict(spam=42)
1862
1863 class Meta(type, metaclass=MetaMeta):
1864 executed = False
1865
1866 class Thing(metaclass=Meta):
1867 pass
1868
1869 with self.assertRaises(AttributeError):
1870 inspect.getattr_static(Thing, "spam")
1871 self.assertFalse(Thing.executed)
1872
Nick Coghlane0f04652010-11-21 03:44:04 +00001873class TestGetGeneratorState(unittest.TestCase):
1874
1875 def setUp(self):
1876 def number_generator():
1877 for number in range(5):
1878 yield number
1879 self.generator = number_generator()
1880
1881 def _generatorstate(self):
1882 return inspect.getgeneratorstate(self.generator)
1883
1884 def test_created(self):
1885 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1886
1887 def test_suspended(self):
1888 next(self.generator)
1889 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1890
1891 def test_closed_after_exhaustion(self):
1892 for i in self.generator:
1893 pass
1894 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1895
1896 def test_closed_after_immediate_exception(self):
1897 with self.assertRaises(RuntimeError):
1898 self.generator.throw(RuntimeError)
1899 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1900
1901 def test_running(self):
1902 # As mentioned on issue #10220, checking for the RUNNING state only
1903 # makes sense inside the generator itself.
1904 # The following generator checks for this by using the closure's
1905 # reference to self and the generator state checking helper method
1906 def running_check_generator():
1907 for number in range(5):
1908 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1909 yield number
1910 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1911 self.generator = running_check_generator()
1912 # Running up to the first yield
1913 next(self.generator)
1914 # Running after the first yield
1915 next(self.generator)
1916
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001917 def test_easy_debugging(self):
1918 # repr() and str() of a generator state should contain the state name
1919 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1920 for name in names:
1921 state = getattr(inspect, name)
1922 self.assertIn(name, repr(state))
1923 self.assertIn(name, str(state))
1924
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001925 def test_getgeneratorlocals(self):
1926 def each(lst, a=None):
1927 b=(1, 2, 3)
1928 for v in lst:
1929 if v == 3:
1930 c = 12
1931 yield v
1932
1933 numbers = each([1, 2, 3])
1934 self.assertEqual(inspect.getgeneratorlocals(numbers),
1935 {'a': None, 'lst': [1, 2, 3]})
1936 next(numbers)
1937 self.assertEqual(inspect.getgeneratorlocals(numbers),
1938 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1939 'b': (1, 2, 3)})
1940 next(numbers)
1941 self.assertEqual(inspect.getgeneratorlocals(numbers),
1942 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1943 'b': (1, 2, 3)})
1944 next(numbers)
1945 self.assertEqual(inspect.getgeneratorlocals(numbers),
1946 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1947 'b': (1, 2, 3), 'c': 12})
1948 try:
1949 next(numbers)
1950 except StopIteration:
1951 pass
1952 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1953
1954 def test_getgeneratorlocals_empty(self):
1955 def yield_one():
1956 yield 1
1957 one = yield_one()
1958 self.assertEqual(inspect.getgeneratorlocals(one), {})
1959 try:
1960 next(one)
1961 except StopIteration:
1962 pass
1963 self.assertEqual(inspect.getgeneratorlocals(one), {})
1964
1965 def test_getgeneratorlocals_error(self):
1966 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1967 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1968 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1969 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1970
Nick Coghlane0f04652010-11-21 03:44:04 +00001971
Yury Selivanov5376ba92015-06-22 12:19:30 -04001972class TestGetCoroutineState(unittest.TestCase):
1973
1974 def setUp(self):
1975 @types.coroutine
1976 def number_coroutine():
1977 for number in range(5):
1978 yield number
1979 async def coroutine():
1980 await number_coroutine()
1981 self.coroutine = coroutine()
1982
1983 def tearDown(self):
1984 self.coroutine.close()
1985
1986 def _coroutinestate(self):
1987 return inspect.getcoroutinestate(self.coroutine)
1988
1989 def test_created(self):
1990 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1991
1992 def test_suspended(self):
1993 self.coroutine.send(None)
1994 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1995
1996 def test_closed_after_exhaustion(self):
1997 while True:
1998 try:
1999 self.coroutine.send(None)
2000 except StopIteration:
2001 break
2002
2003 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2004
2005 def test_closed_after_immediate_exception(self):
2006 with self.assertRaises(RuntimeError):
2007 self.coroutine.throw(RuntimeError)
2008 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2009
2010 def test_easy_debugging(self):
2011 # repr() and str() of a coroutine state should contain the state name
2012 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2013 for name in names:
2014 state = getattr(inspect, name)
2015 self.assertIn(name, repr(state))
2016 self.assertIn(name, str(state))
2017
2018 def test_getcoroutinelocals(self):
2019 @types.coroutine
2020 def gencoro():
2021 yield
2022
2023 gencoro = gencoro()
2024 async def func(a=None):
2025 b = 'spam'
2026 await gencoro
2027
2028 coro = func()
2029 self.assertEqual(inspect.getcoroutinelocals(coro),
2030 {'a': None, 'gencoro': gencoro})
2031 coro.send(None)
2032 self.assertEqual(inspect.getcoroutinelocals(coro),
2033 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2034
2035
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002036class MySignature(inspect.Signature):
2037 # Top-level to make it picklable;
2038 # used in test_signature_object_pickle
2039 pass
2040
2041class MyParameter(inspect.Parameter):
2042 # Top-level to make it picklable;
2043 # used in test_signature_object_pickle
2044 pass
2045
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002046
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002047
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002048class TestSignatureObject(unittest.TestCase):
2049 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002050 def signature(func, **kw):
2051 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002052 return (tuple((param.name,
2053 (... if param.default is param.empty else param.default),
2054 (... if param.annotation is param.empty
2055 else param.annotation),
2056 str(param.kind).lower())
2057 for param in sig.parameters.values()),
2058 (... if sig.return_annotation is sig.empty
2059 else sig.return_annotation))
2060
2061 def test_signature_object(self):
2062 S = inspect.Signature
2063 P = inspect.Parameter
2064
2065 self.assertEqual(str(S()), '()')
2066
Yury Selivanov07a9e452014-01-29 10:58:16 -05002067 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002068 pass
2069 sig = inspect.signature(test)
2070 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002071 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002072 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002073 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002074 args = sig.parameters['args']
2075 ko = sig.parameters['ko']
2076 kwargs = sig.parameters['kwargs']
2077
2078 S((po, pk, args, ko, kwargs))
2079
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002080 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002081 S((pk, po, args, ko, kwargs))
2082
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002083 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002084 S((po, args, pk, ko, kwargs))
2085
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002086 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002087 S((args, po, pk, ko, kwargs))
2088
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002089 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002090 S((po, pk, args, kwargs, ko))
2091
2092 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002093 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002094 S((po, pk, args, kwargs2, ko))
2095
Yury Selivanov07a9e452014-01-29 10:58:16 -05002096 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2097 S((pod, po))
2098
2099 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2100 S((po, pkd, pk))
2101
2102 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2103 S((pkd, pk))
2104
Yury Selivanov374375d2014-03-27 12:41:53 -04002105 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002106 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002107
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002108 def test_signature_object_pickle(self):
2109 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2110 foo_partial = functools.partial(foo, a=1)
2111
2112 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002113
2114 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2115 with self.subTest(pickle_ver=ver, subclass=False):
2116 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2117 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002118
2119 # Test that basic sub-classing works
2120 sig = inspect.signature(foo)
2121 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2122 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2123 mysig = MySignature().replace(parameters=myparams.values(),
2124 return_annotation=sig.return_annotation)
2125 self.assertTrue(isinstance(mysig, MySignature))
2126 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2127
2128 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2129 with self.subTest(pickle_ver=ver, subclass=True):
2130 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2131 self.assertEqual(mysig, sig_pickled)
2132 self.assertTrue(isinstance(sig_pickled, MySignature))
2133 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2134 MyParameter))
2135
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002136 def test_signature_immutability(self):
2137 def test(a):
2138 pass
2139 sig = inspect.signature(test)
2140
2141 with self.assertRaises(AttributeError):
2142 sig.foo = 'bar'
2143
2144 with self.assertRaises(TypeError):
2145 sig.parameters['a'] = None
2146
2147 def test_signature_on_noarg(self):
2148 def test():
2149 pass
2150 self.assertEqual(self.signature(test), ((), ...))
2151
2152 def test_signature_on_wargs(self):
2153 def test(a, b:'foo') -> 123:
2154 pass
2155 self.assertEqual(self.signature(test),
2156 ((('a', ..., ..., "positional_or_keyword"),
2157 ('b', ..., 'foo', "positional_or_keyword")),
2158 123))
2159
2160 def test_signature_on_wkwonly(self):
2161 def test(*, a:float, b:str) -> int:
2162 pass
2163 self.assertEqual(self.signature(test),
2164 ((('a', ..., float, "keyword_only"),
2165 ('b', ..., str, "keyword_only")),
2166 int))
2167
2168 def test_signature_on_complex_args(self):
2169 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2170 pass
2171 self.assertEqual(self.signature(test),
2172 ((('a', ..., ..., "positional_or_keyword"),
2173 ('b', 10, 'foo', "positional_or_keyword"),
2174 ('args', ..., 'bar', "var_positional"),
2175 ('spam', ..., 'baz', "keyword_only"),
2176 ('ham', 123, ..., "keyword_only"),
2177 ('kwargs', ..., int, "var_keyword")),
2178 ...))
2179
Dong-hee Na378d7062017-05-18 04:00:51 +09002180 def test_signature_without_self(self):
2181 def test_args_only(*args): # NOQA
2182 pass
2183
2184 def test_args_kwargs_only(*args, **kwargs): # NOQA
2185 pass
2186
2187 class A:
2188 @classmethod
2189 def test_classmethod(*args): # NOQA
2190 pass
2191
2192 @staticmethod
2193 def test_staticmethod(*args): # NOQA
2194 pass
2195
2196 f1 = functools.partialmethod((test_classmethod), 1)
2197 f2 = functools.partialmethod((test_args_only), 1)
2198 f3 = functools.partialmethod((test_staticmethod), 1)
2199 f4 = functools.partialmethod((test_args_kwargs_only),1)
2200
2201 self.assertEqual(self.signature(test_args_only),
2202 ((('args', ..., ..., 'var_positional'),), ...))
2203 self.assertEqual(self.signature(test_args_kwargs_only),
2204 ((('args', ..., ..., 'var_positional'),
2205 ('kwargs', ..., ..., 'var_keyword')), ...))
2206 self.assertEqual(self.signature(A.f1),
2207 ((('args', ..., ..., 'var_positional'),), ...))
2208 self.assertEqual(self.signature(A.f2),
2209 ((('args', ..., ..., 'var_positional'),), ...))
2210 self.assertEqual(self.signature(A.f3),
2211 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002212 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002213 ((('args', ..., ..., 'var_positional'),
2214 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002215 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002216 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2217 "Signature information for builtins requires docstrings")
2218 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002219 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002220
Larry Hastings5c661892014-01-24 06:17:25 -08002221 def test_unbound_method(o):
2222 """Use this to test unbound methods (things that should have a self)"""
2223 signature = inspect.signature(o)
2224 self.assertTrue(isinstance(signature, inspect.Signature))
2225 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2226 return signature
2227
2228 def test_callable(o):
2229 """Use this to test bound methods or normal callables (things that don't expect self)"""
2230 signature = inspect.signature(o)
2231 self.assertTrue(isinstance(signature, inspect.Signature))
2232 if signature.parameters:
2233 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2234 return signature
2235
2236 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002237 def p(name): return signature.parameters[name].default
2238 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002239 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002240 self.assertEqual(p('d'), 3.14)
2241 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002242 self.assertEqual(p('n'), None)
2243 self.assertEqual(p('t'), True)
2244 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002245 self.assertEqual(p('local'), 3)
2246 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002247 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002248
Larry Hastings5c661892014-01-24 06:17:25 -08002249 test_callable(object)
2250
2251 # normal method
2252 # (PyMethodDescr_Type, "method_descriptor")
2253 test_unbound_method(_pickle.Pickler.dump)
2254 d = _pickle.Pickler(io.StringIO())
2255 test_callable(d.dump)
2256
2257 # static method
2258 test_callable(str.maketrans)
2259 test_callable('abc'.maketrans)
2260
2261 # class method
2262 test_callable(dict.fromkeys)
2263 test_callable({}.fromkeys)
2264
2265 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2266 test_unbound_method(type.__call__)
2267 test_unbound_method(int.__add__)
2268 test_callable((3).__add__)
2269
2270 # _PyMethodWrapper_Type
2271 # support for 'method-wrapper'
2272 test_callable(min.__call__)
2273
Larry Hastings2623c8c2014-02-08 22:15:29 -08002274 # This doesn't work now.
2275 # (We don't have a valid signature for "type" in 3.4)
2276 with self.assertRaisesRegex(ValueError, "no signature found"):
2277 class ThisWorksNow:
2278 __call__ = type
2279 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002280
Yury Selivanov056e2652014-03-02 12:25:27 -05002281 # Regression test for issue #20786
2282 test_unbound_method(dict.__delitem__)
2283 test_unbound_method(property.__delete__)
2284
Zachary Ware8ef887c2015-04-13 18:22:35 -05002285 # Regression test for issue #20586
2286 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2287
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002288 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002289 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2290 "Signature information for builtins requires docstrings")
2291 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002292 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002293 func = _testcapi.docstring_with_signature_with_defaults
2294
2295 def decorator(func):
2296 @functools.wraps(func)
2297 def wrapper(*args, **kwargs) -> int:
2298 return func(*args, **kwargs)
2299 return wrapper
2300
2301 decorated_func = decorator(func)
2302
2303 self.assertEqual(inspect.signature(func),
2304 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002305
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002306 def wrapper_like(*args, **kwargs) -> int: pass
2307 self.assertEqual(inspect.signature(decorated_func,
2308 follow_wrapped=False),
2309 inspect.signature(wrapper_like))
2310
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002311 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002312 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002313 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002314 with self.assertRaisesRegex(ValueError,
2315 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002316 inspect.signature(_testcapi.docstring_no_signature)
2317
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002318 with self.assertRaisesRegex(ValueError,
2319 'no signature found for builtin'):
2320 inspect.signature(str)
2321
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002322 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002323 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002324 inspect.signature(42)
2325
Yury Selivanov63da7c72014-01-31 14:48:37 -05002326 def test_signature_from_functionlike_object(self):
2327 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2328 pass
2329
2330 class funclike:
2331 # Has to be callable, and have correct
2332 # __code__, __annotations__, __defaults__, __name__,
2333 # and __kwdefaults__ attributes
2334
2335 def __init__(self, func):
2336 self.__name__ = func.__name__
2337 self.__code__ = func.__code__
2338 self.__annotations__ = func.__annotations__
2339 self.__defaults__ = func.__defaults__
2340 self.__kwdefaults__ = func.__kwdefaults__
2341 self.func = func
2342
2343 def __call__(self, *args, **kwargs):
2344 return self.func(*args, **kwargs)
2345
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002346 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002347
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002348 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002349 self.assertEqual(sig_funclike, sig_func)
2350
2351 sig_funclike = inspect.signature(funclike(func))
2352 self.assertEqual(sig_funclike, sig_func)
2353
2354 # If object is not a duck type of function, then
2355 # signature will try to get a signature for its '__call__'
2356 # method
2357 fl = funclike(func)
2358 del fl.__defaults__
2359 self.assertEqual(self.signature(fl),
2360 ((('args', ..., ..., "var_positional"),
2361 ('kwargs', ..., ..., "var_keyword")),
2362 ...))
2363
Yury Selivanova773de02014-02-21 18:30:53 -05002364 # Test with cython-like builtins:
2365 _orig_isdesc = inspect.ismethoddescriptor
2366 def _isdesc(obj):
2367 if hasattr(obj, '_builtinmock'):
2368 return True
2369 return _orig_isdesc(obj)
2370
2371 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2372 builtin_func = funclike(func)
2373 # Make sure that our mock setup is working
2374 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2375 builtin_func._builtinmock = True
2376 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2377 self.assertEqual(inspect.signature(builtin_func), sig_func)
2378
Yury Selivanov63da7c72014-01-31 14:48:37 -05002379 def test_signature_functionlike_class(self):
2380 # We only want to duck type function-like objects,
2381 # not classes.
2382
2383 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2384 pass
2385
2386 class funclike:
2387 def __init__(self, marker):
2388 pass
2389
2390 __name__ = func.__name__
2391 __code__ = func.__code__
2392 __annotations__ = func.__annotations__
2393 __defaults__ = func.__defaults__
2394 __kwdefaults__ = func.__kwdefaults__
2395
Yury Selivanov63da7c72014-01-31 14:48:37 -05002396 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2397
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002398 def test_signature_on_method(self):
2399 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002400 def __init__(*args):
2401 pass
2402 def m1(self, arg1, arg2=1) -> int:
2403 pass
2404 def m2(*args):
2405 pass
2406 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002407 pass
2408
Yury Selivanov62560fb2014-01-28 12:26:24 -05002409 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002410 ((('arg1', ..., ..., "positional_or_keyword"),
2411 ('arg2', 1, ..., "positional_or_keyword")),
2412 int))
2413
Yury Selivanov62560fb2014-01-28 12:26:24 -05002414 self.assertEqual(self.signature(Test().m2),
2415 ((('args', ..., ..., "var_positional"),),
2416 ...))
2417
2418 self.assertEqual(self.signature(Test),
2419 ((('args', ..., ..., "var_positional"),),
2420 ...))
2421
2422 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2423 self.signature(Test())
2424
Yury Selivanov46c759d2015-05-27 21:56:53 -04002425 def test_signature_wrapped_bound_method(self):
2426 # Issue 24298
2427 class Test:
2428 def m1(self, arg1, arg2=1) -> int:
2429 pass
2430 @functools.wraps(Test().m1)
2431 def m1d(*args, **kwargs):
2432 pass
2433 self.assertEqual(self.signature(m1d),
2434 ((('arg1', ..., ..., "positional_or_keyword"),
2435 ('arg2', 1, ..., "positional_or_keyword")),
2436 int))
2437
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002438 def test_signature_on_classmethod(self):
2439 class Test:
2440 @classmethod
2441 def foo(cls, arg1, *, arg2=1):
2442 pass
2443
2444 meth = Test().foo
2445 self.assertEqual(self.signature(meth),
2446 ((('arg1', ..., ..., "positional_or_keyword"),
2447 ('arg2', 1, ..., "keyword_only")),
2448 ...))
2449
2450 meth = Test.foo
2451 self.assertEqual(self.signature(meth),
2452 ((('arg1', ..., ..., "positional_or_keyword"),
2453 ('arg2', 1, ..., "keyword_only")),
2454 ...))
2455
2456 def test_signature_on_staticmethod(self):
2457 class Test:
2458 @staticmethod
2459 def foo(cls, *, arg):
2460 pass
2461
2462 meth = Test().foo
2463 self.assertEqual(self.signature(meth),
2464 ((('cls', ..., ..., "positional_or_keyword"),
2465 ('arg', ..., ..., "keyword_only")),
2466 ...))
2467
2468 meth = Test.foo
2469 self.assertEqual(self.signature(meth),
2470 ((('cls', ..., ..., "positional_or_keyword"),
2471 ('arg', ..., ..., "keyword_only")),
2472 ...))
2473
2474 def test_signature_on_partial(self):
2475 from functools import partial
2476
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002477 Parameter = inspect.Parameter
2478
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002479 def test():
2480 pass
2481
2482 self.assertEqual(self.signature(partial(test)), ((), ...))
2483
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002484 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002485 inspect.signature(partial(test, 1))
2486
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002487 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002488 inspect.signature(partial(test, a=1))
2489
2490 def test(a, b, *, c, d):
2491 pass
2492
2493 self.assertEqual(self.signature(partial(test)),
2494 ((('a', ..., ..., "positional_or_keyword"),
2495 ('b', ..., ..., "positional_or_keyword"),
2496 ('c', ..., ..., "keyword_only"),
2497 ('d', ..., ..., "keyword_only")),
2498 ...))
2499
2500 self.assertEqual(self.signature(partial(test, 1)),
2501 ((('b', ..., ..., "positional_or_keyword"),
2502 ('c', ..., ..., "keyword_only"),
2503 ('d', ..., ..., "keyword_only")),
2504 ...))
2505
2506 self.assertEqual(self.signature(partial(test, 1, c=2)),
2507 ((('b', ..., ..., "positional_or_keyword"),
2508 ('c', 2, ..., "keyword_only"),
2509 ('d', ..., ..., "keyword_only")),
2510 ...))
2511
2512 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2513 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002514 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002515 ('c', 2, ..., "keyword_only"),
2516 ('d', ..., ..., "keyword_only")),
2517 ...))
2518
2519 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002520 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002521 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002522 ('d', ..., ..., "keyword_only")),
2523 ...))
2524
2525 self.assertEqual(self.signature(partial(test, a=1)),
2526 ((('a', 1, ..., "keyword_only"),
2527 ('b', ..., ..., "keyword_only"),
2528 ('c', ..., ..., "keyword_only"),
2529 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002530 ...))
2531
2532 def test(a, *args, b, **kwargs):
2533 pass
2534
2535 self.assertEqual(self.signature(partial(test, 1)),
2536 ((('args', ..., ..., "var_positional"),
2537 ('b', ..., ..., "keyword_only"),
2538 ('kwargs', ..., ..., "var_keyword")),
2539 ...))
2540
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002541 self.assertEqual(self.signature(partial(test, a=1)),
2542 ((('a', 1, ..., "keyword_only"),
2543 ('b', ..., ..., "keyword_only"),
2544 ('kwargs', ..., ..., "var_keyword")),
2545 ...))
2546
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002547 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2548 ((('args', ..., ..., "var_positional"),
2549 ('b', ..., ..., "keyword_only"),
2550 ('kwargs', ..., ..., "var_keyword")),
2551 ...))
2552
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002553 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2554 ((('args', ..., ..., "var_positional"),
2555 ('b', ..., ..., "keyword_only"),
2556 ('kwargs', ..., ..., "var_keyword")),
2557 ...))
2558
2559 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2560 ((('args', ..., ..., "var_positional"),
2561 ('b', 0, ..., "keyword_only"),
2562 ('kwargs', ..., ..., "var_keyword")),
2563 ...))
2564
2565 self.assertEqual(self.signature(partial(test, b=0)),
2566 ((('a', ..., ..., "positional_or_keyword"),
2567 ('args', ..., ..., "var_positional"),
2568 ('b', 0, ..., "keyword_only"),
2569 ('kwargs', ..., ..., "var_keyword")),
2570 ...))
2571
2572 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2573 ((('a', ..., ..., "positional_or_keyword"),
2574 ('args', ..., ..., "var_positional"),
2575 ('b', 0, ..., "keyword_only"),
2576 ('kwargs', ..., ..., "var_keyword")),
2577 ...))
2578
2579 def test(a, b, c:int) -> 42:
2580 pass
2581
2582 sig = test.__signature__ = inspect.signature(test)
2583
2584 self.assertEqual(self.signature(partial(partial(test, 1))),
2585 ((('b', ..., ..., "positional_or_keyword"),
2586 ('c', ..., int, "positional_or_keyword")),
2587 42))
2588
2589 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2590 ((('c', ..., int, "positional_or_keyword"),),
2591 42))
2592
2593 psig = inspect.signature(partial(partial(test, 1), 2))
2594
2595 def foo(a):
2596 return a
2597 _foo = partial(partial(foo, a=10), a=20)
2598 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002599 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002600 ...))
2601 # check that we don't have any side-effects in signature(),
2602 # and the partial object is still functioning
2603 self.assertEqual(_foo(), 20)
2604
2605 def foo(a, b, c):
2606 return a, b, c
2607 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002608
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002609 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002610 ((('b', 30, ..., "keyword_only"),
2611 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002612 ...))
2613 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002614
2615 def foo(a, b, c, *, d):
2616 return a, b, c, d
2617 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2618 self.assertEqual(self.signature(_foo),
2619 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002620 ('b', 10, ..., "keyword_only"),
2621 ('c', 20, ..., "keyword_only"),
2622 ('d', 30, ..., "keyword_only"),
2623 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002624 ...))
2625 ba = inspect.signature(_foo).bind(a=200, b=11)
2626 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2627
2628 def foo(a=1, b=2, c=3):
2629 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002630 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2631
2632 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002633 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002634
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002635 ba = inspect.signature(_foo).bind(11, 12)
2636 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002637
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002638 ba = inspect.signature(_foo).bind(11, b=12)
2639 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002640
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002641 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002642 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2643
2644 _foo = partial(_foo, b=10, c=20)
2645 ba = inspect.signature(_foo).bind(12)
2646 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2647
2648
2649 def foo(a, b, c, d, **kwargs):
2650 pass
2651 sig = inspect.signature(foo)
2652 params = sig.parameters.copy()
2653 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2654 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2655 foo.__signature__ = inspect.Signature(params.values())
2656 sig = inspect.signature(foo)
2657 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2658
2659 self.assertEqual(self.signature(partial(foo, 1)),
2660 ((('b', ..., ..., 'positional_only'),
2661 ('c', ..., ..., 'positional_or_keyword'),
2662 ('d', ..., ..., 'positional_or_keyword'),
2663 ('kwargs', ..., ..., 'var_keyword')),
2664 ...))
2665
2666 self.assertEqual(self.signature(partial(foo, 1, 2)),
2667 ((('c', ..., ..., 'positional_or_keyword'),
2668 ('d', ..., ..., 'positional_or_keyword'),
2669 ('kwargs', ..., ..., 'var_keyword')),
2670 ...))
2671
2672 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2673 ((('d', ..., ..., 'positional_or_keyword'),
2674 ('kwargs', ..., ..., 'var_keyword')),
2675 ...))
2676
2677 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2678 ((('c', 3, ..., 'keyword_only'),
2679 ('d', ..., ..., 'keyword_only'),
2680 ('kwargs', ..., ..., 'var_keyword')),
2681 ...))
2682
2683 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2684 ((('b', ..., ..., 'positional_only'),
2685 ('c', 3, ..., 'keyword_only'),
2686 ('d', ..., ..., 'keyword_only'),
2687 ('kwargs', ..., ..., 'var_keyword')),
2688 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002689
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002690 def test_signature_on_partialmethod(self):
2691 from functools import partialmethod
2692
2693 class Spam:
2694 def test():
2695 pass
2696 ham = partialmethod(test)
2697
2698 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2699 inspect.signature(Spam.ham)
2700
2701 class Spam:
2702 def test(it, a, *, c) -> 'spam':
2703 pass
2704 ham = partialmethod(test, c=1)
2705
2706 self.assertEqual(self.signature(Spam.ham),
2707 ((('it', ..., ..., 'positional_or_keyword'),
2708 ('a', ..., ..., 'positional_or_keyword'),
2709 ('c', 1, ..., 'keyword_only')),
2710 'spam'))
2711
2712 self.assertEqual(self.signature(Spam().ham),
2713 ((('a', ..., ..., 'positional_or_keyword'),
2714 ('c', 1, ..., 'keyword_only')),
2715 'spam'))
2716
Yury Selivanov8a387212018-03-06 12:59:45 -05002717 class Spam:
2718 def test(self: 'anno', x):
2719 pass
2720
2721 g = partialmethod(test, 1)
2722
2723 self.assertEqual(self.signature(Spam.g),
2724 ((('self', ..., 'anno', 'positional_or_keyword'),),
2725 ...))
2726
Yury Selivanov0486f812014-01-29 12:18:59 -05002727 def test_signature_on_fake_partialmethod(self):
2728 def foo(a): pass
2729 foo._partialmethod = 'spam'
2730 self.assertEqual(str(inspect.signature(foo)), '(a)')
2731
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002732 def test_signature_on_decorated(self):
2733 import functools
2734
2735 def decorator(func):
2736 @functools.wraps(func)
2737 def wrapper(*args, **kwargs) -> int:
2738 return func(*args, **kwargs)
2739 return wrapper
2740
2741 class Foo:
2742 @decorator
2743 def bar(self, a, b):
2744 pass
2745
2746 self.assertEqual(self.signature(Foo.bar),
2747 ((('self', ..., ..., "positional_or_keyword"),
2748 ('a', ..., ..., "positional_or_keyword"),
2749 ('b', ..., ..., "positional_or_keyword")),
2750 ...))
2751
2752 self.assertEqual(self.signature(Foo().bar),
2753 ((('a', ..., ..., "positional_or_keyword"),
2754 ('b', ..., ..., "positional_or_keyword")),
2755 ...))
2756
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002757 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2758 ((('args', ..., ..., "var_positional"),
2759 ('kwargs', ..., ..., "var_keyword")),
2760 ...)) # functools.wraps will copy __annotations__
2761 # from "func" to "wrapper", hence no
2762 # return_annotation
2763
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002764 # Test that we handle method wrappers correctly
2765 def decorator(func):
2766 @functools.wraps(func)
2767 def wrapper(*args, **kwargs) -> int:
2768 return func(42, *args, **kwargs)
2769 sig = inspect.signature(func)
2770 new_params = tuple(sig.parameters.values())[1:]
2771 wrapper.__signature__ = sig.replace(parameters=new_params)
2772 return wrapper
2773
2774 class Foo:
2775 @decorator
2776 def __call__(self, a, b):
2777 pass
2778
2779 self.assertEqual(self.signature(Foo.__call__),
2780 ((('a', ..., ..., "positional_or_keyword"),
2781 ('b', ..., ..., "positional_or_keyword")),
2782 ...))
2783
2784 self.assertEqual(self.signature(Foo().__call__),
2785 ((('b', ..., ..., "positional_or_keyword"),),
2786 ...))
2787
Nick Coghlane8c45d62013-07-28 20:00:01 +10002788 # Test we handle __signature__ partway down the wrapper stack
2789 def wrapped_foo_call():
2790 pass
2791 wrapped_foo_call.__wrapped__ = Foo.__call__
2792
2793 self.assertEqual(self.signature(wrapped_foo_call),
2794 ((('a', ..., ..., "positional_or_keyword"),
2795 ('b', ..., ..., "positional_or_keyword")),
2796 ...))
2797
2798
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002799 def test_signature_on_class(self):
2800 class C:
2801 def __init__(self, a):
2802 pass
2803
2804 self.assertEqual(self.signature(C),
2805 ((('a', ..., ..., "positional_or_keyword"),),
2806 ...))
2807
2808 class CM(type):
2809 def __call__(cls, a):
2810 pass
2811 class C(metaclass=CM):
2812 def __init__(self, b):
2813 pass
2814
2815 self.assertEqual(self.signature(C),
2816 ((('a', ..., ..., "positional_or_keyword"),),
2817 ...))
2818
2819 class CM(type):
2820 def __new__(mcls, name, bases, dct, *, foo=1):
2821 return super().__new__(mcls, name, bases, dct)
2822 class C(metaclass=CM):
2823 def __init__(self, b):
2824 pass
2825
2826 self.assertEqual(self.signature(C),
2827 ((('b', ..., ..., "positional_or_keyword"),),
2828 ...))
2829
2830 self.assertEqual(self.signature(CM),
2831 ((('name', ..., ..., "positional_or_keyword"),
2832 ('bases', ..., ..., "positional_or_keyword"),
2833 ('dct', ..., ..., "positional_or_keyword"),
2834 ('foo', 1, ..., "keyword_only")),
2835 ...))
2836
2837 class CMM(type):
2838 def __new__(mcls, name, bases, dct, *, foo=1):
2839 return super().__new__(mcls, name, bases, dct)
2840 def __call__(cls, nm, bs, dt):
2841 return type(nm, bs, dt)
2842 class CM(type, metaclass=CMM):
2843 def __new__(mcls, name, bases, dct, *, bar=2):
2844 return super().__new__(mcls, name, bases, dct)
2845 class C(metaclass=CM):
2846 def __init__(self, b):
2847 pass
2848
2849 self.assertEqual(self.signature(CMM),
2850 ((('name', ..., ..., "positional_or_keyword"),
2851 ('bases', ..., ..., "positional_or_keyword"),
2852 ('dct', ..., ..., "positional_or_keyword"),
2853 ('foo', 1, ..., "keyword_only")),
2854 ...))
2855
2856 self.assertEqual(self.signature(CM),
2857 ((('nm', ..., ..., "positional_or_keyword"),
2858 ('bs', ..., ..., "positional_or_keyword"),
2859 ('dt', ..., ..., "positional_or_keyword")),
2860 ...))
2861
2862 self.assertEqual(self.signature(C),
2863 ((('b', ..., ..., "positional_or_keyword"),),
2864 ...))
2865
2866 class CM(type):
2867 def __init__(cls, name, bases, dct, *, bar=2):
2868 return super().__init__(name, bases, dct)
2869 class C(metaclass=CM):
2870 def __init__(self, b):
2871 pass
2872
2873 self.assertEqual(self.signature(CM),
2874 ((('name', ..., ..., "positional_or_keyword"),
2875 ('bases', ..., ..., "positional_or_keyword"),
2876 ('dct', ..., ..., "positional_or_keyword"),
2877 ('bar', 2, ..., "keyword_only")),
2878 ...))
2879
Yury Selivanov145dff82014-02-01 13:49:29 -05002880 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2881 "Signature information for builtins requires docstrings")
2882 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002883 # Test classes without user-defined __init__ or __new__
2884 class C: pass
2885 self.assertEqual(str(inspect.signature(C)), '()')
2886 class D(C): pass
2887 self.assertEqual(str(inspect.signature(D)), '()')
2888
2889 # Test meta-classes without user-defined __init__ or __new__
2890 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002891 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002892 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2893 self.assertEqual(inspect.signature(C), None)
2894 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2895 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002896
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002897 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2898 "Signature information for builtins requires docstrings")
2899 def test_signature_on_builtin_class(self):
Antoine Pitrou91f43802019-05-26 17:10:09 +02002900 expected = ('(file, protocol=None, fix_imports=True, '
2901 'buffer_callback=None)')
2902 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002903
2904 class P(_pickle.Pickler): pass
2905 class EmptyTrait: pass
2906 class P2(EmptyTrait, P): pass
Antoine Pitrou91f43802019-05-26 17:10:09 +02002907 self.assertEqual(str(inspect.signature(P)), expected)
2908 self.assertEqual(str(inspect.signature(P2)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002909
2910 class P3(P2):
2911 def __init__(self, spam):
2912 pass
2913 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2914
2915 class MetaP(type):
2916 def __call__(cls, foo, bar):
2917 pass
2918 class P4(P2, metaclass=MetaP):
2919 pass
2920 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2921
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002922 def test_signature_on_callable_objects(self):
2923 class Foo:
2924 def __call__(self, a):
2925 pass
2926
2927 self.assertEqual(self.signature(Foo()),
2928 ((('a', ..., ..., "positional_or_keyword"),),
2929 ...))
2930
2931 class Spam:
2932 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002933 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002934 inspect.signature(Spam())
2935
2936 class Bar(Spam, Foo):
2937 pass
2938
2939 self.assertEqual(self.signature(Bar()),
2940 ((('a', ..., ..., "positional_or_keyword"),),
2941 ...))
2942
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002943 class Wrapped:
2944 pass
2945 Wrapped.__wrapped__ = lambda a: None
2946 self.assertEqual(self.signature(Wrapped),
2947 ((('a', ..., ..., "positional_or_keyword"),),
2948 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002949 # wrapper loop:
2950 Wrapped.__wrapped__ = Wrapped
2951 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2952 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002953
2954 def test_signature_on_lambdas(self):
2955 self.assertEqual(self.signature((lambda a=10: a)),
2956 ((('a', 10, ..., "positional_or_keyword"),),
2957 ...))
2958
2959 def test_signature_equality(self):
2960 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002961 self.assertFalse(inspect.signature(foo) == 42)
2962 self.assertTrue(inspect.signature(foo) != 42)
2963 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2964 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002965
2966 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002967 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2968 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002969 self.assertEqual(
2970 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002971
2972 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002973 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2974 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002975 self.assertNotEqual(
2976 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002977
2978 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002979 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2980 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002981 self.assertNotEqual(
2982 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002983
2984 def bar(a, *, b:int=42) -> float: 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, *, c) -> float: 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) -> 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 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003002 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3003 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003004 self.assertNotEqual(
3005 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003006
3007 def foo(*, a, b, c): pass
3008 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003009 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3010 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003011 self.assertEqual(
3012 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003013
3014 def foo(*, a=1, b, c): pass
3015 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003016 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3017 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003018 self.assertEqual(
3019 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003020
3021 def foo(pos, *, a=1, b, c): pass
3022 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003023 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3024 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003025 self.assertEqual(
3026 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003027
3028 def foo(pos, *, a, b, c): pass
3029 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003030 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3031 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003032 self.assertNotEqual(
3033 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003034
3035 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3036 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003037 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3038 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003039 self.assertEqual(
3040 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003041
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003042 def test_signature_hashable(self):
3043 S = inspect.Signature
3044 P = inspect.Parameter
3045
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003046 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003047 foo_sig = inspect.signature(foo)
3048
3049 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3050
3051 self.assertEqual(hash(foo_sig), hash(manual_sig))
3052 self.assertNotEqual(hash(foo_sig),
3053 hash(manual_sig.replace(return_annotation='spam')))
3054
3055 def bar(a) -> 1: pass
3056 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3057
3058 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003059 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003060 hash(inspect.signature(foo))
3061
3062 def foo(a) -> {}: pass
3063 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3064 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003065
3066 def test_signature_str(self):
3067 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3068 pass
3069 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003070 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003071
3072 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3073 pass
3074 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003075 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003076
3077 def foo():
3078 pass
3079 self.assertEqual(str(inspect.signature(foo)), '()')
3080
3081 def test_signature_str_positional_only(self):
3082 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003083 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003084
3085 def test(a_po, *, b, **kwargs):
3086 return a_po, kwargs
3087
3088 sig = inspect.signature(test)
3089 new_params = list(sig.parameters.values())
3090 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3091 test.__signature__ = sig.replace(parameters=new_params)
3092
3093 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003094 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003095
Yury Selivanov2393dca2014-01-27 15:07:58 -05003096 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3097 '(foo, /)')
3098
3099 self.assertEqual(str(S(parameters=[
3100 P('foo', P.POSITIONAL_ONLY),
3101 P('bar', P.VAR_KEYWORD)])),
3102 '(foo, /, **bar)')
3103
3104 self.assertEqual(str(S(parameters=[
3105 P('foo', P.POSITIONAL_ONLY),
3106 P('bar', P.VAR_POSITIONAL)])),
3107 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003108
3109 def test_signature_replace_anno(self):
3110 def test() -> 42:
3111 pass
3112
3113 sig = inspect.signature(test)
3114 sig = sig.replace(return_annotation=None)
3115 self.assertIs(sig.return_annotation, None)
3116 sig = sig.replace(return_annotation=sig.empty)
3117 self.assertIs(sig.return_annotation, sig.empty)
3118 sig = sig.replace(return_annotation=42)
3119 self.assertEqual(sig.return_annotation, 42)
3120 self.assertEqual(sig, inspect.signature(test))
3121
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003122 def test_signature_on_mangled_parameters(self):
3123 class Spam:
3124 def foo(self, __p1:1=2, *, __p2:2=3):
3125 pass
3126 class Ham(Spam):
3127 pass
3128
3129 self.assertEqual(self.signature(Spam.foo),
3130 ((('self', ..., ..., "positional_or_keyword"),
3131 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3132 ('_Spam__p2', 3, 2, "keyword_only")),
3133 ...))
3134
3135 self.assertEqual(self.signature(Spam.foo),
3136 self.signature(Ham.foo))
3137
Yury Selivanovda396452014-03-27 12:09:24 -04003138 def test_signature_from_callable_python_obj(self):
3139 class MySignature(inspect.Signature): pass
3140 def foo(a, *, b:1): pass
3141 foo_sig = MySignature.from_callable(foo)
3142 self.assertTrue(isinstance(foo_sig, MySignature))
3143
3144 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3145 "Signature information for builtins requires docstrings")
3146 def test_signature_from_callable_builtin_obj(self):
3147 class MySignature(inspect.Signature): pass
3148 sig = MySignature.from_callable(_pickle.Pickler)
3149 self.assertTrue(isinstance(sig, MySignature))
3150
larryhastingsf36ba122018-01-28 11:13:09 -08003151 def test_signature_definition_order_preserved_on_kwonly(self):
3152 for fn in signatures_with_lexicographic_keyword_only_parameters():
3153 signature = inspect.signature(fn)
3154 l = list(signature.parameters)
3155 sorted_l = sorted(l)
3156 self.assertTrue(l)
3157 self.assertEqual(l, sorted_l)
3158 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3159 l = list(signature.parameters)
3160 self.assertEqual(l, unsorted_keyword_only_parameters)
3161
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003162
3163class TestParameterObject(unittest.TestCase):
3164 def test_signature_parameter_kinds(self):
3165 P = inspect.Parameter
3166 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3167 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3168
3169 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3170 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3171
3172 def test_signature_parameter_object(self):
3173 p = inspect.Parameter('foo', default=10,
3174 kind=inspect.Parameter.POSITIONAL_ONLY)
3175 self.assertEqual(p.name, 'foo')
3176 self.assertEqual(p.default, 10)
3177 self.assertIs(p.annotation, p.empty)
3178 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3179
Dong-hee Naa9cab432018-05-30 00:04:08 +09003180 with self.assertRaisesRegex(ValueError, "value '123' is "
3181 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003182 inspect.Parameter('foo', default=10, kind='123')
3183
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003184 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003185 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3186
Yury Selivanov2393dca2014-01-27 15:07:58 -05003187 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003188 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3189
Yury Selivanov2393dca2014-01-27 15:07:58 -05003190 with self.assertRaisesRegex(ValueError,
3191 'is not a valid parameter name'):
3192 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3193
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003194 with self.assertRaisesRegex(ValueError,
3195 'is not a valid parameter name'):
3196 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3197
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003198 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003199 inspect.Parameter('a', default=42,
3200 kind=inspect.Parameter.VAR_KEYWORD)
3201
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003202 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003203 inspect.Parameter('a', default=42,
3204 kind=inspect.Parameter.VAR_POSITIONAL)
3205
3206 p = inspect.Parameter('a', default=42,
3207 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003208 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003209 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3210
3211 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003212 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003213
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003214 def test_signature_parameter_hashable(self):
3215 P = inspect.Parameter
3216 foo = P('foo', kind=P.POSITIONAL_ONLY)
3217 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3218 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3219 default=42)))
3220 self.assertNotEqual(hash(foo),
3221 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3222
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003223 def test_signature_parameter_equality(self):
3224 P = inspect.Parameter
3225 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3226
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003227 self.assertTrue(p == p)
3228 self.assertFalse(p != p)
3229 self.assertFalse(p == 42)
3230 self.assertTrue(p != 42)
3231 self.assertTrue(p == EqualsToAll())
3232 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003233
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003234 self.assertTrue(p == P('foo', default=42,
3235 kind=inspect.Parameter.KEYWORD_ONLY))
3236 self.assertFalse(p != P('foo', default=42,
3237 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003238
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003239 def test_signature_parameter_replace(self):
3240 p = inspect.Parameter('foo', default=42,
3241 kind=inspect.Parameter.KEYWORD_ONLY)
3242
3243 self.assertIsNot(p, p.replace())
3244 self.assertEqual(p, p.replace())
3245
3246 p2 = p.replace(annotation=1)
3247 self.assertEqual(p2.annotation, 1)
3248 p2 = p2.replace(annotation=p2.empty)
3249 self.assertEqual(p, p2)
3250
3251 p2 = p2.replace(name='bar')
3252 self.assertEqual(p2.name, 'bar')
3253 self.assertNotEqual(p2, p)
3254
Yury Selivanov2393dca2014-01-27 15:07:58 -05003255 with self.assertRaisesRegex(ValueError,
3256 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003257 p2 = p2.replace(name=p2.empty)
3258
3259 p2 = p2.replace(name='foo', default=None)
3260 self.assertIs(p2.default, None)
3261 self.assertNotEqual(p2, p)
3262
3263 p2 = p2.replace(name='foo', default=p2.empty)
3264 self.assertIs(p2.default, p2.empty)
3265
3266
3267 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3268 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3269 self.assertNotEqual(p2, p)
3270
Dong-hee Naa9cab432018-05-30 00:04:08 +09003271 with self.assertRaisesRegex(ValueError,
3272 "value <class 'inspect._empty'> "
3273 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003274 p2 = p2.replace(kind=p2.empty)
3275
3276 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3277 self.assertEqual(p2, p)
3278
3279 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003280 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3281 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003282
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003283 @cpython_only
3284 def test_signature_parameter_implicit(self):
3285 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003286 'implicit arguments must be passed as '
3287 'positional or keyword arguments, '
3288 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003289 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3290
3291 param = inspect.Parameter(
3292 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3293 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3294 self.assertEqual(param.name, 'implicit0')
3295
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003296 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003297 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003298
3299 with self.assertRaises(AttributeError):
3300 p.foo = 'bar'
3301
3302 with self.assertRaises(AttributeError):
3303 p.kind = 123
3304
3305
3306class TestSignatureBind(unittest.TestCase):
3307 @staticmethod
3308 def call(func, *args, **kwargs):
3309 sig = inspect.signature(func)
3310 ba = sig.bind(*args, **kwargs)
3311 return func(*ba.args, **ba.kwargs)
3312
3313 def test_signature_bind_empty(self):
3314 def test():
3315 return 42
3316
3317 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003318 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003319 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003320 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003321 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003322 with self.assertRaisesRegex(
3323 TypeError, "got an unexpected keyword argument 'spam'"):
3324
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003325 self.call(test, spam=1)
3326
3327 def test_signature_bind_var(self):
3328 def test(*args, **kwargs):
3329 return args, kwargs
3330
3331 self.assertEqual(self.call(test), ((), {}))
3332 self.assertEqual(self.call(test, 1), ((1,), {}))
3333 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3334 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3335 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3336 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3337 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3338 ((1, 2), {'foo': 'bar'}))
3339
3340 def test_signature_bind_just_args(self):
3341 def test(a, b, c):
3342 return a, b, c
3343
3344 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3345
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003346 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003347 self.call(test, 1, 2, 3, 4)
3348
Yury Selivanov86872752015-05-19 00:27:49 -04003349 with self.assertRaisesRegex(TypeError,
3350 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003351 self.call(test, 1)
3352
Yury Selivanov86872752015-05-19 00:27:49 -04003353 with self.assertRaisesRegex(TypeError,
3354 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003355 self.call(test)
3356
3357 def test(a, b, c=10):
3358 return a, b, c
3359 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3360 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3361
3362 def test(a=1, b=2, c=3):
3363 return a, b, c
3364 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3365 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3366 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3367
3368 def test_signature_bind_varargs_order(self):
3369 def test(*args):
3370 return args
3371
3372 self.assertEqual(self.call(test), ())
3373 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3374
3375 def test_signature_bind_args_and_varargs(self):
3376 def test(a, b, c=3, *args):
3377 return a, b, c, args
3378
3379 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3380 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3381 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3382 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3383
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003384 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003385 "multiple values for argument 'c'"):
3386 self.call(test, 1, 2, 3, c=4)
3387
3388 def test_signature_bind_just_kwargs(self):
3389 def test(**kwargs):
3390 return kwargs
3391
3392 self.assertEqual(self.call(test), {})
3393 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3394 {'foo': 'bar', 'spam': 'ham'})
3395
3396 def test_signature_bind_args_and_kwargs(self):
3397 def test(a, b, c=3, **kwargs):
3398 return a, b, c, kwargs
3399
3400 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3401 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3402 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3403 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3404 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3405 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3406 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3407 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3408 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3409 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3410 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3411 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3412 (1, 2, 4, {'foo': 'bar'}))
3413 self.assertEqual(self.call(test, c=5, a=4, b=3),
3414 (4, 3, 5, {}))
3415
3416 def test_signature_bind_kwonly(self):
3417 def test(*, foo):
3418 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003419 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003420 'too many positional arguments'):
3421 self.call(test, 1)
3422 self.assertEqual(self.call(test, foo=1), 1)
3423
3424 def test(a, *, foo=1, bar):
3425 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003426 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003427 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003428 self.call(test, 1)
3429
3430 def test(foo, *, bar):
3431 return foo, bar
3432 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3433 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3434
Yury Selivanov86872752015-05-19 00:27:49 -04003435 with self.assertRaisesRegex(
3436 TypeError, "got an unexpected keyword argument 'spam'"):
3437
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003438 self.call(test, bar=2, foo=1, spam=10)
3439
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003440 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003441 'too many positional arguments'):
3442 self.call(test, 1, 2)
3443
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003444 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003445 'too many positional arguments'):
3446 self.call(test, 1, 2, bar=2)
3447
Yury Selivanov86872752015-05-19 00:27:49 -04003448 with self.assertRaisesRegex(
3449 TypeError, "got an unexpected keyword argument 'spam'"):
3450
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003451 self.call(test, 1, bar=2, spam='ham')
3452
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003453 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003454 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003455 self.call(test, 1)
3456
3457 def test(foo, *, bar, **bin):
3458 return foo, bar, bin
3459 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3460 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3461 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3462 (1, 2, {'spam': 'ham'}))
3463 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3464 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003465 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003466 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003467 self.call(test, spam='ham', bar=2)
3468 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3469 (1, 2, {'bin': 1, 'spam': 10}))
3470
3471 def test_signature_bind_arguments(self):
3472 def test(a, *args, b, z=100, **kwargs):
3473 pass
3474 sig = inspect.signature(test)
3475 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3476 # we won't have 'z' argument in the bound arguments object, as we didn't
3477 # pass it to the 'bind'
3478 self.assertEqual(tuple(ba.arguments.items()),
3479 (('a', 10), ('args', (20,)), ('b', 30),
3480 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3481 self.assertEqual(ba.kwargs,
3482 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3483 self.assertEqual(ba.args, (10, 20))
3484
3485 def test_signature_bind_positional_only(self):
3486 P = inspect.Parameter
3487
3488 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3489 return a_po, b_po, c_po, foo, bar, kwargs
3490
3491 sig = inspect.signature(test)
3492 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3493 for name in ('a_po', 'b_po', 'c_po'):
3494 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3495 new_sig = sig.replace(parameters=new_params.values())
3496 test.__signature__ = new_sig
3497
3498 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3499 (1, 2, 4, 5, 6, {}))
3500
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003501 self.assertEqual(self.call(test, 1, 2),
3502 (1, 2, 3, 42, 50, {}))
3503
3504 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3505 (1, 2, 3, 4, 5, {}))
3506
3507 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3508 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3509
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003510 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003511 self.call(test, 1, 2, c_po=4)
3512
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003513 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003514 self.call(test, a_po=1, b_po=2)
3515
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003516 def test_signature_bind_with_self_arg(self):
3517 # Issue #17071: one of the parameters is named "self
3518 def test(a, self, b):
3519 pass
3520 sig = inspect.signature(test)
3521 ba = sig.bind(1, 2, 3)
3522 self.assertEqual(ba.args, (1, 2, 3))
3523 ba = sig.bind(1, self=2, b=3)
3524 self.assertEqual(ba.args, (1, 2, 3))
3525
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003526 def test_signature_bind_vararg_name(self):
3527 def test(a, *args):
3528 return a, args
3529 sig = inspect.signature(test)
3530
Yury Selivanov86872752015-05-19 00:27:49 -04003531 with self.assertRaisesRegex(
3532 TypeError, "got an unexpected keyword argument 'args'"):
3533
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003534 sig.bind(a=0, args=1)
3535
3536 def test(*args, **kwargs):
3537 return args, kwargs
3538 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3539
3540 sig = inspect.signature(test)
3541 ba = sig.bind(args=1)
3542 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3543
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003544 @cpython_only
3545 def test_signature_bind_implicit_arg(self):
3546 # Issue #19611: getcallargs should work with set comprehensions
3547 def make_set():
3548 return {z * z for z in range(5)}
3549 setcomp_code = make_set.__code__.co_consts[1]
3550 setcomp_func = types.FunctionType(setcomp_code, {})
3551
3552 iterator = iter(range(5))
3553 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3554
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003555
3556class TestBoundArguments(unittest.TestCase):
3557 def test_signature_bound_arguments_unhashable(self):
3558 def foo(a): pass
3559 ba = inspect.signature(foo).bind(1)
3560
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003561 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003562 hash(ba)
3563
3564 def test_signature_bound_arguments_equality(self):
3565 def foo(a): pass
3566 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003567 self.assertTrue(ba == ba)
3568 self.assertFalse(ba != ba)
3569 self.assertTrue(ba == EqualsToAll())
3570 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003571
3572 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003573 self.assertTrue(ba == ba2)
3574 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003575
3576 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003577 self.assertFalse(ba == ba3)
3578 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003579 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003580 self.assertTrue(ba == ba3)
3581 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003582
3583 def bar(b): pass
3584 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003585 self.assertFalse(ba == ba4)
3586 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003587
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003588 def foo(*, a, b): pass
3589 sig = inspect.signature(foo)
3590 ba1 = sig.bind(a=1, b=2)
3591 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003592 self.assertTrue(ba1 == ba2)
3593 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003594
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003595 def test_signature_bound_arguments_pickle(self):
3596 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3597 sig = inspect.signature(foo)
3598 ba = sig.bind(20, 30, z={})
3599
3600 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3601 with self.subTest(pickle_ver=ver):
3602 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3603 self.assertEqual(ba, ba_pickled)
3604
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003605 def test_signature_bound_arguments_repr(self):
3606 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3607 sig = inspect.signature(foo)
3608 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003609 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003610
Yury Selivanovb907a512015-05-16 13:45:09 -04003611 def test_signature_bound_arguments_apply_defaults(self):
3612 def foo(a, b=1, *args, c:1={}, **kw): pass
3613 sig = inspect.signature(foo)
3614
3615 ba = sig.bind(20)
3616 ba.apply_defaults()
3617 self.assertEqual(
3618 list(ba.arguments.items()),
3619 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3620
3621 # Make sure that we preserve the order:
3622 # i.e. 'c' should be *before* 'kw'.
3623 ba = sig.bind(10, 20, 30, d=1)
3624 ba.apply_defaults()
3625 self.assertEqual(
3626 list(ba.arguments.items()),
3627 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3628
3629 # Make sure that BoundArguments produced by bind_partial()
3630 # are supported.
3631 def foo(a, b): pass
3632 sig = inspect.signature(foo)
3633 ba = sig.bind_partial(20)
3634 ba.apply_defaults()
3635 self.assertEqual(
3636 list(ba.arguments.items()),
3637 [('a', 20)])
3638
3639 # Test no args
3640 def foo(): pass
3641 sig = inspect.signature(foo)
3642 ba = sig.bind()
3643 ba.apply_defaults()
3644 self.assertEqual(list(ba.arguments.items()), [])
3645
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003646 # Make sure a no-args binding still acquires proper defaults.
3647 def foo(a='spam'): pass
3648 sig = inspect.signature(foo)
3649 ba = sig.bind()
3650 ba.apply_defaults()
3651 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3652
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003653
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003654class TestSignaturePrivateHelpers(unittest.TestCase):
3655 def test_signature_get_bound_param(self):
3656 getter = inspect._signature_get_bound_param
3657
3658 self.assertEqual(getter('($self)'), 'self')
3659 self.assertEqual(getter('($self, obj)'), 'self')
3660 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3661
Larry Hastings2623c8c2014-02-08 22:15:29 -08003662 def _strip_non_python_syntax(self, input,
3663 clean_signature, self_parameter, last_positional_only):
3664 computed_clean_signature, \
3665 computed_self_parameter, \
3666 computed_last_positional_only = \
3667 inspect._signature_strip_non_python_syntax(input)
3668 self.assertEqual(computed_clean_signature, clean_signature)
3669 self.assertEqual(computed_self_parameter, self_parameter)
3670 self.assertEqual(computed_last_positional_only, last_positional_only)
3671
3672 def test_signature_strip_non_python_syntax(self):
3673 self._strip_non_python_syntax(
3674 "($module, /, path, mode, *, dir_fd=None, " +
3675 "effective_ids=False,\n follow_symlinks=True)",
3676 "(module, path, mode, *, dir_fd=None, " +
3677 "effective_ids=False, follow_symlinks=True)",
3678 0,
3679 0)
3680
3681 self._strip_non_python_syntax(
3682 "($module, word, salt, /)",
3683 "(module, word, salt)",
3684 0,
3685 2)
3686
3687 self._strip_non_python_syntax(
3688 "(x, y=None, z=None, /)",
3689 "(x, y=None, z=None)",
3690 None,
3691 2)
3692
3693 self._strip_non_python_syntax(
3694 "(x, y=None, z=None)",
3695 "(x, y=None, z=None)",
3696 None,
3697 None)
3698
3699 self._strip_non_python_syntax(
3700 "(x,\n y=None,\n z = None )",
3701 "(x, y=None, z=None)",
3702 None,
3703 None)
3704
3705 self._strip_non_python_syntax(
3706 "",
3707 "",
3708 None,
3709 None)
3710
3711 self._strip_non_python_syntax(
3712 None,
3713 None,
3714 None,
3715 None)
3716
Nick Coghlan9c680b02015-04-13 12:54:54 -04003717class TestSignatureDefinitions(unittest.TestCase):
3718 # This test case provides a home for checking that particular APIs
3719 # have signatures available for introspection
3720
3721 @cpython_only
3722 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3723 "Signature information for builtins requires docstrings")
3724 def test_builtins_have_signatures(self):
3725 # This checks all builtin callables in CPython have signatures
3726 # A few have signatures Signature can't yet handle, so we skip those
3727 # since they will have to wait until PEP 457 adds the required
3728 # introspection support to the inspect module
3729 # Some others also haven't been converted yet for various other
3730 # reasons, so we also skip those for the time being, but design
3731 # the test to fail in order to indicate when it needs to be
3732 # updated.
3733 no_signature = set()
3734 # These need PEP 457 groups
3735 needs_groups = {"range", "slice", "dir", "getattr",
3736 "next", "iter", "vars"}
3737 no_signature |= needs_groups
3738 # These need PEP 457 groups or a signature change to accept None
3739 needs_semantic_update = {"round"}
3740 no_signature |= needs_semantic_update
3741 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003742 needs_varargs = {"breakpoint", "min", "max", "print",
3743 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003744 no_signature |= needs_varargs
3745 # These simply weren't covered in the initial AC conversion
3746 # for builtin callables
3747 not_converted_yet = {"open", "__import__"}
3748 no_signature |= not_converted_yet
3749 # These builtin types are expected to provide introspection info
3750 types_with_signatures = set()
3751 # Check the signatures we expect to be there
3752 ns = vars(builtins)
3753 for name, obj in sorted(ns.items()):
3754 if not callable(obj):
3755 continue
3756 # The builtin types haven't been converted to AC yet
3757 if isinstance(obj, type) and (name not in types_with_signatures):
3758 # Note that this also skips all the exception types
3759 no_signature.add(name)
3760 if (name in no_signature):
3761 # Not yet converted
3762 continue
3763 with self.subTest(builtin=name):
3764 self.assertIsNotNone(inspect.signature(obj))
3765 # Check callables that haven't been converted don't claim a signature
3766 # This ensures this test will start failing as more signatures are
3767 # added, so the affected items can be moved into the scope of the
3768 # regression test above
3769 for name in no_signature:
3770 with self.subTest(builtin=name):
3771 self.assertIsNone(obj.__text_signature__)
3772
Serhiy Storchakad53cf992019-05-06 22:40:27 +03003773 def test_python_function_override_signature(self):
3774 def func(*args, **kwargs):
3775 pass
3776 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
3777 sig = inspect.signature(func)
3778 self.assertIsNotNone(sig)
3779 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
3780 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
3781 sig = inspect.signature(func)
3782 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
3783
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003784
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003785class NTimesUnwrappable:
3786 def __init__(self, n):
3787 self.n = n
3788 self._next = None
3789
3790 @property
3791 def __wrapped__(self):
3792 if self.n <= 0:
3793 raise Exception("Unwrapped too many times")
3794 if self._next is None:
3795 self._next = NTimesUnwrappable(self.n - 1)
3796 return self._next
3797
Nick Coghlane8c45d62013-07-28 20:00:01 +10003798class TestUnwrap(unittest.TestCase):
3799
3800 def test_unwrap_one(self):
3801 def func(a, b):
3802 return a + b
3803 wrapper = functools.lru_cache(maxsize=20)(func)
3804 self.assertIs(inspect.unwrap(wrapper), func)
3805
3806 def test_unwrap_several(self):
3807 def func(a, b):
3808 return a + b
3809 wrapper = func
3810 for __ in range(10):
3811 @functools.wraps(wrapper)
3812 def wrapper():
3813 pass
3814 self.assertIsNot(wrapper.__wrapped__, func)
3815 self.assertIs(inspect.unwrap(wrapper), func)
3816
3817 def test_stop(self):
3818 def func1(a, b):
3819 return a + b
3820 @functools.wraps(func1)
3821 def func2():
3822 pass
3823 @functools.wraps(func2)
3824 def wrapper():
3825 pass
3826 func2.stop_here = 1
3827 unwrapped = inspect.unwrap(wrapper,
3828 stop=(lambda f: hasattr(f, "stop_here")))
3829 self.assertIs(unwrapped, func2)
3830
3831 def test_cycle(self):
3832 def func1(): pass
3833 func1.__wrapped__ = func1
3834 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3835 inspect.unwrap(func1)
3836
3837 def func2(): pass
3838 func2.__wrapped__ = func1
3839 func1.__wrapped__ = func2
3840 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3841 inspect.unwrap(func1)
3842 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3843 inspect.unwrap(func2)
3844
3845 def test_unhashable(self):
3846 def func(): pass
3847 func.__wrapped__ = None
3848 class C:
3849 __hash__ = None
3850 __wrapped__ = func
3851 self.assertIsNone(inspect.unwrap(C()))
3852
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003853 def test_recursion_limit(self):
3854 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3855 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3856 inspect.unwrap(obj)
3857
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003858class TestMain(unittest.TestCase):
3859 def test_only_source(self):
3860 module = importlib.import_module('unittest')
3861 rc, out, err = assert_python_ok('-m', 'inspect',
3862 'unittest')
3863 lines = out.decode().splitlines()
3864 # ignore the final newline
3865 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3866 self.assertEqual(err, b'')
3867
Yury Selivanov42407ab2014-06-23 10:23:50 -07003868 def test_custom_getattr(self):
3869 def foo():
3870 pass
3871 foo.__signature__ = 42
3872 with self.assertRaises(TypeError):
3873 inspect.signature(foo)
3874
Brett Cannon634a8fc2013-10-02 10:25:42 -04003875 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003876 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003877 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003878 rc, out, err = assert_python_ok('-m', 'inspect',
3879 'concurrent.futures:ThreadPoolExecutor')
3880 lines = out.decode().splitlines()
3881 # ignore the final newline
3882 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003883 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003884 self.assertEqual(err, b'')
3885
3886 def test_builtins(self):
3887 module = importlib.import_module('unittest')
3888 _, out, err = assert_python_failure('-m', 'inspect',
3889 'sys')
3890 lines = err.decode().splitlines()
3891 self.assertEqual(lines, ["Can't get info for builtin modules."])
3892
3893 def test_details(self):
3894 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003895 args = support.optim_args_from_interpreter_flags()
3896 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003897 'unittest', '--details')
3898 output = out.decode()
3899 # Just a quick sanity check on the output
3900 self.assertIn(module.__name__, output)
3901 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003902 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003903 self.assertEqual(err, b'')
3904
3905
Yury Selivanovef1e7502014-12-08 16:05:34 -05003906class TestReload(unittest.TestCase):
3907
3908 src_before = textwrap.dedent("""\
3909def foo():
3910 print("Bla")
3911 """)
3912
3913 src_after = textwrap.dedent("""\
3914def foo():
3915 print("Oh no!")
3916 """)
3917
3918 def assertInspectEqual(self, path, source):
3919 inspected_src = inspect.getsource(source)
3920 with open(path) as src:
3921 self.assertEqual(
3922 src.read().splitlines(True),
3923 inspected_src.splitlines(True)
3924 )
3925
3926 def test_getsource_reload(self):
3927 # see issue 1218234
3928 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3929 module = importlib.import_module(name)
3930 self.assertInspectEqual(path, module)
3931 with open(path, 'w') as src:
3932 src.write(self.src_after)
3933 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003934
Nick Coghlane8c45d62013-07-28 20:00:01 +10003935
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003936def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003937 run_unittest(
3938 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3939 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3940 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003941 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003942 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003943 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04003944 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003945 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07003946 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00003947 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003948
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003949if __name__ == "__main__":
3950 test_main()