blob: b9072e0137eb087f7b1718e931e2bbd14373ce1e [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')
149 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000150 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000151 self.istest(inspect.isgenerator, '(x for x in range(2))')
152 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanoveb636452016-09-08 22:01:51 -0700153 self.istest(inspect.isasyncgen,
154 'async_generator_function_example(1)')
155 self.istest(inspect.isasyncgenfunction,
156 'async_generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400157
158 with warnings.catch_warnings():
159 warnings.simplefilter("ignore")
160 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
161 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
162
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000163 if hasattr(types, 'MemberDescriptorType'):
164 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
165 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000166 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000167
Yury Selivanov75445082015-05-11 22:57:16 -0400168 def test_iscoroutine(self):
Pablo Galindo7cd25432018-10-26 12:19:14 +0100169 async_gen_coro = async_generator_function_example(1)
Yury Selivanov75445082015-05-11 22:57:16 -0400170 gen_coro = gen_coroutine_function_example(1)
171 coro = coroutine_function_example(1)
172
Yury Selivanov5376ba92015-06-22 12:19:30 -0400173 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400174 inspect.iscoroutinefunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100175 self.assertFalse(
176 inspect.iscoroutinefunction(
177 functools.partial(functools.partial(
178 gen_coroutine_function_example))))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400179 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400180
181 self.assertTrue(
182 inspect.isgeneratorfunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100183 self.assertTrue(
184 inspect.isgeneratorfunction(
185 functools.partial(functools.partial(
186 gen_coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400187 self.assertTrue(inspect.isgenerator(gen_coro))
188
189 self.assertTrue(
190 inspect.iscoroutinefunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100191 self.assertTrue(
192 inspect.iscoroutinefunction(
193 functools.partial(functools.partial(
194 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400195 self.assertTrue(inspect.iscoroutine(coro))
196
197 self.assertFalse(
198 inspect.isgeneratorfunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100199 self.assertFalse(
200 inspect.isgeneratorfunction(
201 functools.partial(functools.partial(
202 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400203 self.assertFalse(inspect.isgenerator(coro))
204
Pablo Galindo7cd25432018-10-26 12:19:14 +0100205 self.assertTrue(
206 inspect.isasyncgenfunction(async_generator_function_example))
207 self.assertTrue(
208 inspect.isasyncgenfunction(
209 functools.partial(functools.partial(
210 async_generator_function_example))))
211 self.assertTrue(inspect.isasyncgen(async_gen_coro))
212
213 coro.close(); gen_coro.close(); # silence warnings
Yury Selivanov75445082015-05-11 22:57:16 -0400214
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400215 def test_isawaitable(self):
216 def gen(): yield
217 self.assertFalse(inspect.isawaitable(gen()))
218
219 coro = coroutine_function_example(1)
220 gen_coro = gen_coroutine_function_example(1)
221
222 self.assertTrue(inspect.isawaitable(coro))
223 self.assertTrue(inspect.isawaitable(gen_coro))
224
225 class Future:
226 def __await__():
227 pass
228 self.assertTrue(inspect.isawaitable(Future()))
229 self.assertFalse(inspect.isawaitable(Future))
230
231 class NotFuture: pass
232 not_fut = NotFuture()
233 not_fut.__await__ = lambda: None
234 self.assertFalse(inspect.isawaitable(not_fut))
235
236 coro.close(); gen_coro.close() # silence warnings
237
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000238 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000239 self.assertTrue(inspect.isroutine(mod.spam))
240 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000241
Benjamin Petersonc4656002009-01-17 22:41:18 +0000242 def test_isclass(self):
243 self.istest(inspect.isclass, 'mod.StupidGit')
244 self.assertTrue(inspect.isclass(list))
245
246 class CustomGetattr(object):
247 def __getattr__(self, attr):
248 return None
249 self.assertFalse(inspect.isclass(CustomGetattr()))
250
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000251 def test_get_slot_members(self):
252 class C(object):
253 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000254 x = C()
255 x.a = 42
256 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000257 self.assertIn('a', members)
258 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000259
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000260 def test_isabstract(self):
261 from abc import ABCMeta, abstractmethod
262
263 class AbstractClassExample(metaclass=ABCMeta):
264
265 @abstractmethod
266 def foo(self):
267 pass
268
269 class ClassExample(AbstractClassExample):
270 def foo(self):
271 pass
272
273 a = ClassExample()
274
275 # Test general behaviour.
276 self.assertTrue(inspect.isabstract(AbstractClassExample))
277 self.assertFalse(inspect.isabstract(ClassExample))
278 self.assertFalse(inspect.isabstract(a))
279 self.assertFalse(inspect.isabstract(int))
280 self.assertFalse(inspect.isabstract(5))
281
Natefcfe80e2017-04-24 10:06:15 -0700282 def test_isabstract_during_init_subclass(self):
283 from abc import ABCMeta, abstractmethod
284 isabstract_checks = []
285 class AbstractChecker(metaclass=ABCMeta):
286 def __init_subclass__(cls):
287 isabstract_checks.append(inspect.isabstract(cls))
288 class AbstractClassExample(AbstractChecker):
289 @abstractmethod
290 def foo(self):
291 pass
292 class ClassExample(AbstractClassExample):
293 def foo(self):
294 pass
295 self.assertEqual(isabstract_checks, [True, False])
296
297 isabstract_checks.clear()
298 class AbstractChild(AbstractClassExample):
299 pass
300 class AbstractGrandchild(AbstractChild):
301 pass
302 class ConcreteGrandchild(ClassExample):
303 pass
304 self.assertEqual(isabstract_checks, [True, True, False])
305
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000306
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000307class TestInterpreterStack(IsTestBase):
308 def __init__(self, *args, **kwargs):
309 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000310
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000311 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000312
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000313 def test_abuse_done(self):
314 self.istest(inspect.istraceback, 'git.ex[2]')
315 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000316
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000317 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000318 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000319 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000320 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000321 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000322 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000323 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000324 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000325 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000326 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400327 # Test named tuple fields
328 record = mod.st[0]
329 self.assertIs(record.frame, mod.fr)
330 self.assertEqual(record.lineno, 16)
331 self.assertEqual(record.filename, mod.__file__)
332 self.assertEqual(record.function, 'eggs')
333 self.assertIn('inspect.stack()', record.code_context[0])
334 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000335
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000336 def test_trace(self):
337 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000338 self.assertEqual(revise(*git.tr[0][1:]),
339 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
340 self.assertEqual(revise(*git.tr[1][1:]),
341 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
342 self.assertEqual(revise(*git.tr[2][1:]),
343 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000344
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000345 def test_frame(self):
346 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
347 self.assertEqual(args, ['x', 'y'])
348 self.assertEqual(varargs, None)
349 self.assertEqual(varkw, None)
350 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
351 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
352 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000353
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000354 def test_previous_frame(self):
355 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000356 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000357 self.assertEqual(varargs, 'g')
358 self.assertEqual(varkw, 'h')
359 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000360 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000361
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000362class GetSourceBase(unittest.TestCase):
363 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000364 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000365
Yury Selivanov6738b112015-05-16 10:10:21 -0400366 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000367 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000368 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000369
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000370 def sourcerange(self, top, bottom):
371 lines = self.source.split("\n")
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700372 return "\n".join(lines[top-1:bottom]) + ("\n" if bottom else "")
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000373
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000374 def assertSourceEqual(self, obj, top, bottom):
375 self.assertEqual(inspect.getsource(obj),
376 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000377
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000378class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000379 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000380
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000381 def test_getclasses(self):
382 classes = inspect.getmembers(mod, inspect.isclass)
383 self.assertEqual(classes,
384 [('FesteringGob', mod.FesteringGob),
385 ('MalodorousPervert', mod.MalodorousPervert),
386 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300387 ('StupidGit', mod.StupidGit),
388 ('Tit', mod.MalodorousPervert),
389 ])
390 tree = inspect.getclasstree([cls[1] for cls in classes])
391 self.assertEqual(tree,
392 [(object, ()),
393 [(mod.ParrotDroppings, (object,)),
394 [(mod.FesteringGob, (mod.MalodorousPervert,
395 mod.ParrotDroppings))
396 ],
397 (mod.StupidGit, (object,)),
398 [(mod.MalodorousPervert, (mod.StupidGit,)),
399 [(mod.FesteringGob, (mod.MalodorousPervert,
400 mod.ParrotDroppings))
401 ]
402 ]
403 ]
404 ])
405 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000406 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000407 [(object, ()),
408 [(mod.ParrotDroppings, (object,)),
409 (mod.StupidGit, (object,)),
410 [(mod.MalodorousPervert, (mod.StupidGit,)),
411 [(mod.FesteringGob, (mod.MalodorousPervert,
412 mod.ParrotDroppings))
413 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000414 ]
415 ]
416 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000417
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000418 def test_getfunctions(self):
419 functions = inspect.getmembers(mod, inspect.isfunction)
420 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300421 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000422 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000423
R. David Murray378c0cf2010-02-24 01:46:21 +0000424 @unittest.skipIf(sys.flags.optimize >= 2,
425 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000426 def test_getdoc(self):
427 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
428 self.assertEqual(inspect.getdoc(mod.StupidGit),
429 'A longer,\n\nindented\n\ndocstring.')
430 self.assertEqual(inspect.getdoc(git.abuse),
431 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000432
Serhiy Storchaka5cf2b7252015-04-03 22:38:53 +0300433 @unittest.skipIf(sys.flags.optimize >= 2,
434 "Docstrings are omitted with -O2 and above")
435 def test_getdoc_inherited(self):
436 self.assertEqual(inspect.getdoc(mod.FesteringGob),
437 'A longer,\n\nindented\n\ndocstring.')
438 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
439 'Another\n\ndocstring\n\ncontaining\n\ntabs')
440 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
441 'Another\n\ndocstring\n\ncontaining\n\ntabs')
442 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
443 'The automatic gainsaying.')
444
445 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
446 def test_finddoc(self):
447 finddoc = inspect._finddoc
448 self.assertEqual(finddoc(int), int.__doc__)
449 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
450 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
451 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
452 self.assertEqual(finddoc(int.real), int.real.__doc__)
453
Georg Brandl0c77a822008-06-10 16:37:50 +0000454 def test_cleandoc(self):
455 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
456 'An\nindented\ndocstring.')
457
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000458 def test_getcomments(self):
459 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
460 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Marco Buttu3f2155f2017-03-17 09:50:23 +0100461 # If the object source file is not available, return None.
462 co = compile('x=1', '_non_existing_filename.py', 'exec')
463 self.assertIsNone(inspect.getcomments(co))
464 # If the object has been defined in C, return None.
465 self.assertIsNone(inspect.getcomments(list))
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000466
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000467 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000468 # Check actual module
469 self.assertEqual(inspect.getmodule(mod), mod)
470 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000471 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000472 # Check a method (no __module__ attribute, falls back to filename)
473 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
474 # Do it again (check the caching isn't broken)
475 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
476 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000477 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000478 # Check filename override
479 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000480
Berker Peksagff0e3b72017-01-02 06:57:43 +0300481 def test_getframeinfo_get_first_line(self):
482 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
483 self.assertEqual(frame_info.code_context[0], "# line 1\n")
484 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
485
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000486 def test_getsource(self):
487 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200488 self.assertSourceEqual(mod.StupidGit, 21, 51)
489 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000490
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000491 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000492 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
493 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000494 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100495 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000496 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000497 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200498 try:
499 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
500 finally:
501 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000502
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000503 def test_getfile(self):
504 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000505
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500506 def test_getfile_class_without_module(self):
507 class CM(type):
508 @property
509 def __module__(cls):
510 raise AttributeError
511 class C(metaclass=CM):
512 pass
513 with self.assertRaises(TypeError):
514 inspect.getfile(C)
515
Thomas Kluyvere968bc732017-10-24 13:42:36 +0100516 def test_getfile_broken_repr(self):
517 class ErrorRepr:
518 def __repr__(self):
519 raise Exception('xyz')
520 er = ErrorRepr()
521 with self.assertRaises(TypeError):
522 inspect.getfile(er)
523
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000524 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000525 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000526 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000527 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000528 m.__file__ = "<string>" # hopefully not a real filename...
529 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000530 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000531 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000532 del sys.modules[name]
533 inspect.getmodule(compile('a=10','','single'))
534
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500535 def test_proceed_with_fake_filename(self):
536 '''doctest monkeypatches linecache to enable inspection'''
537 fn, source = '<test>', 'def x(): pass\n'
538 getlines = linecache.getlines
539 def monkey(filename, module_globals=None):
540 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300541 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500542 else:
543 return getlines(filename, module_globals)
544 linecache.getlines = monkey
545 try:
546 ns = {}
547 exec(compile(source, fn, 'single'), ns)
548 inspect.getsource(ns["x"])
549 finally:
550 linecache.getlines = getlines
551
Antoine Pitroua8723a02015-04-15 00:41:29 +0200552 def test_getsource_on_code_object(self):
553 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
554
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700555class TestGettingSourceOfToplevelFrames(GetSourceBase):
556 fodderModule = mod
557
558 def test_range_toplevel_frame(self):
559 self.maxDiff = None
560 self.assertSourceEqual(mod.currentframe, 1, None)
561
562 def test_range_traceback_toplevel_frame(self):
563 self.assertSourceEqual(mod.tb, 1, None)
564
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000565class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000566 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000567
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000568 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000569 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000570
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000571 def test_replacing_decorator(self):
572 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000573
Yury Selivanov081bbf62014-09-26 17:34:54 -0400574 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200575 self.assertSourceEqual(mod2.real, 130, 132)
576
577 def test_decorator_with_lambda(self):
578 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400579
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000580class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000581 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000582 def test_oneline_lambda(self):
583 # Test inspect.getsource with a one-line lambda function.
584 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000585
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000586 def test_threeline_lambda(self):
587 # Test inspect.getsource with a three-line lambda function,
588 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000589 self.assertSourceEqual(mod2.tll, 28, 30)
590
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000591 def test_twoline_indented_lambda(self):
592 # Test inspect.getsource with a two-line lambda function,
593 # where the second line _is_ indented.
594 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000595
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000596 def test_onelinefunc(self):
597 # Test inspect.getsource with a regular one-line function.
598 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000599
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000600 def test_manyargs(self):
601 # Test inspect.getsource with a regular function where
602 # the arguments are on two lines and _not_ indented and
603 # the body on the second line with the last arguments.
604 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000605
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000606 def test_twolinefunc(self):
607 # Test inspect.getsource with a regular function where
608 # the body is on two lines, following the argument list and
609 # continued on the next line by a \\.
610 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000611
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000612 def test_lambda_in_list(self):
613 # Test inspect.getsource with a one-line lambda function
614 # defined in a list, indented.
615 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000616
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000617 def test_anonymous(self):
618 # Test inspect.getsource with a lambda function defined
619 # as argument to another function.
620 self.assertSourceEqual(mod2.anonymous, 55, 55)
621
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000622class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000623 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000624
625 def test_with_comment(self):
626 self.assertSourceEqual(mod2.with_comment, 58, 59)
627
628 def test_multiline_sig(self):
629 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
630
Armin Rigodd5c0232005-09-25 11:45:45 +0000631 def test_nested_class(self):
632 self.assertSourceEqual(mod2.func69().func71, 71, 72)
633
634 def test_one_liner_followed_by_non_name(self):
635 self.assertSourceEqual(mod2.func77, 77, 77)
636
637 def test_one_liner_dedent_non_name(self):
638 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
639
640 def test_with_comment_instead_of_docstring(self):
641 self.assertSourceEqual(mod2.func88, 88, 90)
642
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000643 def test_method_in_dynamic_class(self):
644 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
645
R David Murray32562d72014-10-03 11:15:38 -0400646 # This should not skip for CPython, but might on a repackaged python where
647 # unicodedata is not an external module, or on pypy.
648 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
649 unicodedata.__file__.endswith('.py'),
650 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000651 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200652 self.assertRaises(OSError, inspect.getsource, unicodedata)
653 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000654
R. David Murraya1b37402010-06-17 02:04:29 +0000655 def test_findsource_code_in_linecache(self):
656 lines = ["x=1"]
657 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200658 self.assertRaises(OSError, inspect.findsource, co)
659 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000660 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200661 try:
662 self.assertEqual(inspect.findsource(co), (lines,0))
663 self.assertEqual(inspect.getsource(co), lines[0])
664 finally:
665 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000666
Ezio Melotti1b145922013-03-30 05:17:24 +0200667 def test_findsource_without_filename(self):
668 for fname in ['', '<string>']:
669 co = compile('x=1', fname, "exec")
670 self.assertRaises(IOError, inspect.findsource, co)
671 self.assertRaises(IOError, inspect.getsource, co)
672
Antoine Pitroua8723a02015-04-15 00:41:29 +0200673 def test_getsource_on_method(self):
674 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
675
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300676 def test_nested_func(self):
677 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
678
679
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000680class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400681 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000682 self.tempdir = TESTFN + '_dir'
683 os.mkdir(self.tempdir)
684 with open(os.path.join(self.tempdir,
685 'inspect_fodder3%spy' % os.extsep), 'w') as f:
686 f.write("class X:\n pass # No EOL")
687 with DirsOnSysPath(self.tempdir):
688 import inspect_fodder3 as mod3
689 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400690 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000691
692 def tearDown(self):
693 shutil.rmtree(self.tempdir)
694
695 def test_class(self):
696 self.assertSourceEqual(self.fodderModule.X, 1, 2)
697
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100698
699class _BrokenDataDescriptor(object):
700 """
701 A broken data descriptor. See bug #1785.
702 """
703 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700704 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100705
706 def __set__(*args):
707 raise RuntimeError
708
709 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700710 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100711
712
713class _BrokenMethodDescriptor(object):
714 """
715 A broken method descriptor. See bug #1785.
716 """
717 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700718 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100719
720 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700721 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100722
723
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000724# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000725def attrs_wo_objs(cls):
726 return [t[:3] for t in inspect.classify_class_attrs(cls)]
727
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100728
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000729class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000730 def test_newstyle_mro(self):
731 # The same w/ new-class MRO.
732 class A(object): pass
733 class B(A): pass
734 class C(A): pass
735 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000736
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000737 expected = (D, B, C, A, object)
738 got = inspect.getmro(D)
739 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000740
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500741 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
742 varkw_e=None, defaults_e=None, formatted=None):
743 with self.assertWarns(DeprecationWarning):
744 args, varargs, varkw, defaults = inspect.getargspec(routine)
745 self.assertEqual(args, args_e)
746 self.assertEqual(varargs, varargs_e)
747 self.assertEqual(varkw, varkw_e)
748 self.assertEqual(defaults, defaults_e)
749 if formatted is not None:
Matthias Bussonnier46c5cd02018-06-11 22:08:16 +0200750 with self.assertWarns(DeprecationWarning):
751 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
752 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500753
Christian Heimes3795b532007-11-08 13:48:53 +0000754 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
755 varkw_e=None, defaults_e=None,
756 kwonlyargs_e=[], kwonlydefaults_e=None,
757 ann_e={}, formatted=None):
758 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
759 inspect.getfullargspec(routine)
760 self.assertEqual(args, args_e)
761 self.assertEqual(varargs, varargs_e)
762 self.assertEqual(varkw, varkw_e)
763 self.assertEqual(defaults, defaults_e)
764 self.assertEqual(kwonlyargs, kwonlyargs_e)
765 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
766 self.assertEqual(ann, ann_e)
767 if formatted is not None:
Matthias Bussonnier46c5cd02018-06-11 22:08:16 +0200768 with self.assertWarns(DeprecationWarning):
769 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
770 kwonlyargs, kwonlydefaults, ann),
Christian Heimes3795b532007-11-08 13:48:53 +0000771 formatted)
772
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500773 def test_getargspec(self):
774 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
775
776 self.assertArgSpecEquals(mod.spam,
777 ['a', 'b', 'c', 'd', 'e', 'f'],
778 'g', 'h', (3, 4, 5),
779 '(a, b, c, d=3, e=4, f=5, *g, **h)')
780
781 self.assertRaises(ValueError, self.assertArgSpecEquals,
782 mod2.keyworded, [])
783
784 self.assertRaises(ValueError, self.assertArgSpecEquals,
785 mod2.annotated, [])
786 self.assertRaises(ValueError, self.assertArgSpecEquals,
787 mod2.keyword_only_arg, [])
788
789
Christian Heimes3795b532007-11-08 13:48:53 +0000790 def test_getfullargspec(self):
791 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
792 kwonlyargs_e=['arg2'],
793 kwonlydefaults_e={'arg2':1},
794 formatted='(*arg1, arg2=1)')
795
796 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000797 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000798 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000799 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
800 kwonlyargs_e=['arg'],
801 formatted='(*, arg)')
802
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500803 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500804 # Issue 20684: low level introspection API must ignore __wrapped__
805 @functools.wraps(mod.spam)
806 def ham(x, y):
807 pass
808 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500809 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500810 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
811 self.assertFullArgSpecEquals(functools.partial(ham),
812 ['x', 'y'], formatted='(x, y)')
813 # Other variants
814 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500815 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
816 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500817 class C:
818 @functools.wraps(mod.spam)
819 def ham(self, x, y):
820 pass
821 pham = functools.partialmethod(ham)
822 @functools.wraps(mod.spam)
823 def __call__(self, x, y):
824 pass
825 check_method(C())
826 check_method(C.ham)
827 check_method(C().ham)
828 check_method(C.pham)
829 check_method(C().pham)
830
831 class C_new:
832 @functools.wraps(mod.spam)
833 def __new__(self, x, y):
834 pass
835 check_method(C_new)
836
837 class C_init:
838 @functools.wraps(mod.spam)
839 def __init__(self, x, y):
840 pass
841 check_method(C_init)
842
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500843 def test_getfullargspec_signature_attr(self):
844 def test():
845 pass
846 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
847 test.__signature__ = inspect.Signature(parameters=(spam_param,))
848
849 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
850
Yury Selivanov4cb93912014-01-29 11:54:12 -0500851 def test_getfullargspec_signature_annos(self):
852 def test(a:'spam') -> 'ham': pass
853 spec = inspect.getfullargspec(test)
854 self.assertEqual(test.__annotations__, spec.annotations)
855
856 def test(): pass
857 spec = inspect.getfullargspec(test)
858 self.assertEqual(test.__annotations__, spec.annotations)
859
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500860 @unittest.skipIf(MISSING_C_DOCSTRINGS,
861 "Signature information for builtins requires docstrings")
862 def test_getfullargspec_builtin_methods(self):
863 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
864 args_e=['self', 'obj'], formatted='(self, obj)')
865
866 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
867 args_e=['self', 'obj'], formatted='(self, obj)')
868
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500869 self.assertFullArgSpecEquals(
870 os.stat,
871 args_e=['path'],
872 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
873 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
874 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
875
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200876 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500877 @unittest.skipIf(MISSING_C_DOCSTRINGS,
878 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800879 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200880 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500881 builtin = _testcapi.docstring_with_signature_with_defaults
882 spec = inspect.getfullargspec(builtin)
883 self.assertEqual(spec.defaults[0], 'avocado')
884
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200885 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500886 @unittest.skipIf(MISSING_C_DOCSTRINGS,
887 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800888 def test_getfullargspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200889 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500890 builtin = _testcapi.docstring_no_signature
891 with self.assertRaises(TypeError):
892 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000893
larryhastingsf36ba122018-01-28 11:13:09 -0800894 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
895 for fn in signatures_with_lexicographic_keyword_only_parameters():
896 signature = inspect.getfullargspec(fn)
897 l = list(signature.kwonlyargs)
898 sorted_l = sorted(l)
899 self.assertTrue(l)
900 self.assertEqual(l, sorted_l)
901 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
902 l = list(signature.kwonlyargs)
903 self.assertEqual(l, unsorted_keyword_only_parameters)
904
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500905 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000906 class A(object):
907 def m(self):
908 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500909 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000910
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000911 def test_classify_newstyle(self):
912 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000913
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000914 def s(): pass
915 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000916
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000917 def c(cls): pass
918 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000919
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000920 def getp(self): pass
921 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000922
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000923 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000924
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000925 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000926
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000927 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000928
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100929 dd = _BrokenDataDescriptor()
930 md = _BrokenMethodDescriptor()
931
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000932 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500933
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +0200934 self.assertIn(('__new__', 'static method', object), attrs,
935 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500936 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
937
Benjamin Peterson577473f2010-01-19 00:09:57 +0000938 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
939 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
940 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000941 self.assertIn(('m', 'method', A), attrs,
942 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000943 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
944 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100945 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
946 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000947
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000948 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000949
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000950 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000951
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000952 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000953 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
954 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
955 self.assertIn(('p', 'property', A), attrs, 'missing property')
956 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
957 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
958 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100959 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
960 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000961
962
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000963 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000964
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000965 def m(self): pass
966 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000967
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000968 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000969 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
970 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
971 self.assertIn(('p', 'property', A), attrs, 'missing property')
972 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
973 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
974 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100975 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
976 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000977
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000978 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000979
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000980 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000981
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000982 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000983 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
984 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
985 self.assertIn(('p', 'property', A), attrs, 'missing property')
986 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
987 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
988 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100989 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
990 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
991
992 def test_classify_builtin_types(self):
993 # Simple sanity check that all built-in types can have their
994 # attributes classified.
995 for name in dir(__builtins__):
996 builtin = getattr(__builtins__, name)
997 if isinstance(builtin, type):
998 inspect.classify_class_attrs(builtin)
999
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001000 attrs = attrs_wo_objs(bool)
1001 self.assertIn(('__new__', 'static method', bool), attrs,
1002 'missing __new__')
1003 self.assertIn(('from_bytes', 'class method', int), attrs,
1004 'missing class method')
1005 self.assertIn(('to_bytes', 'method', int), attrs,
1006 'missing plain method')
1007 self.assertIn(('__add__', 'method', int), attrs,
1008 'missing plain method')
1009 self.assertIn(('__and__', 'method', bool), attrs,
1010 'missing plain method')
1011
Ethan Furman63c141c2013-10-18 00:27:39 -07001012 def test_classify_DynamicClassAttribute(self):
1013 class Meta(type):
1014 def __getattr__(self, name):
1015 if name == 'ham':
1016 return 'spam'
1017 return super().__getattr__(name)
1018 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001019 @types.DynamicClassAttribute
1020 def ham(self):
1021 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001022 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1023 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001024 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001025 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1026
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001027 def test_classify_overrides_bool(self):
1028 class NoBool(object):
1029 def __eq__(self, other):
1030 return NoBool()
1031
1032 def __bool__(self):
1033 raise NotImplementedError(
1034 "This object does not specify a boolean value")
1035
1036 class HasNB(object):
1037 dd = NoBool()
1038
1039 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1040 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1041
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001042 def test_classify_metaclass_class_attribute(self):
1043 class Meta(type):
1044 fish = 'slap'
1045 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001046 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001047 class Class(metaclass=Meta):
1048 pass
1049 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1050 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1051
Ethan Furman63c141c2013-10-18 00:27:39 -07001052 def test_classify_VirtualAttribute(self):
1053 class Meta(type):
1054 def __dir__(cls):
1055 return ['__class__', '__module__', '__name__', 'BOOM']
1056 def __getattr__(self, name):
1057 if name =='BOOM':
1058 return 42
1059 return super().__getattr(name)
1060 class Class(metaclass=Meta):
1061 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001062 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001063 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1064
1065 def test_classify_VirtualAttribute_multi_classes(self):
1066 class Meta1(type):
1067 def __dir__(cls):
1068 return ['__class__', '__module__', '__name__', 'one']
1069 def __getattr__(self, name):
1070 if name =='one':
1071 return 1
1072 return super().__getattr__(name)
1073 class Meta2(type):
1074 def __dir__(cls):
1075 return ['__class__', '__module__', '__name__', 'two']
1076 def __getattr__(self, name):
1077 if name =='two':
1078 return 2
1079 return super().__getattr__(name)
1080 class Meta3(Meta1, Meta2):
1081 def __dir__(cls):
1082 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1083 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1084 def __getattr__(self, name):
1085 if name =='three':
1086 return 3
1087 return super().__getattr__(name)
1088 class Class1(metaclass=Meta1):
1089 pass
1090 class Class2(Class1, metaclass=Meta3):
1091 pass
1092
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001093 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1094 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1095 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001096 cca = inspect.classify_class_attrs(Class2)
1097 for sf in (should_find1, should_find2, should_find3):
1098 self.assertIn(sf, cca)
1099
1100 def test_classify_class_attrs_with_buggy_dir(self):
1101 class M(type):
1102 def __dir__(cls):
1103 return ['__class__', '__name__', 'missing']
1104 class C(metaclass=M):
1105 pass
1106 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1107 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001108
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001109 def test_getmembers_descriptors(self):
1110 class A(object):
1111 dd = _BrokenDataDescriptor()
1112 md = _BrokenMethodDescriptor()
1113
1114 def pred_wrapper(pred):
1115 # A quick'n'dirty way to discard standard attributes of new-style
1116 # classes.
1117 class Empty(object):
1118 pass
1119 def wrapped(x):
1120 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1121 return False
1122 return pred(x)
1123 return wrapped
1124
1125 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1126 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1127
1128 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1129 [('md', A.__dict__['md'])])
1130 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1131 [('dd', A.__dict__['dd'])])
1132
1133 class B(A):
1134 pass
1135
1136 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1137 [('md', A.__dict__['md'])])
1138 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1139 [('dd', A.__dict__['dd'])])
1140
Antoine Pitrou0c603812012-01-18 17:40:18 +01001141 def test_getmembers_method(self):
1142 class B:
1143 def f(self):
1144 pass
1145
1146 self.assertIn(('f', B.f), inspect.getmembers(B))
1147 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1148 b = B()
1149 self.assertIn(('f', b.f), inspect.getmembers(b))
1150 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1151
Ethan Furmane03ea372013-09-25 07:14:41 -07001152 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001153 class M(type):
1154 def __getattr__(cls, name):
1155 if name == 'eggs':
1156 return 'scrambled'
1157 return super().__getattr__(name)
1158 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001159 @types.DynamicClassAttribute
1160 def eggs(self):
1161 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001162 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1163 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1164
1165 def test_getmembers_with_buggy_dir(self):
1166 class M(type):
1167 def __dir__(cls):
1168 return ['__class__', '__name__', 'missing']
1169 class C(metaclass=M):
1170 pass
1171 attrs = [a[0] for a in inspect.getmembers(C)]
1172 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001173
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001174class TestIsDataDescriptor(unittest.TestCase):
1175
1176 def test_custom_descriptors(self):
1177 class NonDataDescriptor:
1178 def __get__(self, value, type=None): pass
1179 class DataDescriptor0:
1180 def __set__(self, name, value): pass
1181 class DataDescriptor1:
1182 def __delete__(self, name): pass
1183 class DataDescriptor2:
1184 __set__ = None
1185 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1186 'class with only __get__ not a data descriptor')
1187 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1188 'class with __set__ is a data descriptor')
1189 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1190 'class with __delete__ is a data descriptor')
1191 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1192 'class with __set__ = None is a data descriptor')
1193
1194 def test_slot(self):
1195 class Slotted:
1196 __slots__ = 'foo',
1197 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1198 'a slot is a data descriptor')
1199
1200 def test_property(self):
1201 class Propertied:
1202 @property
1203 def a_property(self):
1204 pass
1205 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1206 'a property is a data descriptor')
1207
1208 def test_functions(self):
1209 class Test(object):
1210 def instance_method(self): pass
1211 @classmethod
1212 def class_method(cls): pass
1213 @staticmethod
1214 def static_method(): pass
1215 def function():
1216 pass
1217 a_lambda = lambda: None
1218 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1219 'a instance method is not a data descriptor')
1220 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1221 'a class method is not a data descriptor')
1222 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1223 'a static method is not a data descriptor')
1224 self.assertFalse(inspect.isdatadescriptor(function),
1225 'a function is not a data descriptor')
1226 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1227 'a lambda is not a data descriptor')
1228
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001229
Nick Coghlan2f92e542012-06-23 19:39:55 +10001230_global_ref = object()
1231class TestGetClosureVars(unittest.TestCase):
1232
1233 def test_name_resolution(self):
1234 # Basic test of the 4 different resolution mechanisms
1235 def f(nonlocal_ref):
1236 def g(local_ref):
1237 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1238 return g
1239 _arg = object()
1240 nonlocal_vars = {"nonlocal_ref": _arg}
1241 global_vars = {"_global_ref": _global_ref}
1242 builtin_vars = {"print": print}
1243 unbound_names = {"unbound_ref"}
1244 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1245 builtin_vars, unbound_names)
1246 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1247
1248 def test_generator_closure(self):
1249 def f(nonlocal_ref):
1250 def g(local_ref):
1251 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1252 yield
1253 return g
1254 _arg = object()
1255 nonlocal_vars = {"nonlocal_ref": _arg}
1256 global_vars = {"_global_ref": _global_ref}
1257 builtin_vars = {"print": print}
1258 unbound_names = {"unbound_ref"}
1259 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1260 builtin_vars, unbound_names)
1261 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1262
1263 def test_method_closure(self):
1264 class C:
1265 def f(self, nonlocal_ref):
1266 def g(local_ref):
1267 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1268 return g
1269 _arg = object()
1270 nonlocal_vars = {"nonlocal_ref": _arg}
1271 global_vars = {"_global_ref": _global_ref}
1272 builtin_vars = {"print": print}
1273 unbound_names = {"unbound_ref"}
1274 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1275 builtin_vars, unbound_names)
1276 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1277
1278 def test_nonlocal_vars(self):
1279 # More complex tests of nonlocal resolution
1280 def _nonlocal_vars(f):
1281 return inspect.getclosurevars(f).nonlocals
1282
1283 def make_adder(x):
1284 def add(y):
1285 return x + y
1286 return add
1287
1288 def curry(func, arg1):
1289 return lambda arg2: func(arg1, arg2)
1290
1291 def less_than(a, b):
1292 return a < b
1293
1294 # The infamous Y combinator.
1295 def Y(le):
1296 def g(f):
1297 return le(lambda x: f(f)(x))
1298 Y.g_ref = g
1299 return g(g)
1300
1301 def check_y_combinator(func):
1302 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1303
1304 inc = make_adder(1)
1305 add_two = make_adder(2)
1306 greater_than_five = curry(less_than, 5)
1307
1308 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1309 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1310 self.assertEqual(_nonlocal_vars(greater_than_five),
1311 {'arg1': 5, 'func': less_than})
1312 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1313 {'x': 3})
1314 Y(check_y_combinator)
1315
1316 def test_getclosurevars_empty(self):
1317 def foo(): pass
1318 _empty = inspect.ClosureVars({}, {}, {}, set())
1319 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1320 self.assertEqual(inspect.getclosurevars(foo), _empty)
1321
1322 def test_getclosurevars_error(self):
1323 class T: pass
1324 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1325 self.assertRaises(TypeError, inspect.getclosurevars, list)
1326 self.assertRaises(TypeError, inspect.getclosurevars, {})
1327
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001328 def _private_globals(self):
1329 code = """def f(): print(path)"""
1330 ns = {}
1331 exec(code, ns)
1332 return ns["f"], ns
1333
1334 def test_builtins_fallback(self):
1335 f, ns = self._private_globals()
1336 ns.pop("__builtins__", None)
1337 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1338 self.assertEqual(inspect.getclosurevars(f), expected)
1339
1340 def test_builtins_as_dict(self):
1341 f, ns = self._private_globals()
1342 ns["__builtins__"] = {"path":1}
1343 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1344 self.assertEqual(inspect.getclosurevars(f), expected)
1345
1346 def test_builtins_as_module(self):
1347 f, ns = self._private_globals()
1348 ns["__builtins__"] = os
1349 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1350 self.assertEqual(inspect.getclosurevars(f), expected)
1351
Nick Coghlan2f92e542012-06-23 19:39:55 +10001352
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001353class TestGetcallargsFunctions(unittest.TestCase):
1354
1355 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1356 locs = dict(locs or {}, func=func)
1357 r1 = eval('func(%s)' % call_params_string, None, locs)
1358 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1359 locs)
1360 self.assertEqual(r1, r2)
1361
1362 def assertEqualException(self, func, call_param_string, locs=None):
1363 locs = dict(locs or {}, func=func)
1364 try:
1365 eval('func(%s)' % call_param_string, None, locs)
1366 except Exception as e:
1367 ex1 = e
1368 else:
1369 self.fail('Exception not raised')
1370 try:
1371 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1372 locs)
1373 except Exception as e:
1374 ex2 = e
1375 else:
1376 self.fail('Exception not raised')
1377 self.assertIs(type(ex1), type(ex2))
1378 self.assertEqual(str(ex1), str(ex2))
1379 del ex1, ex2
1380
1381 def makeCallable(self, signature):
1382 """Create a function that returns its locals()"""
1383 code = "lambda %s: locals()"
1384 return eval(code % signature)
1385
1386 def test_plain(self):
1387 f = self.makeCallable('a, b=1')
1388 self.assertEqualCallArgs(f, '2')
1389 self.assertEqualCallArgs(f, '2, 3')
1390 self.assertEqualCallArgs(f, 'a=2')
1391 self.assertEqualCallArgs(f, 'b=3, a=2')
1392 self.assertEqualCallArgs(f, '2, b=3')
1393 # expand *iterable / **mapping
1394 self.assertEqualCallArgs(f, '*(2,)')
1395 self.assertEqualCallArgs(f, '*[2]')
1396 self.assertEqualCallArgs(f, '*(2, 3)')
1397 self.assertEqualCallArgs(f, '*[2, 3]')
1398 self.assertEqualCallArgs(f, '**{"a":2}')
1399 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1400 self.assertEqualCallArgs(f, '2, **{"b":3}')
1401 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1402 # expand UserList / UserDict
1403 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1404 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1405 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1406 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1407 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1408
1409 def test_varargs(self):
1410 f = self.makeCallable('a, b=1, *c')
1411 self.assertEqualCallArgs(f, '2')
1412 self.assertEqualCallArgs(f, '2, 3')
1413 self.assertEqualCallArgs(f, '2, 3, 4')
1414 self.assertEqualCallArgs(f, '*(2,3,4)')
1415 self.assertEqualCallArgs(f, '2, *[3,4]')
1416 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1417
1418 def test_varkw(self):
1419 f = self.makeCallable('a, b=1, **c')
1420 self.assertEqualCallArgs(f, 'a=2')
1421 self.assertEqualCallArgs(f, '2, b=3, c=4')
1422 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1423 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1424 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1425 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1426 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1427 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1428 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1429
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001430 def test_varkw_only(self):
1431 # issue11256:
1432 f = self.makeCallable('**c')
1433 self.assertEqualCallArgs(f, '')
1434 self.assertEqualCallArgs(f, 'a=1')
1435 self.assertEqualCallArgs(f, 'a=1, b=2')
1436 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1437 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1438 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1439
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001440 def test_keyword_only(self):
1441 f = self.makeCallable('a=3, *, c, d=2')
1442 self.assertEqualCallArgs(f, 'c=3')
1443 self.assertEqualCallArgs(f, 'c=3, a=3')
1444 self.assertEqualCallArgs(f, 'a=2, c=4')
1445 self.assertEqualCallArgs(f, '4, c=4')
1446 self.assertEqualException(f, '')
1447 self.assertEqualException(f, '3')
1448 self.assertEqualException(f, 'a=3')
1449 self.assertEqualException(f, 'd=4')
1450
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001451 f = self.makeCallable('*, c, d=2')
1452 self.assertEqualCallArgs(f, 'c=3')
1453 self.assertEqualCallArgs(f, 'c=3, d=4')
1454 self.assertEqualCallArgs(f, 'd=4, c=3')
1455
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001456 def test_multiple_features(self):
1457 f = self.makeCallable('a, b=2, *f, **g')
1458 self.assertEqualCallArgs(f, '2, 3, 7')
1459 self.assertEqualCallArgs(f, '2, 3, x=8')
1460 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1461 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1462 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1463 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1464 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1465 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1466 '(4,[5,6])]), **collections.UserDict('
1467 'y=9, z=10)')
1468
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001469 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1470 self.assertEqualCallArgs(f, '2, 3, x=8')
1471 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1472 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1473 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1474 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1475 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1476 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1477 '(4,[5,6])]), q=0, **collections.UserDict('
1478 'y=9, z=10)')
1479
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001480 def test_errors(self):
1481 f0 = self.makeCallable('')
1482 f1 = self.makeCallable('a, b')
1483 f2 = self.makeCallable('a, b=1')
1484 # f0 takes no arguments
1485 self.assertEqualException(f0, '1')
1486 self.assertEqualException(f0, 'x=1')
1487 self.assertEqualException(f0, '1,x=1')
1488 # f1 takes exactly 2 arguments
1489 self.assertEqualException(f1, '')
1490 self.assertEqualException(f1, '1')
1491 self.assertEqualException(f1, 'a=2')
1492 self.assertEqualException(f1, 'b=3')
1493 # f2 takes at least 1 argument
1494 self.assertEqualException(f2, '')
1495 self.assertEqualException(f2, 'b=3')
1496 for f in f1, f2:
1497 # f1/f2 takes exactly/at most 2 arguments
1498 self.assertEqualException(f, '2, 3, 4')
1499 self.assertEqualException(f, '1, 2, 3, a=1')
1500 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001501 # XXX: success of this one depends on dict order
1502 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001503 # f got an unexpected keyword argument
1504 self.assertEqualException(f, 'c=2')
1505 self.assertEqualException(f, '2, c=3')
1506 self.assertEqualException(f, '2, 3, c=4')
1507 self.assertEqualException(f, '2, c=4, b=3')
1508 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1509 # f got multiple values for keyword argument
1510 self.assertEqualException(f, '1, a=2')
1511 self.assertEqualException(f, '1, **{"a":2}')
1512 self.assertEqualException(f, '1, 2, b=3')
1513 # XXX: Python inconsistency
1514 # - for functions and bound methods: unexpected keyword 'c'
1515 # - for unbound methods: multiple values for keyword 'a'
1516 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001517 # issue11256:
1518 f3 = self.makeCallable('**c')
1519 self.assertEqualException(f3, '1, 2')
1520 self.assertEqualException(f3, '1, 2, a=1, b=2')
1521 f4 = self.makeCallable('*, a, b=0')
1522 self.assertEqualException(f3, '1, 2')
1523 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001524
Yury Selivanov875df202014-03-27 18:23:03 -04001525 # issue #20816: getcallargs() fails to iterate over non-existent
1526 # kwonlydefaults and raises a wrong TypeError
1527 def f5(*, a): pass
1528 with self.assertRaisesRegex(TypeError,
1529 'missing 1 required keyword-only'):
1530 inspect.getcallargs(f5)
1531
1532
Yury Selivanovdccfa132014-03-27 18:42:52 -04001533 # issue20817:
1534 def f6(a, b, c):
1535 pass
1536 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1537 inspect.getcallargs(f6)
1538
Dong-hee Naa9cab432018-05-30 00:04:08 +09001539 # bpo-33197
1540 with self.assertRaisesRegex(ValueError,
1541 'variadic keyword parameters cannot'
1542 ' have default values'):
1543 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1544 default=42)
1545 with self.assertRaisesRegex(ValueError,
1546 "value 5 is not a valid Parameter.kind"):
1547 inspect.Parameter("bar", kind=5, default=42)
1548
1549 with self.assertRaisesRegex(TypeError,
1550 'name must be a str, not a int'):
1551 inspect.Parameter(123, kind=4)
1552
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001553class TestGetcallargsMethods(TestGetcallargsFunctions):
1554
1555 def setUp(self):
1556 class Foo(object):
1557 pass
1558 self.cls = Foo
1559 self.inst = Foo()
1560
1561 def makeCallable(self, signature):
1562 assert 'self' not in signature
1563 mk = super(TestGetcallargsMethods, self).makeCallable
1564 self.cls.method = mk('self, ' + signature)
1565 return self.inst.method
1566
1567class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1568
1569 def makeCallable(self, signature):
1570 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1571 return self.cls.method
1572
1573 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1574 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1575 *self._getAssertEqualParams(func, call_params_string, locs))
1576
1577 def assertEqualException(self, func, call_params_string, locs=None):
1578 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1579 *self._getAssertEqualParams(func, call_params_string, locs))
1580
1581 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1582 assert 'inst' not in call_params_string
1583 locs = dict(locs or {}, inst=self.inst)
1584 return (func, 'inst,' + call_params_string, locs)
1585
Michael Foord95fc51d2010-11-20 15:07:30 +00001586
1587class TestGetattrStatic(unittest.TestCase):
1588
1589 def test_basic(self):
1590 class Thing(object):
1591 x = object()
1592
1593 thing = Thing()
1594 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1595 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1596 with self.assertRaises(AttributeError):
1597 inspect.getattr_static(thing, 'y')
1598
1599 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1600
1601 def test_inherited(self):
1602 class Thing(object):
1603 x = object()
1604 class OtherThing(Thing):
1605 pass
1606
1607 something = OtherThing()
1608 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1609
1610 def test_instance_attr(self):
1611 class Thing(object):
1612 x = 2
1613 def __init__(self, x):
1614 self.x = x
1615 thing = Thing(3)
1616 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1617 del thing.x
1618 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1619
1620 def test_property(self):
1621 class Thing(object):
1622 @property
1623 def x(self):
1624 raise AttributeError("I'm pretending not to exist")
1625 thing = Thing()
1626 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1627
Ezio Melotti75cbd732011-04-28 00:59:29 +03001628 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001629 class descriptor(object):
1630 def __get__(*_):
1631 raise AttributeError("I'm pretending not to exist")
1632 desc = descriptor()
1633 class Thing(object):
1634 x = desc
1635 thing = Thing()
1636 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1637
1638 def test_classAttribute(self):
1639 class Thing(object):
1640 x = object()
1641
1642 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1643
Ethan Furmane03ea372013-09-25 07:14:41 -07001644 def test_classVirtualAttribute(self):
1645 class Thing(object):
1646 @types.DynamicClassAttribute
1647 def x(self):
1648 return self._x
1649 _x = object()
1650
1651 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1652
Michael Foord95fc51d2010-11-20 15:07:30 +00001653 def test_inherited_classattribute(self):
1654 class Thing(object):
1655 x = object()
1656 class OtherThing(Thing):
1657 pass
1658
1659 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1660
1661 def test_slots(self):
1662 class Thing(object):
1663 y = 'bar'
1664 __slots__ = ['x']
1665 def __init__(self):
1666 self.x = 'foo'
1667 thing = Thing()
1668 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1669 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1670
1671 del thing.x
1672 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1673
1674 def test_metaclass(self):
1675 class meta(type):
1676 attr = 'foo'
1677 class Thing(object, metaclass=meta):
1678 pass
1679 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1680
1681 class sub(meta):
1682 pass
1683 class OtherThing(object, metaclass=sub):
1684 x = 3
1685 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1686
1687 class OtherOtherThing(OtherThing):
1688 pass
1689 # this test is odd, but it was added as it exposed a bug
1690 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1691
1692 def test_no_dict_no_slots(self):
1693 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1694 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1695
1696 def test_no_dict_no_slots_instance_member(self):
1697 # returns descriptor
1698 with open(__file__) as handle:
1699 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1700
1701 def test_inherited_slots(self):
1702 # returns descriptor
1703 class Thing(object):
1704 __slots__ = ['x']
1705 def __init__(self):
1706 self.x = 'foo'
1707
1708 class OtherThing(Thing):
1709 pass
1710 # it would be nice if this worked...
1711 # we get the descriptor instead of the instance attribute
1712 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1713
1714 def test_descriptor(self):
1715 class descriptor(object):
1716 def __get__(self, instance, owner):
1717 return 3
1718 class Foo(object):
1719 d = descriptor()
1720
1721 foo = Foo()
1722
1723 # for a non data descriptor we return the instance attribute
1724 foo.__dict__['d'] = 1
1725 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1726
Mike53f7a7c2017-12-14 14:04:53 +03001727 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001728 # descriptor
1729 descriptor.__set__ = lambda s, i, v: None
1730 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1731
1732
1733 def test_metaclass_with_descriptor(self):
1734 class descriptor(object):
1735 def __get__(self, instance, owner):
1736 return 3
1737 class meta(type):
1738 d = descriptor()
1739 class Thing(object, metaclass=meta):
1740 pass
1741 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1742
1743
Michael Foordcc7ebb82010-11-20 16:20:16 +00001744 def test_class_as_property(self):
1745 class Base(object):
1746 foo = 3
1747
1748 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001749 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001750 @property
1751 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001752 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001753 return object
1754
Michael Foord35184ed2010-11-20 16:58:30 +00001755 instance = Something()
1756 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1757 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001758 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1759
Michael Foorde5162652010-11-20 16:40:44 +00001760 def test_mro_as_property(self):
1761 class Meta(type):
1762 @property
1763 def __mro__(self):
1764 return (object,)
1765
1766 class Base(object):
1767 foo = 3
1768
1769 class Something(Base, metaclass=Meta):
1770 pass
1771
1772 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1773 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1774
Michael Foorddcebe0f2011-03-15 19:20:44 -04001775 def test_dict_as_property(self):
1776 test = self
1777 test.called = False
1778
1779 class Foo(dict):
1780 a = 3
1781 @property
1782 def __dict__(self):
1783 test.called = True
1784 return {}
1785
1786 foo = Foo()
1787 foo.a = 4
1788 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1789 self.assertFalse(test.called)
1790
1791 def test_custom_object_dict(self):
1792 test = self
1793 test.called = False
1794
1795 class Custom(dict):
1796 def get(self, key, default=None):
1797 test.called = True
1798 super().get(key, default)
1799
1800 class Foo(object):
1801 a = 3
1802 foo = Foo()
1803 foo.__dict__ = Custom()
1804 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1805 self.assertFalse(test.called)
1806
1807 def test_metaclass_dict_as_property(self):
1808 class Meta(type):
1809 @property
1810 def __dict__(self):
1811 self.executed = True
1812
1813 class Thing(metaclass=Meta):
1814 executed = False
1815
1816 def __init__(self):
1817 self.spam = 42
1818
1819 instance = Thing()
1820 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1821 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001822
Michael Foorda51623b2011-12-18 22:01:40 +00001823 def test_module(self):
1824 sentinel = object()
1825 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1826 sentinel)
1827
Michael Foord3ba95f82011-12-22 01:13:37 +00001828 def test_metaclass_with_metaclass_with_dict_as_property(self):
1829 class MetaMeta(type):
1830 @property
1831 def __dict__(self):
1832 self.executed = True
1833 return dict(spam=42)
1834
1835 class Meta(type, metaclass=MetaMeta):
1836 executed = False
1837
1838 class Thing(metaclass=Meta):
1839 pass
1840
1841 with self.assertRaises(AttributeError):
1842 inspect.getattr_static(Thing, "spam")
1843 self.assertFalse(Thing.executed)
1844
Nick Coghlane0f04652010-11-21 03:44:04 +00001845class TestGetGeneratorState(unittest.TestCase):
1846
1847 def setUp(self):
1848 def number_generator():
1849 for number in range(5):
1850 yield number
1851 self.generator = number_generator()
1852
1853 def _generatorstate(self):
1854 return inspect.getgeneratorstate(self.generator)
1855
1856 def test_created(self):
1857 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1858
1859 def test_suspended(self):
1860 next(self.generator)
1861 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1862
1863 def test_closed_after_exhaustion(self):
1864 for i in self.generator:
1865 pass
1866 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1867
1868 def test_closed_after_immediate_exception(self):
1869 with self.assertRaises(RuntimeError):
1870 self.generator.throw(RuntimeError)
1871 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1872
1873 def test_running(self):
1874 # As mentioned on issue #10220, checking for the RUNNING state only
1875 # makes sense inside the generator itself.
1876 # The following generator checks for this by using the closure's
1877 # reference to self and the generator state checking helper method
1878 def running_check_generator():
1879 for number in range(5):
1880 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1881 yield number
1882 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1883 self.generator = running_check_generator()
1884 # Running up to the first yield
1885 next(self.generator)
1886 # Running after the first yield
1887 next(self.generator)
1888
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001889 def test_easy_debugging(self):
1890 # repr() and str() of a generator state should contain the state name
1891 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1892 for name in names:
1893 state = getattr(inspect, name)
1894 self.assertIn(name, repr(state))
1895 self.assertIn(name, str(state))
1896
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001897 def test_getgeneratorlocals(self):
1898 def each(lst, a=None):
1899 b=(1, 2, 3)
1900 for v in lst:
1901 if v == 3:
1902 c = 12
1903 yield v
1904
1905 numbers = each([1, 2, 3])
1906 self.assertEqual(inspect.getgeneratorlocals(numbers),
1907 {'a': None, 'lst': [1, 2, 3]})
1908 next(numbers)
1909 self.assertEqual(inspect.getgeneratorlocals(numbers),
1910 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1911 'b': (1, 2, 3)})
1912 next(numbers)
1913 self.assertEqual(inspect.getgeneratorlocals(numbers),
1914 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1915 'b': (1, 2, 3)})
1916 next(numbers)
1917 self.assertEqual(inspect.getgeneratorlocals(numbers),
1918 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1919 'b': (1, 2, 3), 'c': 12})
1920 try:
1921 next(numbers)
1922 except StopIteration:
1923 pass
1924 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1925
1926 def test_getgeneratorlocals_empty(self):
1927 def yield_one():
1928 yield 1
1929 one = yield_one()
1930 self.assertEqual(inspect.getgeneratorlocals(one), {})
1931 try:
1932 next(one)
1933 except StopIteration:
1934 pass
1935 self.assertEqual(inspect.getgeneratorlocals(one), {})
1936
1937 def test_getgeneratorlocals_error(self):
1938 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1939 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1940 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1941 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1942
Nick Coghlane0f04652010-11-21 03:44:04 +00001943
Yury Selivanov5376ba92015-06-22 12:19:30 -04001944class TestGetCoroutineState(unittest.TestCase):
1945
1946 def setUp(self):
1947 @types.coroutine
1948 def number_coroutine():
1949 for number in range(5):
1950 yield number
1951 async def coroutine():
1952 await number_coroutine()
1953 self.coroutine = coroutine()
1954
1955 def tearDown(self):
1956 self.coroutine.close()
1957
1958 def _coroutinestate(self):
1959 return inspect.getcoroutinestate(self.coroutine)
1960
1961 def test_created(self):
1962 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
1963
1964 def test_suspended(self):
1965 self.coroutine.send(None)
1966 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
1967
1968 def test_closed_after_exhaustion(self):
1969 while True:
1970 try:
1971 self.coroutine.send(None)
1972 except StopIteration:
1973 break
1974
1975 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1976
1977 def test_closed_after_immediate_exception(self):
1978 with self.assertRaises(RuntimeError):
1979 self.coroutine.throw(RuntimeError)
1980 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
1981
1982 def test_easy_debugging(self):
1983 # repr() and str() of a coroutine state should contain the state name
1984 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
1985 for name in names:
1986 state = getattr(inspect, name)
1987 self.assertIn(name, repr(state))
1988 self.assertIn(name, str(state))
1989
1990 def test_getcoroutinelocals(self):
1991 @types.coroutine
1992 def gencoro():
1993 yield
1994
1995 gencoro = gencoro()
1996 async def func(a=None):
1997 b = 'spam'
1998 await gencoro
1999
2000 coro = func()
2001 self.assertEqual(inspect.getcoroutinelocals(coro),
2002 {'a': None, 'gencoro': gencoro})
2003 coro.send(None)
2004 self.assertEqual(inspect.getcoroutinelocals(coro),
2005 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2006
2007
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002008class MySignature(inspect.Signature):
2009 # Top-level to make it picklable;
2010 # used in test_signature_object_pickle
2011 pass
2012
2013class MyParameter(inspect.Parameter):
2014 # Top-level to make it picklable;
2015 # used in test_signature_object_pickle
2016 pass
2017
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002018
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002019
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002020class TestSignatureObject(unittest.TestCase):
2021 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002022 def signature(func, **kw):
2023 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002024 return (tuple((param.name,
2025 (... if param.default is param.empty else param.default),
2026 (... if param.annotation is param.empty
2027 else param.annotation),
2028 str(param.kind).lower())
2029 for param in sig.parameters.values()),
2030 (... if sig.return_annotation is sig.empty
2031 else sig.return_annotation))
2032
2033 def test_signature_object(self):
2034 S = inspect.Signature
2035 P = inspect.Parameter
2036
2037 self.assertEqual(str(S()), '()')
2038
Yury Selivanov07a9e452014-01-29 10:58:16 -05002039 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002040 pass
2041 sig = inspect.signature(test)
2042 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002043 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002044 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002045 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002046 args = sig.parameters['args']
2047 ko = sig.parameters['ko']
2048 kwargs = sig.parameters['kwargs']
2049
2050 S((po, pk, args, ko, kwargs))
2051
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002052 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002053 S((pk, po, args, ko, kwargs))
2054
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002055 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002056 S((po, args, pk, ko, kwargs))
2057
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002058 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002059 S((args, po, pk, ko, kwargs))
2060
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002061 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002062 S((po, pk, args, kwargs, ko))
2063
2064 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002065 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002066 S((po, pk, args, kwargs2, ko))
2067
Yury Selivanov07a9e452014-01-29 10:58:16 -05002068 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2069 S((pod, po))
2070
2071 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2072 S((po, pkd, pk))
2073
2074 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2075 S((pkd, pk))
2076
Yury Selivanov374375d2014-03-27 12:41:53 -04002077 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002078 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002079
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002080 def test_signature_object_pickle(self):
2081 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2082 foo_partial = functools.partial(foo, a=1)
2083
2084 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002085
2086 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2087 with self.subTest(pickle_ver=ver, subclass=False):
2088 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2089 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002090
2091 # Test that basic sub-classing works
2092 sig = inspect.signature(foo)
2093 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2094 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2095 mysig = MySignature().replace(parameters=myparams.values(),
2096 return_annotation=sig.return_annotation)
2097 self.assertTrue(isinstance(mysig, MySignature))
2098 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2099
2100 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2101 with self.subTest(pickle_ver=ver, subclass=True):
2102 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2103 self.assertEqual(mysig, sig_pickled)
2104 self.assertTrue(isinstance(sig_pickled, MySignature))
2105 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2106 MyParameter))
2107
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002108 def test_signature_immutability(self):
2109 def test(a):
2110 pass
2111 sig = inspect.signature(test)
2112
2113 with self.assertRaises(AttributeError):
2114 sig.foo = 'bar'
2115
2116 with self.assertRaises(TypeError):
2117 sig.parameters['a'] = None
2118
2119 def test_signature_on_noarg(self):
2120 def test():
2121 pass
2122 self.assertEqual(self.signature(test), ((), ...))
2123
2124 def test_signature_on_wargs(self):
2125 def test(a, b:'foo') -> 123:
2126 pass
2127 self.assertEqual(self.signature(test),
2128 ((('a', ..., ..., "positional_or_keyword"),
2129 ('b', ..., 'foo', "positional_or_keyword")),
2130 123))
2131
2132 def test_signature_on_wkwonly(self):
2133 def test(*, a:float, b:str) -> int:
2134 pass
2135 self.assertEqual(self.signature(test),
2136 ((('a', ..., float, "keyword_only"),
2137 ('b', ..., str, "keyword_only")),
2138 int))
2139
2140 def test_signature_on_complex_args(self):
2141 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2142 pass
2143 self.assertEqual(self.signature(test),
2144 ((('a', ..., ..., "positional_or_keyword"),
2145 ('b', 10, 'foo', "positional_or_keyword"),
2146 ('args', ..., 'bar', "var_positional"),
2147 ('spam', ..., 'baz', "keyword_only"),
2148 ('ham', 123, ..., "keyword_only"),
2149 ('kwargs', ..., int, "var_keyword")),
2150 ...))
2151
Dong-hee Na378d7062017-05-18 04:00:51 +09002152 def test_signature_without_self(self):
2153 def test_args_only(*args): # NOQA
2154 pass
2155
2156 def test_args_kwargs_only(*args, **kwargs): # NOQA
2157 pass
2158
2159 class A:
2160 @classmethod
2161 def test_classmethod(*args): # NOQA
2162 pass
2163
2164 @staticmethod
2165 def test_staticmethod(*args): # NOQA
2166 pass
2167
2168 f1 = functools.partialmethod((test_classmethod), 1)
2169 f2 = functools.partialmethod((test_args_only), 1)
2170 f3 = functools.partialmethod((test_staticmethod), 1)
2171 f4 = functools.partialmethod((test_args_kwargs_only),1)
2172
2173 self.assertEqual(self.signature(test_args_only),
2174 ((('args', ..., ..., 'var_positional'),), ...))
2175 self.assertEqual(self.signature(test_args_kwargs_only),
2176 ((('args', ..., ..., 'var_positional'),
2177 ('kwargs', ..., ..., 'var_keyword')), ...))
2178 self.assertEqual(self.signature(A.f1),
2179 ((('args', ..., ..., 'var_positional'),), ...))
2180 self.assertEqual(self.signature(A.f2),
2181 ((('args', ..., ..., 'var_positional'),), ...))
2182 self.assertEqual(self.signature(A.f3),
2183 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002184 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002185 ((('args', ..., ..., 'var_positional'),
2186 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002187 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002188 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2189 "Signature information for builtins requires docstrings")
2190 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002191 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002192
Larry Hastings5c661892014-01-24 06:17:25 -08002193 def test_unbound_method(o):
2194 """Use this to test unbound methods (things that should have a self)"""
2195 signature = inspect.signature(o)
2196 self.assertTrue(isinstance(signature, inspect.Signature))
2197 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2198 return signature
2199
2200 def test_callable(o):
2201 """Use this to test bound methods or normal callables (things that don't expect self)"""
2202 signature = inspect.signature(o)
2203 self.assertTrue(isinstance(signature, inspect.Signature))
2204 if signature.parameters:
2205 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2206 return signature
2207
2208 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002209 def p(name): return signature.parameters[name].default
2210 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002211 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002212 self.assertEqual(p('d'), 3.14)
2213 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002214 self.assertEqual(p('n'), None)
2215 self.assertEqual(p('t'), True)
2216 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002217 self.assertEqual(p('local'), 3)
2218 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002219 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002220
Larry Hastings5c661892014-01-24 06:17:25 -08002221 test_callable(object)
2222
2223 # normal method
2224 # (PyMethodDescr_Type, "method_descriptor")
2225 test_unbound_method(_pickle.Pickler.dump)
2226 d = _pickle.Pickler(io.StringIO())
2227 test_callable(d.dump)
2228
2229 # static method
2230 test_callable(str.maketrans)
2231 test_callable('abc'.maketrans)
2232
2233 # class method
2234 test_callable(dict.fromkeys)
2235 test_callable({}.fromkeys)
2236
2237 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2238 test_unbound_method(type.__call__)
2239 test_unbound_method(int.__add__)
2240 test_callable((3).__add__)
2241
2242 # _PyMethodWrapper_Type
2243 # support for 'method-wrapper'
2244 test_callable(min.__call__)
2245
Larry Hastings2623c8c2014-02-08 22:15:29 -08002246 # This doesn't work now.
2247 # (We don't have a valid signature for "type" in 3.4)
2248 with self.assertRaisesRegex(ValueError, "no signature found"):
2249 class ThisWorksNow:
2250 __call__ = type
2251 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002252
Yury Selivanov056e2652014-03-02 12:25:27 -05002253 # Regression test for issue #20786
2254 test_unbound_method(dict.__delitem__)
2255 test_unbound_method(property.__delete__)
2256
Zachary Ware8ef887c2015-04-13 18:22:35 -05002257 # Regression test for issue #20586
2258 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2259
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002260 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002261 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2262 "Signature information for builtins requires docstrings")
2263 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002264 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002265 func = _testcapi.docstring_with_signature_with_defaults
2266
2267 def decorator(func):
2268 @functools.wraps(func)
2269 def wrapper(*args, **kwargs) -> int:
2270 return func(*args, **kwargs)
2271 return wrapper
2272
2273 decorated_func = decorator(func)
2274
2275 self.assertEqual(inspect.signature(func),
2276 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002277
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002278 def wrapper_like(*args, **kwargs) -> int: pass
2279 self.assertEqual(inspect.signature(decorated_func,
2280 follow_wrapped=False),
2281 inspect.signature(wrapper_like))
2282
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002283 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002284 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002285 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002286 with self.assertRaisesRegex(ValueError,
2287 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002288 inspect.signature(_testcapi.docstring_no_signature)
2289
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002290 with self.assertRaisesRegex(ValueError,
2291 'no signature found for builtin'):
2292 inspect.signature(str)
2293
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002294 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002295 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002296 inspect.signature(42)
2297
Yury Selivanov63da7c72014-01-31 14:48:37 -05002298 def test_signature_from_functionlike_object(self):
2299 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2300 pass
2301
2302 class funclike:
2303 # Has to be callable, and have correct
2304 # __code__, __annotations__, __defaults__, __name__,
2305 # and __kwdefaults__ attributes
2306
2307 def __init__(self, func):
2308 self.__name__ = func.__name__
2309 self.__code__ = func.__code__
2310 self.__annotations__ = func.__annotations__
2311 self.__defaults__ = func.__defaults__
2312 self.__kwdefaults__ = func.__kwdefaults__
2313 self.func = func
2314
2315 def __call__(self, *args, **kwargs):
2316 return self.func(*args, **kwargs)
2317
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002318 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002319
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002320 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002321 self.assertEqual(sig_funclike, sig_func)
2322
2323 sig_funclike = inspect.signature(funclike(func))
2324 self.assertEqual(sig_funclike, sig_func)
2325
2326 # If object is not a duck type of function, then
2327 # signature will try to get a signature for its '__call__'
2328 # method
2329 fl = funclike(func)
2330 del fl.__defaults__
2331 self.assertEqual(self.signature(fl),
2332 ((('args', ..., ..., "var_positional"),
2333 ('kwargs', ..., ..., "var_keyword")),
2334 ...))
2335
Yury Selivanova773de02014-02-21 18:30:53 -05002336 # Test with cython-like builtins:
2337 _orig_isdesc = inspect.ismethoddescriptor
2338 def _isdesc(obj):
2339 if hasattr(obj, '_builtinmock'):
2340 return True
2341 return _orig_isdesc(obj)
2342
2343 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2344 builtin_func = funclike(func)
2345 # Make sure that our mock setup is working
2346 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2347 builtin_func._builtinmock = True
2348 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2349 self.assertEqual(inspect.signature(builtin_func), sig_func)
2350
Yury Selivanov63da7c72014-01-31 14:48:37 -05002351 def test_signature_functionlike_class(self):
2352 # We only want to duck type function-like objects,
2353 # not classes.
2354
2355 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2356 pass
2357
2358 class funclike:
2359 def __init__(self, marker):
2360 pass
2361
2362 __name__ = func.__name__
2363 __code__ = func.__code__
2364 __annotations__ = func.__annotations__
2365 __defaults__ = func.__defaults__
2366 __kwdefaults__ = func.__kwdefaults__
2367
Yury Selivanov63da7c72014-01-31 14:48:37 -05002368 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2369
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002370 def test_signature_on_method(self):
2371 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002372 def __init__(*args):
2373 pass
2374 def m1(self, arg1, arg2=1) -> int:
2375 pass
2376 def m2(*args):
2377 pass
2378 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002379 pass
2380
Yury Selivanov62560fb2014-01-28 12:26:24 -05002381 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002382 ((('arg1', ..., ..., "positional_or_keyword"),
2383 ('arg2', 1, ..., "positional_or_keyword")),
2384 int))
2385
Yury Selivanov62560fb2014-01-28 12:26:24 -05002386 self.assertEqual(self.signature(Test().m2),
2387 ((('args', ..., ..., "var_positional"),),
2388 ...))
2389
2390 self.assertEqual(self.signature(Test),
2391 ((('args', ..., ..., "var_positional"),),
2392 ...))
2393
2394 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2395 self.signature(Test())
2396
Yury Selivanov46c759d2015-05-27 21:56:53 -04002397 def test_signature_wrapped_bound_method(self):
2398 # Issue 24298
2399 class Test:
2400 def m1(self, arg1, arg2=1) -> int:
2401 pass
2402 @functools.wraps(Test().m1)
2403 def m1d(*args, **kwargs):
2404 pass
2405 self.assertEqual(self.signature(m1d),
2406 ((('arg1', ..., ..., "positional_or_keyword"),
2407 ('arg2', 1, ..., "positional_or_keyword")),
2408 int))
2409
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002410 def test_signature_on_classmethod(self):
2411 class Test:
2412 @classmethod
2413 def foo(cls, arg1, *, arg2=1):
2414 pass
2415
2416 meth = Test().foo
2417 self.assertEqual(self.signature(meth),
2418 ((('arg1', ..., ..., "positional_or_keyword"),
2419 ('arg2', 1, ..., "keyword_only")),
2420 ...))
2421
2422 meth = Test.foo
2423 self.assertEqual(self.signature(meth),
2424 ((('arg1', ..., ..., "positional_or_keyword"),
2425 ('arg2', 1, ..., "keyword_only")),
2426 ...))
2427
2428 def test_signature_on_staticmethod(self):
2429 class Test:
2430 @staticmethod
2431 def foo(cls, *, arg):
2432 pass
2433
2434 meth = Test().foo
2435 self.assertEqual(self.signature(meth),
2436 ((('cls', ..., ..., "positional_or_keyword"),
2437 ('arg', ..., ..., "keyword_only")),
2438 ...))
2439
2440 meth = Test.foo
2441 self.assertEqual(self.signature(meth),
2442 ((('cls', ..., ..., "positional_or_keyword"),
2443 ('arg', ..., ..., "keyword_only")),
2444 ...))
2445
2446 def test_signature_on_partial(self):
2447 from functools import partial
2448
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002449 Parameter = inspect.Parameter
2450
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002451 def test():
2452 pass
2453
2454 self.assertEqual(self.signature(partial(test)), ((), ...))
2455
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002456 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002457 inspect.signature(partial(test, 1))
2458
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002459 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002460 inspect.signature(partial(test, a=1))
2461
2462 def test(a, b, *, c, d):
2463 pass
2464
2465 self.assertEqual(self.signature(partial(test)),
2466 ((('a', ..., ..., "positional_or_keyword"),
2467 ('b', ..., ..., "positional_or_keyword"),
2468 ('c', ..., ..., "keyword_only"),
2469 ('d', ..., ..., "keyword_only")),
2470 ...))
2471
2472 self.assertEqual(self.signature(partial(test, 1)),
2473 ((('b', ..., ..., "positional_or_keyword"),
2474 ('c', ..., ..., "keyword_only"),
2475 ('d', ..., ..., "keyword_only")),
2476 ...))
2477
2478 self.assertEqual(self.signature(partial(test, 1, c=2)),
2479 ((('b', ..., ..., "positional_or_keyword"),
2480 ('c', 2, ..., "keyword_only"),
2481 ('d', ..., ..., "keyword_only")),
2482 ...))
2483
2484 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2485 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002486 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002487 ('c', 2, ..., "keyword_only"),
2488 ('d', ..., ..., "keyword_only")),
2489 ...))
2490
2491 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002492 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002493 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002494 ('d', ..., ..., "keyword_only")),
2495 ...))
2496
2497 self.assertEqual(self.signature(partial(test, a=1)),
2498 ((('a', 1, ..., "keyword_only"),
2499 ('b', ..., ..., "keyword_only"),
2500 ('c', ..., ..., "keyword_only"),
2501 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002502 ...))
2503
2504 def test(a, *args, b, **kwargs):
2505 pass
2506
2507 self.assertEqual(self.signature(partial(test, 1)),
2508 ((('args', ..., ..., "var_positional"),
2509 ('b', ..., ..., "keyword_only"),
2510 ('kwargs', ..., ..., "var_keyword")),
2511 ...))
2512
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002513 self.assertEqual(self.signature(partial(test, a=1)),
2514 ((('a', 1, ..., "keyword_only"),
2515 ('b', ..., ..., "keyword_only"),
2516 ('kwargs', ..., ..., "var_keyword")),
2517 ...))
2518
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002519 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2520 ((('args', ..., ..., "var_positional"),
2521 ('b', ..., ..., "keyword_only"),
2522 ('kwargs', ..., ..., "var_keyword")),
2523 ...))
2524
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002525 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2526 ((('args', ..., ..., "var_positional"),
2527 ('b', ..., ..., "keyword_only"),
2528 ('kwargs', ..., ..., "var_keyword")),
2529 ...))
2530
2531 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2532 ((('args', ..., ..., "var_positional"),
2533 ('b', 0, ..., "keyword_only"),
2534 ('kwargs', ..., ..., "var_keyword")),
2535 ...))
2536
2537 self.assertEqual(self.signature(partial(test, b=0)),
2538 ((('a', ..., ..., "positional_or_keyword"),
2539 ('args', ..., ..., "var_positional"),
2540 ('b', 0, ..., "keyword_only"),
2541 ('kwargs', ..., ..., "var_keyword")),
2542 ...))
2543
2544 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2545 ((('a', ..., ..., "positional_or_keyword"),
2546 ('args', ..., ..., "var_positional"),
2547 ('b', 0, ..., "keyword_only"),
2548 ('kwargs', ..., ..., "var_keyword")),
2549 ...))
2550
2551 def test(a, b, c:int) -> 42:
2552 pass
2553
2554 sig = test.__signature__ = inspect.signature(test)
2555
2556 self.assertEqual(self.signature(partial(partial(test, 1))),
2557 ((('b', ..., ..., "positional_or_keyword"),
2558 ('c', ..., int, "positional_or_keyword")),
2559 42))
2560
2561 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2562 ((('c', ..., int, "positional_or_keyword"),),
2563 42))
2564
2565 psig = inspect.signature(partial(partial(test, 1), 2))
2566
2567 def foo(a):
2568 return a
2569 _foo = partial(partial(foo, a=10), a=20)
2570 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002571 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002572 ...))
2573 # check that we don't have any side-effects in signature(),
2574 # and the partial object is still functioning
2575 self.assertEqual(_foo(), 20)
2576
2577 def foo(a, b, c):
2578 return a, b, c
2579 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002580
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002581 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002582 ((('b', 30, ..., "keyword_only"),
2583 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002584 ...))
2585 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002586
2587 def foo(a, b, c, *, d):
2588 return a, b, c, d
2589 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2590 self.assertEqual(self.signature(_foo),
2591 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002592 ('b', 10, ..., "keyword_only"),
2593 ('c', 20, ..., "keyword_only"),
2594 ('d', 30, ..., "keyword_only"),
2595 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002596 ...))
2597 ba = inspect.signature(_foo).bind(a=200, b=11)
2598 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2599
2600 def foo(a=1, b=2, c=3):
2601 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002602 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2603
2604 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002605 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002606
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002607 ba = inspect.signature(_foo).bind(11, 12)
2608 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002609
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002610 ba = inspect.signature(_foo).bind(11, b=12)
2611 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002612
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002613 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002614 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2615
2616 _foo = partial(_foo, b=10, c=20)
2617 ba = inspect.signature(_foo).bind(12)
2618 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2619
2620
2621 def foo(a, b, c, d, **kwargs):
2622 pass
2623 sig = inspect.signature(foo)
2624 params = sig.parameters.copy()
2625 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2626 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2627 foo.__signature__ = inspect.Signature(params.values())
2628 sig = inspect.signature(foo)
2629 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2630
2631 self.assertEqual(self.signature(partial(foo, 1)),
2632 ((('b', ..., ..., 'positional_only'),
2633 ('c', ..., ..., 'positional_or_keyword'),
2634 ('d', ..., ..., 'positional_or_keyword'),
2635 ('kwargs', ..., ..., 'var_keyword')),
2636 ...))
2637
2638 self.assertEqual(self.signature(partial(foo, 1, 2)),
2639 ((('c', ..., ..., 'positional_or_keyword'),
2640 ('d', ..., ..., 'positional_or_keyword'),
2641 ('kwargs', ..., ..., 'var_keyword')),
2642 ...))
2643
2644 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2645 ((('d', ..., ..., 'positional_or_keyword'),
2646 ('kwargs', ..., ..., 'var_keyword')),
2647 ...))
2648
2649 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2650 ((('c', 3, ..., 'keyword_only'),
2651 ('d', ..., ..., 'keyword_only'),
2652 ('kwargs', ..., ..., 'var_keyword')),
2653 ...))
2654
2655 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2656 ((('b', ..., ..., 'positional_only'),
2657 ('c', 3, ..., 'keyword_only'),
2658 ('d', ..., ..., 'keyword_only'),
2659 ('kwargs', ..., ..., 'var_keyword')),
2660 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002661
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002662 def test_signature_on_partialmethod(self):
2663 from functools import partialmethod
2664
2665 class Spam:
2666 def test():
2667 pass
2668 ham = partialmethod(test)
2669
2670 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2671 inspect.signature(Spam.ham)
2672
2673 class Spam:
2674 def test(it, a, *, c) -> 'spam':
2675 pass
2676 ham = partialmethod(test, c=1)
2677
2678 self.assertEqual(self.signature(Spam.ham),
2679 ((('it', ..., ..., 'positional_or_keyword'),
2680 ('a', ..., ..., 'positional_or_keyword'),
2681 ('c', 1, ..., 'keyword_only')),
2682 'spam'))
2683
2684 self.assertEqual(self.signature(Spam().ham),
2685 ((('a', ..., ..., 'positional_or_keyword'),
2686 ('c', 1, ..., 'keyword_only')),
2687 'spam'))
2688
Yury Selivanov8a387212018-03-06 12:59:45 -05002689 class Spam:
2690 def test(self: 'anno', x):
2691 pass
2692
2693 g = partialmethod(test, 1)
2694
2695 self.assertEqual(self.signature(Spam.g),
2696 ((('self', ..., 'anno', 'positional_or_keyword'),),
2697 ...))
2698
Yury Selivanov0486f812014-01-29 12:18:59 -05002699 def test_signature_on_fake_partialmethod(self):
2700 def foo(a): pass
2701 foo._partialmethod = 'spam'
2702 self.assertEqual(str(inspect.signature(foo)), '(a)')
2703
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002704 def test_signature_on_decorated(self):
2705 import functools
2706
2707 def decorator(func):
2708 @functools.wraps(func)
2709 def wrapper(*args, **kwargs) -> int:
2710 return func(*args, **kwargs)
2711 return wrapper
2712
2713 class Foo:
2714 @decorator
2715 def bar(self, a, b):
2716 pass
2717
2718 self.assertEqual(self.signature(Foo.bar),
2719 ((('self', ..., ..., "positional_or_keyword"),
2720 ('a', ..., ..., "positional_or_keyword"),
2721 ('b', ..., ..., "positional_or_keyword")),
2722 ...))
2723
2724 self.assertEqual(self.signature(Foo().bar),
2725 ((('a', ..., ..., "positional_or_keyword"),
2726 ('b', ..., ..., "positional_or_keyword")),
2727 ...))
2728
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002729 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2730 ((('args', ..., ..., "var_positional"),
2731 ('kwargs', ..., ..., "var_keyword")),
2732 ...)) # functools.wraps will copy __annotations__
2733 # from "func" to "wrapper", hence no
2734 # return_annotation
2735
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002736 # Test that we handle method wrappers correctly
2737 def decorator(func):
2738 @functools.wraps(func)
2739 def wrapper(*args, **kwargs) -> int:
2740 return func(42, *args, **kwargs)
2741 sig = inspect.signature(func)
2742 new_params = tuple(sig.parameters.values())[1:]
2743 wrapper.__signature__ = sig.replace(parameters=new_params)
2744 return wrapper
2745
2746 class Foo:
2747 @decorator
2748 def __call__(self, a, b):
2749 pass
2750
2751 self.assertEqual(self.signature(Foo.__call__),
2752 ((('a', ..., ..., "positional_or_keyword"),
2753 ('b', ..., ..., "positional_or_keyword")),
2754 ...))
2755
2756 self.assertEqual(self.signature(Foo().__call__),
2757 ((('b', ..., ..., "positional_or_keyword"),),
2758 ...))
2759
Nick Coghlane8c45d62013-07-28 20:00:01 +10002760 # Test we handle __signature__ partway down the wrapper stack
2761 def wrapped_foo_call():
2762 pass
2763 wrapped_foo_call.__wrapped__ = Foo.__call__
2764
2765 self.assertEqual(self.signature(wrapped_foo_call),
2766 ((('a', ..., ..., "positional_or_keyword"),
2767 ('b', ..., ..., "positional_or_keyword")),
2768 ...))
2769
2770
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002771 def test_signature_on_class(self):
2772 class C:
2773 def __init__(self, a):
2774 pass
2775
2776 self.assertEqual(self.signature(C),
2777 ((('a', ..., ..., "positional_or_keyword"),),
2778 ...))
2779
2780 class CM(type):
2781 def __call__(cls, a):
2782 pass
2783 class C(metaclass=CM):
2784 def __init__(self, b):
2785 pass
2786
2787 self.assertEqual(self.signature(C),
2788 ((('a', ..., ..., "positional_or_keyword"),),
2789 ...))
2790
2791 class CM(type):
2792 def __new__(mcls, name, bases, dct, *, foo=1):
2793 return super().__new__(mcls, name, bases, dct)
2794 class C(metaclass=CM):
2795 def __init__(self, b):
2796 pass
2797
2798 self.assertEqual(self.signature(C),
2799 ((('b', ..., ..., "positional_or_keyword"),),
2800 ...))
2801
2802 self.assertEqual(self.signature(CM),
2803 ((('name', ..., ..., "positional_or_keyword"),
2804 ('bases', ..., ..., "positional_or_keyword"),
2805 ('dct', ..., ..., "positional_or_keyword"),
2806 ('foo', 1, ..., "keyword_only")),
2807 ...))
2808
2809 class CMM(type):
2810 def __new__(mcls, name, bases, dct, *, foo=1):
2811 return super().__new__(mcls, name, bases, dct)
2812 def __call__(cls, nm, bs, dt):
2813 return type(nm, bs, dt)
2814 class CM(type, metaclass=CMM):
2815 def __new__(mcls, name, bases, dct, *, bar=2):
2816 return super().__new__(mcls, name, bases, dct)
2817 class C(metaclass=CM):
2818 def __init__(self, b):
2819 pass
2820
2821 self.assertEqual(self.signature(CMM),
2822 ((('name', ..., ..., "positional_or_keyword"),
2823 ('bases', ..., ..., "positional_or_keyword"),
2824 ('dct', ..., ..., "positional_or_keyword"),
2825 ('foo', 1, ..., "keyword_only")),
2826 ...))
2827
2828 self.assertEqual(self.signature(CM),
2829 ((('nm', ..., ..., "positional_or_keyword"),
2830 ('bs', ..., ..., "positional_or_keyword"),
2831 ('dt', ..., ..., "positional_or_keyword")),
2832 ...))
2833
2834 self.assertEqual(self.signature(C),
2835 ((('b', ..., ..., "positional_or_keyword"),),
2836 ...))
2837
2838 class CM(type):
2839 def __init__(cls, name, bases, dct, *, bar=2):
2840 return super().__init__(name, bases, dct)
2841 class C(metaclass=CM):
2842 def __init__(self, b):
2843 pass
2844
2845 self.assertEqual(self.signature(CM),
2846 ((('name', ..., ..., "positional_or_keyword"),
2847 ('bases', ..., ..., "positional_or_keyword"),
2848 ('dct', ..., ..., "positional_or_keyword"),
2849 ('bar', 2, ..., "keyword_only")),
2850 ...))
2851
Yury Selivanov145dff82014-02-01 13:49:29 -05002852 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2853 "Signature information for builtins requires docstrings")
2854 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002855 # Test classes without user-defined __init__ or __new__
2856 class C: pass
2857 self.assertEqual(str(inspect.signature(C)), '()')
2858 class D(C): pass
2859 self.assertEqual(str(inspect.signature(D)), '()')
2860
2861 # Test meta-classes without user-defined __init__ or __new__
2862 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002863 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002864 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2865 self.assertEqual(inspect.signature(C), None)
2866 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2867 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002868
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002869 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2870 "Signature information for builtins requires docstrings")
2871 def test_signature_on_builtin_class(self):
2872 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2873 '(file, protocol=None, fix_imports=True)')
2874
2875 class P(_pickle.Pickler): pass
2876 class EmptyTrait: pass
2877 class P2(EmptyTrait, P): pass
2878 self.assertEqual(str(inspect.signature(P)),
2879 '(file, protocol=None, fix_imports=True)')
2880 self.assertEqual(str(inspect.signature(P2)),
2881 '(file, protocol=None, fix_imports=True)')
2882
2883 class P3(P2):
2884 def __init__(self, spam):
2885 pass
2886 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2887
2888 class MetaP(type):
2889 def __call__(cls, foo, bar):
2890 pass
2891 class P4(P2, metaclass=MetaP):
2892 pass
2893 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2894
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002895 def test_signature_on_callable_objects(self):
2896 class Foo:
2897 def __call__(self, a):
2898 pass
2899
2900 self.assertEqual(self.signature(Foo()),
2901 ((('a', ..., ..., "positional_or_keyword"),),
2902 ...))
2903
2904 class Spam:
2905 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002906 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002907 inspect.signature(Spam())
2908
2909 class Bar(Spam, Foo):
2910 pass
2911
2912 self.assertEqual(self.signature(Bar()),
2913 ((('a', ..., ..., "positional_or_keyword"),),
2914 ...))
2915
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002916 class Wrapped:
2917 pass
2918 Wrapped.__wrapped__ = lambda a: None
2919 self.assertEqual(self.signature(Wrapped),
2920 ((('a', ..., ..., "positional_or_keyword"),),
2921 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002922 # wrapper loop:
2923 Wrapped.__wrapped__ = Wrapped
2924 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2925 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002926
2927 def test_signature_on_lambdas(self):
2928 self.assertEqual(self.signature((lambda a=10: a)),
2929 ((('a', 10, ..., "positional_or_keyword"),),
2930 ...))
2931
2932 def test_signature_equality(self):
2933 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002934 self.assertFalse(inspect.signature(foo) == 42)
2935 self.assertTrue(inspect.signature(foo) != 42)
2936 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2937 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002938
2939 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002940 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2941 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002942 self.assertEqual(
2943 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002944
2945 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002946 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2947 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002948 self.assertNotEqual(
2949 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002950
2951 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002952 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2953 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002954 self.assertNotEqual(
2955 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002956
2957 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002958 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2959 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002960 self.assertNotEqual(
2961 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002962
2963 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002964 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2965 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002966 self.assertNotEqual(
2967 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002968
2969 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002970 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2971 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002972 self.assertNotEqual(
2973 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002974 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002975 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
2976 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002977 self.assertNotEqual(
2978 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002979
2980 def foo(*, a, b, c): pass
2981 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002982 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2983 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002984 self.assertEqual(
2985 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002986
2987 def foo(*, a=1, b, c): pass
2988 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002989 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2990 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002991 self.assertEqual(
2992 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002993
2994 def foo(pos, *, a=1, b, c): pass
2995 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002996 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2997 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002998 self.assertEqual(
2999 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003000
3001 def foo(pos, *, a, b, c): pass
3002 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003003 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3004 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003005 self.assertNotEqual(
3006 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003007
3008 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3009 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003010 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3011 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003012 self.assertEqual(
3013 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003014
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003015 def test_signature_hashable(self):
3016 S = inspect.Signature
3017 P = inspect.Parameter
3018
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003019 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003020 foo_sig = inspect.signature(foo)
3021
3022 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3023
3024 self.assertEqual(hash(foo_sig), hash(manual_sig))
3025 self.assertNotEqual(hash(foo_sig),
3026 hash(manual_sig.replace(return_annotation='spam')))
3027
3028 def bar(a) -> 1: pass
3029 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3030
3031 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003032 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003033 hash(inspect.signature(foo))
3034
3035 def foo(a) -> {}: pass
3036 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3037 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003038
3039 def test_signature_str(self):
3040 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3041 pass
3042 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003043 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003044
3045 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3046 pass
3047 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003048 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003049
3050 def foo():
3051 pass
3052 self.assertEqual(str(inspect.signature(foo)), '()')
3053
3054 def test_signature_str_positional_only(self):
3055 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003056 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003057
3058 def test(a_po, *, b, **kwargs):
3059 return a_po, kwargs
3060
3061 sig = inspect.signature(test)
3062 new_params = list(sig.parameters.values())
3063 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3064 test.__signature__ = sig.replace(parameters=new_params)
3065
3066 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003067 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003068
Yury Selivanov2393dca2014-01-27 15:07:58 -05003069 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3070 '(foo, /)')
3071
3072 self.assertEqual(str(S(parameters=[
3073 P('foo', P.POSITIONAL_ONLY),
3074 P('bar', P.VAR_KEYWORD)])),
3075 '(foo, /, **bar)')
3076
3077 self.assertEqual(str(S(parameters=[
3078 P('foo', P.POSITIONAL_ONLY),
3079 P('bar', P.VAR_POSITIONAL)])),
3080 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003081
3082 def test_signature_replace_anno(self):
3083 def test() -> 42:
3084 pass
3085
3086 sig = inspect.signature(test)
3087 sig = sig.replace(return_annotation=None)
3088 self.assertIs(sig.return_annotation, None)
3089 sig = sig.replace(return_annotation=sig.empty)
3090 self.assertIs(sig.return_annotation, sig.empty)
3091 sig = sig.replace(return_annotation=42)
3092 self.assertEqual(sig.return_annotation, 42)
3093 self.assertEqual(sig, inspect.signature(test))
3094
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003095 def test_signature_on_mangled_parameters(self):
3096 class Spam:
3097 def foo(self, __p1:1=2, *, __p2:2=3):
3098 pass
3099 class Ham(Spam):
3100 pass
3101
3102 self.assertEqual(self.signature(Spam.foo),
3103 ((('self', ..., ..., "positional_or_keyword"),
3104 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3105 ('_Spam__p2', 3, 2, "keyword_only")),
3106 ...))
3107
3108 self.assertEqual(self.signature(Spam.foo),
3109 self.signature(Ham.foo))
3110
Yury Selivanovda396452014-03-27 12:09:24 -04003111 def test_signature_from_callable_python_obj(self):
3112 class MySignature(inspect.Signature): pass
3113 def foo(a, *, b:1): pass
3114 foo_sig = MySignature.from_callable(foo)
3115 self.assertTrue(isinstance(foo_sig, MySignature))
3116
3117 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3118 "Signature information for builtins requires docstrings")
3119 def test_signature_from_callable_builtin_obj(self):
3120 class MySignature(inspect.Signature): pass
3121 sig = MySignature.from_callable(_pickle.Pickler)
3122 self.assertTrue(isinstance(sig, MySignature))
3123
larryhastingsf36ba122018-01-28 11:13:09 -08003124 def test_signature_definition_order_preserved_on_kwonly(self):
3125 for fn in signatures_with_lexicographic_keyword_only_parameters():
3126 signature = inspect.signature(fn)
3127 l = list(signature.parameters)
3128 sorted_l = sorted(l)
3129 self.assertTrue(l)
3130 self.assertEqual(l, sorted_l)
3131 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3132 l = list(signature.parameters)
3133 self.assertEqual(l, unsorted_keyword_only_parameters)
3134
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003135
3136class TestParameterObject(unittest.TestCase):
3137 def test_signature_parameter_kinds(self):
3138 P = inspect.Parameter
3139 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3140 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3141
3142 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3143 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3144
3145 def test_signature_parameter_object(self):
3146 p = inspect.Parameter('foo', default=10,
3147 kind=inspect.Parameter.POSITIONAL_ONLY)
3148 self.assertEqual(p.name, 'foo')
3149 self.assertEqual(p.default, 10)
3150 self.assertIs(p.annotation, p.empty)
3151 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3152
Dong-hee Naa9cab432018-05-30 00:04:08 +09003153 with self.assertRaisesRegex(ValueError, "value '123' is "
3154 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003155 inspect.Parameter('foo', default=10, kind='123')
3156
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003157 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003158 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3159
Yury Selivanov2393dca2014-01-27 15:07:58 -05003160 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003161 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3162
Yury Selivanov2393dca2014-01-27 15:07:58 -05003163 with self.assertRaisesRegex(ValueError,
3164 'is not a valid parameter name'):
3165 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3166
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003167 with self.assertRaisesRegex(ValueError,
3168 'is not a valid parameter name'):
3169 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3170
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003171 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003172 inspect.Parameter('a', default=42,
3173 kind=inspect.Parameter.VAR_KEYWORD)
3174
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003175 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003176 inspect.Parameter('a', default=42,
3177 kind=inspect.Parameter.VAR_POSITIONAL)
3178
3179 p = inspect.Parameter('a', default=42,
3180 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003181 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003182 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3183
3184 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003185 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003186
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003187 def test_signature_parameter_hashable(self):
3188 P = inspect.Parameter
3189 foo = P('foo', kind=P.POSITIONAL_ONLY)
3190 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3191 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3192 default=42)))
3193 self.assertNotEqual(hash(foo),
3194 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3195
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003196 def test_signature_parameter_equality(self):
3197 P = inspect.Parameter
3198 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3199
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003200 self.assertTrue(p == p)
3201 self.assertFalse(p != p)
3202 self.assertFalse(p == 42)
3203 self.assertTrue(p != 42)
3204 self.assertTrue(p == EqualsToAll())
3205 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003206
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003207 self.assertTrue(p == P('foo', default=42,
3208 kind=inspect.Parameter.KEYWORD_ONLY))
3209 self.assertFalse(p != P('foo', default=42,
3210 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003211
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003212 def test_signature_parameter_replace(self):
3213 p = inspect.Parameter('foo', default=42,
3214 kind=inspect.Parameter.KEYWORD_ONLY)
3215
3216 self.assertIsNot(p, p.replace())
3217 self.assertEqual(p, p.replace())
3218
3219 p2 = p.replace(annotation=1)
3220 self.assertEqual(p2.annotation, 1)
3221 p2 = p2.replace(annotation=p2.empty)
3222 self.assertEqual(p, p2)
3223
3224 p2 = p2.replace(name='bar')
3225 self.assertEqual(p2.name, 'bar')
3226 self.assertNotEqual(p2, p)
3227
Yury Selivanov2393dca2014-01-27 15:07:58 -05003228 with self.assertRaisesRegex(ValueError,
3229 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003230 p2 = p2.replace(name=p2.empty)
3231
3232 p2 = p2.replace(name='foo', default=None)
3233 self.assertIs(p2.default, None)
3234 self.assertNotEqual(p2, p)
3235
3236 p2 = p2.replace(name='foo', default=p2.empty)
3237 self.assertIs(p2.default, p2.empty)
3238
3239
3240 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3241 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3242 self.assertNotEqual(p2, p)
3243
Dong-hee Naa9cab432018-05-30 00:04:08 +09003244 with self.assertRaisesRegex(ValueError,
3245 "value <class 'inspect._empty'> "
3246 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003247 p2 = p2.replace(kind=p2.empty)
3248
3249 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3250 self.assertEqual(p2, p)
3251
3252 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003253 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3254 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003255
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003256 @cpython_only
3257 def test_signature_parameter_implicit(self):
3258 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003259 'implicit arguments must be passed as '
3260 'positional or keyword arguments, '
3261 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003262 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3263
3264 param = inspect.Parameter(
3265 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3266 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3267 self.assertEqual(param.name, 'implicit0')
3268
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003269 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003270 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003271
3272 with self.assertRaises(AttributeError):
3273 p.foo = 'bar'
3274
3275 with self.assertRaises(AttributeError):
3276 p.kind = 123
3277
3278
3279class TestSignatureBind(unittest.TestCase):
3280 @staticmethod
3281 def call(func, *args, **kwargs):
3282 sig = inspect.signature(func)
3283 ba = sig.bind(*args, **kwargs)
3284 return func(*ba.args, **ba.kwargs)
3285
3286 def test_signature_bind_empty(self):
3287 def test():
3288 return 42
3289
3290 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003291 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003292 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003293 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003294 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003295 with self.assertRaisesRegex(
3296 TypeError, "got an unexpected keyword argument 'spam'"):
3297
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003298 self.call(test, spam=1)
3299
3300 def test_signature_bind_var(self):
3301 def test(*args, **kwargs):
3302 return args, kwargs
3303
3304 self.assertEqual(self.call(test), ((), {}))
3305 self.assertEqual(self.call(test, 1), ((1,), {}))
3306 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3307 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3308 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3309 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3310 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3311 ((1, 2), {'foo': 'bar'}))
3312
3313 def test_signature_bind_just_args(self):
3314 def test(a, b, c):
3315 return a, b, c
3316
3317 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3318
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003319 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003320 self.call(test, 1, 2, 3, 4)
3321
Yury Selivanov86872752015-05-19 00:27:49 -04003322 with self.assertRaisesRegex(TypeError,
3323 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003324 self.call(test, 1)
3325
Yury Selivanov86872752015-05-19 00:27:49 -04003326 with self.assertRaisesRegex(TypeError,
3327 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003328 self.call(test)
3329
3330 def test(a, b, c=10):
3331 return a, b, c
3332 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3333 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3334
3335 def test(a=1, b=2, c=3):
3336 return a, b, c
3337 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3338 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3339 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3340
3341 def test_signature_bind_varargs_order(self):
3342 def test(*args):
3343 return args
3344
3345 self.assertEqual(self.call(test), ())
3346 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3347
3348 def test_signature_bind_args_and_varargs(self):
3349 def test(a, b, c=3, *args):
3350 return a, b, c, args
3351
3352 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3353 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3354 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3355 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3356
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003357 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003358 "multiple values for argument 'c'"):
3359 self.call(test, 1, 2, 3, c=4)
3360
3361 def test_signature_bind_just_kwargs(self):
3362 def test(**kwargs):
3363 return kwargs
3364
3365 self.assertEqual(self.call(test), {})
3366 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3367 {'foo': 'bar', 'spam': 'ham'})
3368
3369 def test_signature_bind_args_and_kwargs(self):
3370 def test(a, b, c=3, **kwargs):
3371 return a, b, c, kwargs
3372
3373 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3374 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3375 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3376 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3377 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3378 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3379 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3380 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3381 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3382 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3383 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3384 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3385 (1, 2, 4, {'foo': 'bar'}))
3386 self.assertEqual(self.call(test, c=5, a=4, b=3),
3387 (4, 3, 5, {}))
3388
3389 def test_signature_bind_kwonly(self):
3390 def test(*, foo):
3391 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003392 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003393 'too many positional arguments'):
3394 self.call(test, 1)
3395 self.assertEqual(self.call(test, foo=1), 1)
3396
3397 def test(a, *, foo=1, bar):
3398 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003399 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003400 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003401 self.call(test, 1)
3402
3403 def test(foo, *, bar):
3404 return foo, bar
3405 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3406 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3407
Yury Selivanov86872752015-05-19 00:27:49 -04003408 with self.assertRaisesRegex(
3409 TypeError, "got an unexpected keyword argument 'spam'"):
3410
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003411 self.call(test, bar=2, foo=1, spam=10)
3412
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003413 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003414 'too many positional arguments'):
3415 self.call(test, 1, 2)
3416
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003417 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003418 'too many positional arguments'):
3419 self.call(test, 1, 2, bar=2)
3420
Yury Selivanov86872752015-05-19 00:27:49 -04003421 with self.assertRaisesRegex(
3422 TypeError, "got an unexpected keyword argument 'spam'"):
3423
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003424 self.call(test, 1, bar=2, spam='ham')
3425
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, **bin):
3431 return foo, bar, bin
3432 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3433 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3434 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3435 (1, 2, {'spam': 'ham'}))
3436 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3437 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003438 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003439 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003440 self.call(test, spam='ham', bar=2)
3441 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3442 (1, 2, {'bin': 1, 'spam': 10}))
3443
3444 def test_signature_bind_arguments(self):
3445 def test(a, *args, b, z=100, **kwargs):
3446 pass
3447 sig = inspect.signature(test)
3448 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3449 # we won't have 'z' argument in the bound arguments object, as we didn't
3450 # pass it to the 'bind'
3451 self.assertEqual(tuple(ba.arguments.items()),
3452 (('a', 10), ('args', (20,)), ('b', 30),
3453 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3454 self.assertEqual(ba.kwargs,
3455 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3456 self.assertEqual(ba.args, (10, 20))
3457
3458 def test_signature_bind_positional_only(self):
3459 P = inspect.Parameter
3460
3461 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3462 return a_po, b_po, c_po, foo, bar, kwargs
3463
3464 sig = inspect.signature(test)
3465 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3466 for name in ('a_po', 'b_po', 'c_po'):
3467 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3468 new_sig = sig.replace(parameters=new_params.values())
3469 test.__signature__ = new_sig
3470
3471 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3472 (1, 2, 4, 5, 6, {}))
3473
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003474 self.assertEqual(self.call(test, 1, 2),
3475 (1, 2, 3, 42, 50, {}))
3476
3477 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3478 (1, 2, 3, 4, 5, {}))
3479
3480 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3481 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3482
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003483 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003484 self.call(test, 1, 2, c_po=4)
3485
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003486 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003487 self.call(test, a_po=1, b_po=2)
3488
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003489 def test_signature_bind_with_self_arg(self):
3490 # Issue #17071: one of the parameters is named "self
3491 def test(a, self, b):
3492 pass
3493 sig = inspect.signature(test)
3494 ba = sig.bind(1, 2, 3)
3495 self.assertEqual(ba.args, (1, 2, 3))
3496 ba = sig.bind(1, self=2, b=3)
3497 self.assertEqual(ba.args, (1, 2, 3))
3498
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003499 def test_signature_bind_vararg_name(self):
3500 def test(a, *args):
3501 return a, args
3502 sig = inspect.signature(test)
3503
Yury Selivanov86872752015-05-19 00:27:49 -04003504 with self.assertRaisesRegex(
3505 TypeError, "got an unexpected keyword argument 'args'"):
3506
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003507 sig.bind(a=0, args=1)
3508
3509 def test(*args, **kwargs):
3510 return args, kwargs
3511 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3512
3513 sig = inspect.signature(test)
3514 ba = sig.bind(args=1)
3515 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3516
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003517 @cpython_only
3518 def test_signature_bind_implicit_arg(self):
3519 # Issue #19611: getcallargs should work with set comprehensions
3520 def make_set():
3521 return {z * z for z in range(5)}
3522 setcomp_code = make_set.__code__.co_consts[1]
3523 setcomp_func = types.FunctionType(setcomp_code, {})
3524
3525 iterator = iter(range(5))
3526 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3527
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003528
3529class TestBoundArguments(unittest.TestCase):
3530 def test_signature_bound_arguments_unhashable(self):
3531 def foo(a): pass
3532 ba = inspect.signature(foo).bind(1)
3533
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003534 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003535 hash(ba)
3536
3537 def test_signature_bound_arguments_equality(self):
3538 def foo(a): pass
3539 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003540 self.assertTrue(ba == ba)
3541 self.assertFalse(ba != ba)
3542 self.assertTrue(ba == EqualsToAll())
3543 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003544
3545 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003546 self.assertTrue(ba == ba2)
3547 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003548
3549 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003550 self.assertFalse(ba == ba3)
3551 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003552 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003553 self.assertTrue(ba == ba3)
3554 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003555
3556 def bar(b): pass
3557 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003558 self.assertFalse(ba == ba4)
3559 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003560
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003561 def foo(*, a, b): pass
3562 sig = inspect.signature(foo)
3563 ba1 = sig.bind(a=1, b=2)
3564 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003565 self.assertTrue(ba1 == ba2)
3566 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003567
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003568 def test_signature_bound_arguments_pickle(self):
3569 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3570 sig = inspect.signature(foo)
3571 ba = sig.bind(20, 30, z={})
3572
3573 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3574 with self.subTest(pickle_ver=ver):
3575 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3576 self.assertEqual(ba, ba_pickled)
3577
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003578 def test_signature_bound_arguments_repr(self):
3579 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3580 sig = inspect.signature(foo)
3581 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003582 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003583
Yury Selivanovb907a512015-05-16 13:45:09 -04003584 def test_signature_bound_arguments_apply_defaults(self):
3585 def foo(a, b=1, *args, c:1={}, **kw): pass
3586 sig = inspect.signature(foo)
3587
3588 ba = sig.bind(20)
3589 ba.apply_defaults()
3590 self.assertEqual(
3591 list(ba.arguments.items()),
3592 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3593
3594 # Make sure that we preserve the order:
3595 # i.e. 'c' should be *before* 'kw'.
3596 ba = sig.bind(10, 20, 30, d=1)
3597 ba.apply_defaults()
3598 self.assertEqual(
3599 list(ba.arguments.items()),
3600 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3601
3602 # Make sure that BoundArguments produced by bind_partial()
3603 # are supported.
3604 def foo(a, b): pass
3605 sig = inspect.signature(foo)
3606 ba = sig.bind_partial(20)
3607 ba.apply_defaults()
3608 self.assertEqual(
3609 list(ba.arguments.items()),
3610 [('a', 20)])
3611
3612 # Test no args
3613 def foo(): pass
3614 sig = inspect.signature(foo)
3615 ba = sig.bind()
3616 ba.apply_defaults()
3617 self.assertEqual(list(ba.arguments.items()), [])
3618
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003619 # Make sure a no-args binding still acquires proper defaults.
3620 def foo(a='spam'): pass
3621 sig = inspect.signature(foo)
3622 ba = sig.bind()
3623 ba.apply_defaults()
3624 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3625
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003626
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003627class TestSignaturePrivateHelpers(unittest.TestCase):
3628 def test_signature_get_bound_param(self):
3629 getter = inspect._signature_get_bound_param
3630
3631 self.assertEqual(getter('($self)'), 'self')
3632 self.assertEqual(getter('($self, obj)'), 'self')
3633 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3634
Larry Hastings2623c8c2014-02-08 22:15:29 -08003635 def _strip_non_python_syntax(self, input,
3636 clean_signature, self_parameter, last_positional_only):
3637 computed_clean_signature, \
3638 computed_self_parameter, \
3639 computed_last_positional_only = \
3640 inspect._signature_strip_non_python_syntax(input)
3641 self.assertEqual(computed_clean_signature, clean_signature)
3642 self.assertEqual(computed_self_parameter, self_parameter)
3643 self.assertEqual(computed_last_positional_only, last_positional_only)
3644
3645 def test_signature_strip_non_python_syntax(self):
3646 self._strip_non_python_syntax(
3647 "($module, /, path, mode, *, dir_fd=None, " +
3648 "effective_ids=False,\n follow_symlinks=True)",
3649 "(module, path, mode, *, dir_fd=None, " +
3650 "effective_ids=False, follow_symlinks=True)",
3651 0,
3652 0)
3653
3654 self._strip_non_python_syntax(
3655 "($module, word, salt, /)",
3656 "(module, word, salt)",
3657 0,
3658 2)
3659
3660 self._strip_non_python_syntax(
3661 "(x, y=None, z=None, /)",
3662 "(x, y=None, z=None)",
3663 None,
3664 2)
3665
3666 self._strip_non_python_syntax(
3667 "(x, y=None, z=None)",
3668 "(x, y=None, z=None)",
3669 None,
3670 None)
3671
3672 self._strip_non_python_syntax(
3673 "(x,\n y=None,\n z = None )",
3674 "(x, y=None, z=None)",
3675 None,
3676 None)
3677
3678 self._strip_non_python_syntax(
3679 "",
3680 "",
3681 None,
3682 None)
3683
3684 self._strip_non_python_syntax(
3685 None,
3686 None,
3687 None,
3688 None)
3689
Nick Coghlan9c680b02015-04-13 12:54:54 -04003690class TestSignatureDefinitions(unittest.TestCase):
3691 # This test case provides a home for checking that particular APIs
3692 # have signatures available for introspection
3693
3694 @cpython_only
3695 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3696 "Signature information for builtins requires docstrings")
3697 def test_builtins_have_signatures(self):
3698 # This checks all builtin callables in CPython have signatures
3699 # A few have signatures Signature can't yet handle, so we skip those
3700 # since they will have to wait until PEP 457 adds the required
3701 # introspection support to the inspect module
3702 # Some others also haven't been converted yet for various other
3703 # reasons, so we also skip those for the time being, but design
3704 # the test to fail in order to indicate when it needs to be
3705 # updated.
3706 no_signature = set()
3707 # These need PEP 457 groups
3708 needs_groups = {"range", "slice", "dir", "getattr",
3709 "next", "iter", "vars"}
3710 no_signature |= needs_groups
3711 # These need PEP 457 groups or a signature change to accept None
3712 needs_semantic_update = {"round"}
3713 no_signature |= needs_semantic_update
3714 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003715 needs_varargs = {"breakpoint", "min", "max", "print",
3716 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003717 no_signature |= needs_varargs
3718 # These simply weren't covered in the initial AC conversion
3719 # for builtin callables
3720 not_converted_yet = {"open", "__import__"}
3721 no_signature |= not_converted_yet
3722 # These builtin types are expected to provide introspection info
3723 types_with_signatures = set()
3724 # Check the signatures we expect to be there
3725 ns = vars(builtins)
3726 for name, obj in sorted(ns.items()):
3727 if not callable(obj):
3728 continue
3729 # The builtin types haven't been converted to AC yet
3730 if isinstance(obj, type) and (name not in types_with_signatures):
3731 # Note that this also skips all the exception types
3732 no_signature.add(name)
3733 if (name in no_signature):
3734 # Not yet converted
3735 continue
3736 with self.subTest(builtin=name):
3737 self.assertIsNotNone(inspect.signature(obj))
3738 # Check callables that haven't been converted don't claim a signature
3739 # This ensures this test will start failing as more signatures are
3740 # added, so the affected items can be moved into the scope of the
3741 # regression test above
3742 for name in no_signature:
3743 with self.subTest(builtin=name):
3744 self.assertIsNone(obj.__text_signature__)
3745
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003746
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003747class NTimesUnwrappable:
3748 def __init__(self, n):
3749 self.n = n
3750 self._next = None
3751
3752 @property
3753 def __wrapped__(self):
3754 if self.n <= 0:
3755 raise Exception("Unwrapped too many times")
3756 if self._next is None:
3757 self._next = NTimesUnwrappable(self.n - 1)
3758 return self._next
3759
Nick Coghlane8c45d62013-07-28 20:00:01 +10003760class TestUnwrap(unittest.TestCase):
3761
3762 def test_unwrap_one(self):
3763 def func(a, b):
3764 return a + b
3765 wrapper = functools.lru_cache(maxsize=20)(func)
3766 self.assertIs(inspect.unwrap(wrapper), func)
3767
3768 def test_unwrap_several(self):
3769 def func(a, b):
3770 return a + b
3771 wrapper = func
3772 for __ in range(10):
3773 @functools.wraps(wrapper)
3774 def wrapper():
3775 pass
3776 self.assertIsNot(wrapper.__wrapped__, func)
3777 self.assertIs(inspect.unwrap(wrapper), func)
3778
3779 def test_stop(self):
3780 def func1(a, b):
3781 return a + b
3782 @functools.wraps(func1)
3783 def func2():
3784 pass
3785 @functools.wraps(func2)
3786 def wrapper():
3787 pass
3788 func2.stop_here = 1
3789 unwrapped = inspect.unwrap(wrapper,
3790 stop=(lambda f: hasattr(f, "stop_here")))
3791 self.assertIs(unwrapped, func2)
3792
3793 def test_cycle(self):
3794 def func1(): pass
3795 func1.__wrapped__ = func1
3796 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3797 inspect.unwrap(func1)
3798
3799 def func2(): pass
3800 func2.__wrapped__ = func1
3801 func1.__wrapped__ = func2
3802 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3803 inspect.unwrap(func1)
3804 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3805 inspect.unwrap(func2)
3806
3807 def test_unhashable(self):
3808 def func(): pass
3809 func.__wrapped__ = None
3810 class C:
3811 __hash__ = None
3812 __wrapped__ = func
3813 self.assertIsNone(inspect.unwrap(C()))
3814
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003815 def test_recursion_limit(self):
3816 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3817 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3818 inspect.unwrap(obj)
3819
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003820class TestMain(unittest.TestCase):
3821 def test_only_source(self):
3822 module = importlib.import_module('unittest')
3823 rc, out, err = assert_python_ok('-m', 'inspect',
3824 'unittest')
3825 lines = out.decode().splitlines()
3826 # ignore the final newline
3827 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3828 self.assertEqual(err, b'')
3829
Yury Selivanov42407ab2014-06-23 10:23:50 -07003830 def test_custom_getattr(self):
3831 def foo():
3832 pass
3833 foo.__signature__ = 42
3834 with self.assertRaises(TypeError):
3835 inspect.signature(foo)
3836
Brett Cannon634a8fc2013-10-02 10:25:42 -04003837 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003838 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003839 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003840 rc, out, err = assert_python_ok('-m', 'inspect',
3841 'concurrent.futures:ThreadPoolExecutor')
3842 lines = out.decode().splitlines()
3843 # ignore the final newline
3844 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003845 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003846 self.assertEqual(err, b'')
3847
3848 def test_builtins(self):
3849 module = importlib.import_module('unittest')
3850 _, out, err = assert_python_failure('-m', 'inspect',
3851 'sys')
3852 lines = err.decode().splitlines()
3853 self.assertEqual(lines, ["Can't get info for builtin modules."])
3854
3855 def test_details(self):
3856 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003857 args = support.optim_args_from_interpreter_flags()
3858 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003859 'unittest', '--details')
3860 output = out.decode()
3861 # Just a quick sanity check on the output
3862 self.assertIn(module.__name__, output)
3863 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003864 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003865 self.assertEqual(err, b'')
3866
3867
Yury Selivanovef1e7502014-12-08 16:05:34 -05003868class TestReload(unittest.TestCase):
3869
3870 src_before = textwrap.dedent("""\
3871def foo():
3872 print("Bla")
3873 """)
3874
3875 src_after = textwrap.dedent("""\
3876def foo():
3877 print("Oh no!")
3878 """)
3879
3880 def assertInspectEqual(self, path, source):
3881 inspected_src = inspect.getsource(source)
3882 with open(path) as src:
3883 self.assertEqual(
3884 src.read().splitlines(True),
3885 inspected_src.splitlines(True)
3886 )
3887
3888 def test_getsource_reload(self):
3889 # see issue 1218234
3890 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3891 module = importlib.import_module(name)
3892 self.assertInspectEqual(path, module)
3893 with open(path, 'w') as src:
3894 src.write(self.src_after)
3895 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003896
Nick Coghlane8c45d62013-07-28 20:00:01 +10003897
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003898def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003899 run_unittest(
3900 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3901 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3902 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003903 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003904 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003905 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04003906 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003907 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07003908 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00003909 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003910
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003911if __name__ == "__main__":
3912 test_main()