blob: 2dc8454595e175ee9cd607a71ff5ad6ccc947bec [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
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +030028from test.support import MISSING_C_DOCSTRINGS, ALWAYS_EQ
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
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000121class TestPredicates(IsTestBase):
Christian Heimes7131fd92008-02-19 14:21:46 +0000122
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000123 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200124 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000125 self.istest(inspect.isbuiltin, 'sys.exit')
126 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +0000127 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +0200128 try:
129 1/0
130 except:
131 tb = sys.exc_info()[2]
132 self.istest(inspect.isframe, 'tb.tb_frame')
133 self.istest(inspect.istraceback, 'tb')
134 if hasattr(types, 'GetSetDescriptorType'):
135 self.istest(inspect.isgetsetdescriptor,
136 'type(tb.tb_frame).f_locals')
137 else:
138 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
139 finally:
140 # Clear traceback and all the frames and local variables hanging to it.
141 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000142 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000143 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000144 self.istest(inspect.ismethod, 'git.argue')
Jeroen Demeyerfcef60f2019-04-02 16:03:42 +0200145 self.istest(inspect.ismethod, 'mod.custom_method')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000146 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000147 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000148 self.istest(inspect.isgenerator, '(x for x in range(2))')
149 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Yury Selivanoveb636452016-09-08 22:01:51 -0700150 self.istest(inspect.isasyncgen,
151 'async_generator_function_example(1)')
152 self.istest(inspect.isasyncgenfunction,
153 'async_generator_function_example')
Yury Selivanov75445082015-05-11 22:57:16 -0400154
155 with warnings.catch_warnings():
156 warnings.simplefilter("ignore")
157 self.istest(inspect.iscoroutine, 'coroutine_function_example(1)')
158 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
159
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000160 if hasattr(types, 'MemberDescriptorType'):
161 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
162 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000163 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000164
Yury Selivanov75445082015-05-11 22:57:16 -0400165 def test_iscoroutine(self):
Pablo Galindo7cd25432018-10-26 12:19:14 +0100166 async_gen_coro = async_generator_function_example(1)
Yury Selivanov75445082015-05-11 22:57:16 -0400167 gen_coro = gen_coroutine_function_example(1)
168 coro = coroutine_function_example(1)
169
Yury Selivanov5376ba92015-06-22 12:19:30 -0400170 self.assertFalse(
Yury Selivanov75445082015-05-11 22:57:16 -0400171 inspect.iscoroutinefunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100172 self.assertFalse(
173 inspect.iscoroutinefunction(
174 functools.partial(functools.partial(
175 gen_coroutine_function_example))))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400176 self.assertFalse(inspect.iscoroutine(gen_coro))
Yury Selivanov75445082015-05-11 22:57:16 -0400177
178 self.assertTrue(
179 inspect.isgeneratorfunction(gen_coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100180 self.assertTrue(
181 inspect.isgeneratorfunction(
182 functools.partial(functools.partial(
183 gen_coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400184 self.assertTrue(inspect.isgenerator(gen_coro))
185
186 self.assertTrue(
187 inspect.iscoroutinefunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100188 self.assertTrue(
189 inspect.iscoroutinefunction(
190 functools.partial(functools.partial(
191 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400192 self.assertTrue(inspect.iscoroutine(coro))
193
194 self.assertFalse(
195 inspect.isgeneratorfunction(coroutine_function_example))
Pablo Galindo7cd25432018-10-26 12:19:14 +0100196 self.assertFalse(
197 inspect.isgeneratorfunction(
198 functools.partial(functools.partial(
199 coroutine_function_example))))
Yury Selivanov75445082015-05-11 22:57:16 -0400200 self.assertFalse(inspect.isgenerator(coro))
201
Pablo Galindo7cd25432018-10-26 12:19:14 +0100202 self.assertTrue(
203 inspect.isasyncgenfunction(async_generator_function_example))
204 self.assertTrue(
205 inspect.isasyncgenfunction(
206 functools.partial(functools.partial(
207 async_generator_function_example))))
208 self.assertTrue(inspect.isasyncgen(async_gen_coro))
209
210 coro.close(); gen_coro.close(); # silence warnings
Yury Selivanov75445082015-05-11 22:57:16 -0400211
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400212 def test_isawaitable(self):
213 def gen(): yield
214 self.assertFalse(inspect.isawaitable(gen()))
215
216 coro = coroutine_function_example(1)
217 gen_coro = gen_coroutine_function_example(1)
218
219 self.assertTrue(inspect.isawaitable(coro))
220 self.assertTrue(inspect.isawaitable(gen_coro))
221
222 class Future:
223 def __await__():
224 pass
225 self.assertTrue(inspect.isawaitable(Future()))
226 self.assertFalse(inspect.isawaitable(Future))
227
228 class NotFuture: pass
229 not_fut = NotFuture()
230 not_fut.__await__ = lambda: None
231 self.assertFalse(inspect.isawaitable(not_fut))
232
233 coro.close(); gen_coro.close() # silence warnings
234
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000235 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000236 self.assertTrue(inspect.isroutine(mod.spam))
237 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000238
Benjamin Petersonc4656002009-01-17 22:41:18 +0000239 def test_isclass(self):
240 self.istest(inspect.isclass, 'mod.StupidGit')
241 self.assertTrue(inspect.isclass(list))
242
243 class CustomGetattr(object):
244 def __getattr__(self, attr):
245 return None
246 self.assertFalse(inspect.isclass(CustomGetattr()))
247
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000248 def test_get_slot_members(self):
249 class C(object):
250 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000251 x = C()
252 x.a = 42
253 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000254 self.assertIn('a', members)
255 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000256
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000257 def test_isabstract(self):
258 from abc import ABCMeta, abstractmethod
259
260 class AbstractClassExample(metaclass=ABCMeta):
261
262 @abstractmethod
263 def foo(self):
264 pass
265
266 class ClassExample(AbstractClassExample):
267 def foo(self):
268 pass
269
270 a = ClassExample()
271
272 # Test general behaviour.
273 self.assertTrue(inspect.isabstract(AbstractClassExample))
274 self.assertFalse(inspect.isabstract(ClassExample))
275 self.assertFalse(inspect.isabstract(a))
276 self.assertFalse(inspect.isabstract(int))
277 self.assertFalse(inspect.isabstract(5))
278
Natefcfe80e2017-04-24 10:06:15 -0700279 def test_isabstract_during_init_subclass(self):
280 from abc import ABCMeta, abstractmethod
281 isabstract_checks = []
282 class AbstractChecker(metaclass=ABCMeta):
283 def __init_subclass__(cls):
284 isabstract_checks.append(inspect.isabstract(cls))
285 class AbstractClassExample(AbstractChecker):
286 @abstractmethod
287 def foo(self):
288 pass
289 class ClassExample(AbstractClassExample):
290 def foo(self):
291 pass
292 self.assertEqual(isabstract_checks, [True, False])
293
294 isabstract_checks.clear()
295 class AbstractChild(AbstractClassExample):
296 pass
297 class AbstractGrandchild(AbstractChild):
298 pass
299 class ConcreteGrandchild(ClassExample):
300 pass
301 self.assertEqual(isabstract_checks, [True, True, False])
302
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000303
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000304class TestInterpreterStack(IsTestBase):
305 def __init__(self, *args, **kwargs):
306 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000307
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000308 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000309
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000310 def test_abuse_done(self):
311 self.istest(inspect.istraceback, 'git.ex[2]')
312 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000313
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000314 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000315 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000316 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000317 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000318 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000319 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000320 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000321 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000322 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000323 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Antoine Pitroucdcafb72014-08-24 10:50:28 -0400324 # Test named tuple fields
325 record = mod.st[0]
326 self.assertIs(record.frame, mod.fr)
327 self.assertEqual(record.lineno, 16)
328 self.assertEqual(record.filename, mod.__file__)
329 self.assertEqual(record.function, 'eggs')
330 self.assertIn('inspect.stack()', record.code_context[0])
331 self.assertEqual(record.index, 0)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000332
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000333 def test_trace(self):
334 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000335 self.assertEqual(revise(*git.tr[0][1:]),
336 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
337 self.assertEqual(revise(*git.tr[1][1:]),
338 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
339 self.assertEqual(revise(*git.tr[2][1:]),
340 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000341
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000342 def test_frame(self):
343 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
344 self.assertEqual(args, ['x', 'y'])
345 self.assertEqual(varargs, None)
346 self.assertEqual(varkw, None)
347 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
348 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
349 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000350
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000351 def test_previous_frame(self):
352 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000353 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000354 self.assertEqual(varargs, 'g')
355 self.assertEqual(varkw, 'h')
356 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000357 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000358
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000359class GetSourceBase(unittest.TestCase):
360 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000361 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000362
Yury Selivanov6738b112015-05-16 10:10:21 -0400363 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000364 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000365 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000366
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000367 def sourcerange(self, top, bottom):
368 lines = self.source.split("\n")
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700369 return "\n".join(lines[top-1:bottom]) + ("\n" if bottom else "")
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000370
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000371 def assertSourceEqual(self, obj, top, bottom):
372 self.assertEqual(inspect.getsource(obj),
373 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000374
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700375class SlotUser:
376 'Docstrings for __slots__'
377 __slots__ = {'power': 'measured in kilowatts',
378 'distance': 'measured in kilometers'}
379
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000380class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000381 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000382
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000383 def test_getclasses(self):
384 classes = inspect.getmembers(mod, inspect.isclass)
385 self.assertEqual(classes,
386 [('FesteringGob', mod.FesteringGob),
387 ('MalodorousPervert', mod.MalodorousPervert),
388 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300389 ('StupidGit', mod.StupidGit),
390 ('Tit', mod.MalodorousPervert),
391 ])
392 tree = inspect.getclasstree([cls[1] for cls in classes])
393 self.assertEqual(tree,
394 [(object, ()),
395 [(mod.ParrotDroppings, (object,)),
396 [(mod.FesteringGob, (mod.MalodorousPervert,
397 mod.ParrotDroppings))
398 ],
399 (mod.StupidGit, (object,)),
400 [(mod.MalodorousPervert, (mod.StupidGit,)),
401 [(mod.FesteringGob, (mod.MalodorousPervert,
402 mod.ParrotDroppings))
403 ]
404 ]
405 ]
406 ])
407 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000408 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000409 [(object, ()),
410 [(mod.ParrotDroppings, (object,)),
411 (mod.StupidGit, (object,)),
412 [(mod.MalodorousPervert, (mod.StupidGit,)),
413 [(mod.FesteringGob, (mod.MalodorousPervert,
414 mod.ParrotDroppings))
415 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000416 ]
417 ]
418 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000419
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000420 def test_getfunctions(self):
421 functions = inspect.getmembers(mod, inspect.isfunction)
422 self.assertEqual(functions, [('eggs', mod.eggs),
Yury Selivanove4e811d2015-07-21 19:01:52 +0300423 ('lobbest', mod.lobbest),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000424 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000425
R. David Murray378c0cf2010-02-24 01:46:21 +0000426 @unittest.skipIf(sys.flags.optimize >= 2,
427 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000428 def test_getdoc(self):
429 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
430 self.assertEqual(inspect.getdoc(mod.StupidGit),
431 'A longer,\n\nindented\n\ndocstring.')
432 self.assertEqual(inspect.getdoc(git.abuse),
433 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Raymond Hettingerd1e768a2019-03-25 13:01:13 -0700434 self.assertEqual(inspect.getdoc(SlotUser.power),
435 'measured in kilowatts')
436 self.assertEqual(inspect.getdoc(SlotUser.distance),
437 'measured in kilometers')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000438
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300439 @unittest.skipIf(sys.flags.optimize >= 2,
440 "Docstrings are omitted with -O2 and above")
441 def test_getdoc_inherited(self):
Serhiy Storchakafbf27862020-04-15 23:00:20 +0300442 self.assertIsNone(inspect.getdoc(mod.FesteringGob))
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300443 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
444 'Another\n\ndocstring\n\ncontaining\n\ntabs')
445 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
446 'Another\n\ndocstring\n\ncontaining\n\ntabs')
447 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
448 'The automatic gainsaying.')
449
450 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
Serhiy Storchakafbf27862020-04-15 23:00:20 +0300451 def test_getowndoc(self):
452 getowndoc = inspect._getowndoc
453 self.assertEqual(getowndoc(type), type.__doc__)
454 self.assertEqual(getowndoc(int), int.__doc__)
455 self.assertEqual(getowndoc(int.to_bytes), int.to_bytes.__doc__)
456 self.assertEqual(getowndoc(int().to_bytes), int.to_bytes.__doc__)
457 self.assertEqual(getowndoc(int.from_bytes), int.from_bytes.__doc__)
458 self.assertEqual(getowndoc(int.real), int.real.__doc__)
459
460 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300461 def test_finddoc(self):
462 finddoc = inspect._finddoc
Serhiy Storchakafbf27862020-04-15 23:00:20 +0300463 self.assertIsNone(finddoc(int))
Serhiy Storchaka5cf2b722015-04-03 22:38:53 +0300464 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
465 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
466 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
467 self.assertEqual(finddoc(int.real), int.real.__doc__)
468
Georg Brandl0c77a822008-06-10 16:37:50 +0000469 def test_cleandoc(self):
470 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
471 'An\nindented\ndocstring.')
472
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000473 def test_getcomments(self):
474 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
475 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Marco Buttu3f2155f2017-03-17 09:50:23 +0100476 # If the object source file is not available, return None.
477 co = compile('x=1', '_non_existing_filename.py', 'exec')
478 self.assertIsNone(inspect.getcomments(co))
479 # If the object has been defined in C, return None.
480 self.assertIsNone(inspect.getcomments(list))
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000481
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000482 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000483 # Check actual module
484 self.assertEqual(inspect.getmodule(mod), mod)
485 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000486 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000487 # Check a method (no __module__ attribute, falls back to filename)
488 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
489 # Do it again (check the caching isn't broken)
490 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
491 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000492 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000493 # Check filename override
494 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000495
Berker Peksagff0e3b72017-01-02 06:57:43 +0300496 def test_getframeinfo_get_first_line(self):
497 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
498 self.assertEqual(frame_info.code_context[0], "# line 1\n")
499 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
500
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000501 def test_getsource(self):
502 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200503 self.assertSourceEqual(mod.StupidGit, 21, 51)
504 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000505
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000506 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000507 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
508 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000509 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100510 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000511 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000512 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200513 try:
514 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
515 finally:
516 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000517
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000518 def test_getfile(self):
519 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000520
Philipp Ad407d2a2019-06-08 14:05:46 +0200521 def test_getfile_builtin_module(self):
522 with self.assertRaises(TypeError) as e:
523 inspect.getfile(sys)
524 self.assertTrue(str(e.exception).startswith('<module'))
525
526 def test_getfile_builtin_class(self):
527 with self.assertRaises(TypeError) as e:
528 inspect.getfile(int)
529 self.assertTrue(str(e.exception).startswith('<class'))
530
531 def test_getfile_builtin_function_or_method(self):
532 with self.assertRaises(TypeError) as e_abs:
533 inspect.getfile(abs)
534 self.assertIn('expected, got', str(e_abs.exception))
535 with self.assertRaises(TypeError) as e_append:
536 inspect.getfile(list.append)
537 self.assertIn('expected, got', str(e_append.exception))
538
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500539 def test_getfile_class_without_module(self):
540 class CM(type):
541 @property
542 def __module__(cls):
543 raise AttributeError
544 class C(metaclass=CM):
545 pass
546 with self.assertRaises(TypeError):
547 inspect.getfile(C)
548
Thomas Kluyvere968bc732017-10-24 13:42:36 +0100549 def test_getfile_broken_repr(self):
550 class ErrorRepr:
551 def __repr__(self):
552 raise Exception('xyz')
553 er = ErrorRepr()
554 with self.assertRaises(TypeError):
555 inspect.getfile(er)
556
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000557 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000558 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000559 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000560 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000561 m.__file__ = "<string>" # hopefully not a real filename...
562 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000563 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000564 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000565 del sys.modules[name]
566 inspect.getmodule(compile('a=10','','single'))
567
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500568 def test_proceed_with_fake_filename(self):
569 '''doctest monkeypatches linecache to enable inspection'''
570 fn, source = '<test>', 'def x(): pass\n'
571 getlines = linecache.getlines
572 def monkey(filename, module_globals=None):
573 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300574 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500575 else:
576 return getlines(filename, module_globals)
577 linecache.getlines = monkey
578 try:
579 ns = {}
580 exec(compile(source, fn, 'single'), ns)
581 inspect.getsource(ns["x"])
582 finally:
583 linecache.getlines = getlines
584
Antoine Pitroua8723a02015-04-15 00:41:29 +0200585 def test_getsource_on_code_object(self):
586 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
587
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700588class TestGettingSourceOfToplevelFrames(GetSourceBase):
589 fodderModule = mod
590
591 def test_range_toplevel_frame(self):
592 self.maxDiff = None
593 self.assertSourceEqual(mod.currentframe, 1, None)
594
595 def test_range_traceback_toplevel_frame(self):
596 self.assertSourceEqual(mod.tb, 1, None)
597
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000598class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000599 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000600
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000601 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000602 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000603
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000604 def test_replacing_decorator(self):
605 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000606
Yury Selivanov081bbf62014-09-26 17:34:54 -0400607 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200608 self.assertSourceEqual(mod2.real, 130, 132)
609
610 def test_decorator_with_lambda(self):
611 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400612
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000613class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000614 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000615 def test_oneline_lambda(self):
616 # Test inspect.getsource with a one-line lambda function.
617 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000618
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000619 def test_threeline_lambda(self):
620 # Test inspect.getsource with a three-line lambda function,
621 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000622 self.assertSourceEqual(mod2.tll, 28, 30)
623
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000624 def test_twoline_indented_lambda(self):
625 # Test inspect.getsource with a two-line lambda function,
626 # where the second line _is_ indented.
627 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000628
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000629 def test_onelinefunc(self):
630 # Test inspect.getsource with a regular one-line function.
631 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000632
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000633 def test_manyargs(self):
634 # Test inspect.getsource with a regular function where
635 # the arguments are on two lines and _not_ indented and
636 # the body on the second line with the last arguments.
637 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000638
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000639 def test_twolinefunc(self):
640 # Test inspect.getsource with a regular function where
641 # the body is on two lines, following the argument list and
642 # continued on the next line by a \\.
643 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000644
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000645 def test_lambda_in_list(self):
646 # Test inspect.getsource with a one-line lambda function
647 # defined in a list, indented.
648 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000649
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000650 def test_anonymous(self):
651 # Test inspect.getsource with a lambda function defined
652 # as argument to another function.
653 self.assertSourceEqual(mod2.anonymous, 55, 55)
654
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000655class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000656 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000657
658 def test_with_comment(self):
659 self.assertSourceEqual(mod2.with_comment, 58, 59)
660
661 def test_multiline_sig(self):
662 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
663
Armin Rigodd5c0232005-09-25 11:45:45 +0000664 def test_nested_class(self):
665 self.assertSourceEqual(mod2.func69().func71, 71, 72)
666
667 def test_one_liner_followed_by_non_name(self):
668 self.assertSourceEqual(mod2.func77, 77, 77)
669
670 def test_one_liner_dedent_non_name(self):
671 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
672
673 def test_with_comment_instead_of_docstring(self):
674 self.assertSourceEqual(mod2.func88, 88, 90)
675
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000676 def test_method_in_dynamic_class(self):
677 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
678
R David Murray32562d72014-10-03 11:15:38 -0400679 # This should not skip for CPython, but might on a repackaged python where
680 # unicodedata is not an external module, or on pypy.
681 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
682 unicodedata.__file__.endswith('.py'),
683 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000684 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200685 self.assertRaises(OSError, inspect.getsource, unicodedata)
686 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000687
R. David Murraya1b37402010-06-17 02:04:29 +0000688 def test_findsource_code_in_linecache(self):
689 lines = ["x=1"]
690 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200691 self.assertRaises(OSError, inspect.findsource, co)
692 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000693 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200694 try:
695 self.assertEqual(inspect.findsource(co), (lines,0))
696 self.assertEqual(inspect.getsource(co), lines[0])
697 finally:
698 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000699
Ezio Melotti1b145922013-03-30 05:17:24 +0200700 def test_findsource_without_filename(self):
701 for fname in ['', '<string>']:
702 co = compile('x=1', fname, "exec")
703 self.assertRaises(IOError, inspect.findsource, co)
704 self.assertRaises(IOError, inspect.getsource, co)
705
Antoine Pitroua8723a02015-04-15 00:41:29 +0200706 def test_getsource_on_method(self):
707 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
708
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300709 def test_nested_func(self):
710 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
711
712
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000713class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400714 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000715 self.tempdir = TESTFN + '_dir'
716 os.mkdir(self.tempdir)
717 with open(os.path.join(self.tempdir,
718 'inspect_fodder3%spy' % os.extsep), 'w') as f:
719 f.write("class X:\n pass # No EOL")
720 with DirsOnSysPath(self.tempdir):
721 import inspect_fodder3 as mod3
722 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400723 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000724
725 def tearDown(self):
726 shutil.rmtree(self.tempdir)
727
728 def test_class(self):
729 self.assertSourceEqual(self.fodderModule.X, 1, 2)
730
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100731
732class _BrokenDataDescriptor(object):
733 """
734 A broken data descriptor. See bug #1785.
735 """
736 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700737 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100738
739 def __set__(*args):
740 raise RuntimeError
741
742 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700743 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100744
745
746class _BrokenMethodDescriptor(object):
747 """
748 A broken method descriptor. See bug #1785.
749 """
750 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700751 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100752
753 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700754 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100755
756
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000757# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000758def attrs_wo_objs(cls):
759 return [t[:3] for t in inspect.classify_class_attrs(cls)]
760
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100761
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000762class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000763 def test_newstyle_mro(self):
764 # The same w/ new-class MRO.
765 class A(object): pass
766 class B(A): pass
767 class C(A): pass
768 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000769
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000770 expected = (D, B, C, A, object)
771 got = inspect.getmro(D)
772 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000773
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500774 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
775 varkw_e=None, defaults_e=None, formatted=None):
Xtreak6d0b7472019-05-30 17:31:39 +0530776 with self.assertWarns(DeprecationWarning):
777 args, varargs, varkw, defaults = inspect.getargspec(routine)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500778 self.assertEqual(args, args_e)
779 self.assertEqual(varargs, varargs_e)
780 self.assertEqual(varkw, varkw_e)
781 self.assertEqual(defaults, defaults_e)
782 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530783 with self.assertWarns(DeprecationWarning):
784 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
785 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500786
Christian Heimes3795b532007-11-08 13:48:53 +0000787 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
788 varkw_e=None, defaults_e=None,
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100789 posonlyargs_e=[], kwonlyargs_e=[],
790 kwonlydefaults_e=None,
Christian Heimes3795b532007-11-08 13:48:53 +0000791 ann_e={}, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100792 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
793 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000794 self.assertEqual(args, args_e)
795 self.assertEqual(varargs, varargs_e)
796 self.assertEqual(varkw, varkw_e)
797 self.assertEqual(defaults, defaults_e)
798 self.assertEqual(kwonlyargs, kwonlyargs_e)
799 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
800 self.assertEqual(ann, ann_e)
801 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530802 with self.assertWarns(DeprecationWarning):
803 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
804 kwonlyargs, kwonlydefaults, ann),
805 formatted)
Christian Heimes3795b532007-11-08 13:48:53 +0000806
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500807 def test_getargspec(self):
808 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
809
Pablo Galindod5d2b452019-04-30 02:01:14 +0100810 self.assertArgSpecEquals(mod.spam,
811 ['a', 'b', 'c', 'd', 'e', 'f'],
812 'g', 'h', (3, 4, 5),
813 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500814
815 self.assertRaises(ValueError, self.assertArgSpecEquals,
816 mod2.keyworded, [])
817
818 self.assertRaises(ValueError, self.assertArgSpecEquals,
819 mod2.annotated, [])
820 self.assertRaises(ValueError, self.assertArgSpecEquals,
821 mod2.keyword_only_arg, [])
822
823
Christian Heimes3795b532007-11-08 13:48:53 +0000824 def test_getfullargspec(self):
825 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
826 kwonlyargs_e=['arg2'],
827 kwonlydefaults_e={'arg2':1},
828 formatted='(*arg1, arg2=1)')
829
830 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000831 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000832 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000833 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
834 kwonlyargs_e=['arg'],
835 formatted='(*, arg)')
836
Pablo Galindod5d2b452019-04-30 02:01:14 +0100837 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100838 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100839 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100840
841 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100842 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100843 varargs_e='args',
844 varkw_e='kwargs',
845 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100846 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100847
Pablo Galindod5d2b452019-04-30 02:01:14 +0100848 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100849 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100850 kwonlyargs_e=['e', 'f'],
851 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100852 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100853
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500854 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500855 # Issue 20684: low level introspection API must ignore __wrapped__
856 @functools.wraps(mod.spam)
857 def ham(x, y):
858 pass
859 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500860 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500861 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
862 self.assertFullArgSpecEquals(functools.partial(ham),
863 ['x', 'y'], formatted='(x, y)')
864 # Other variants
865 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500866 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
867 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500868 class C:
869 @functools.wraps(mod.spam)
870 def ham(self, x, y):
871 pass
872 pham = functools.partialmethod(ham)
873 @functools.wraps(mod.spam)
874 def __call__(self, x, y):
875 pass
876 check_method(C())
877 check_method(C.ham)
878 check_method(C().ham)
879 check_method(C.pham)
880 check_method(C().pham)
881
882 class C_new:
883 @functools.wraps(mod.spam)
884 def __new__(self, x, y):
885 pass
886 check_method(C_new)
887
888 class C_init:
889 @functools.wraps(mod.spam)
890 def __init__(self, x, y):
891 pass
892 check_method(C_init)
893
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500894 def test_getfullargspec_signature_attr(self):
895 def test():
896 pass
897 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
898 test.__signature__ = inspect.Signature(parameters=(spam_param,))
899
Pablo Galindod5d2b452019-04-30 02:01:14 +0100900 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500901
Yury Selivanov4cb93912014-01-29 11:54:12 -0500902 def test_getfullargspec_signature_annos(self):
903 def test(a:'spam') -> 'ham': pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100904 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500905 self.assertEqual(test.__annotations__, spec.annotations)
906
907 def test(): pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100908 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500909 self.assertEqual(test.__annotations__, spec.annotations)
910
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500911 @unittest.skipIf(MISSING_C_DOCSTRINGS,
912 "Signature information for builtins requires docstrings")
913 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100914 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
915 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500916
Pablo Galindod5d2b452019-04-30 02:01:14 +0100917 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
918 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500919
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500920 self.assertFullArgSpecEquals(
921 os.stat,
922 args_e=['path'],
923 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
924 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
925 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
926
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200927 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500928 @unittest.skipIf(MISSING_C_DOCSTRINGS,
929 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800930 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200931 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500932 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindoaee19f52019-05-16 21:08:15 +0100933 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500934 self.assertEqual(spec.defaults[0], 'avocado')
935
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200936 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500937 @unittest.skipIf(MISSING_C_DOCSTRINGS,
938 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800939 def test_getfullargspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200940 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500941 builtin = _testcapi.docstring_no_signature
Pablo Galindoaee19f52019-05-16 21:08:15 +0100942 with self.assertRaises(TypeError):
943 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000944
larryhastingsf36ba122018-01-28 11:13:09 -0800945 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
946 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindoaee19f52019-05-16 21:08:15 +0100947 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800948 l = list(signature.kwonlyargs)
949 sorted_l = sorted(l)
950 self.assertTrue(l)
951 self.assertEqual(l, sorted_l)
Pablo Galindoaee19f52019-05-16 21:08:15 +0100952 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800953 l = list(signature.kwonlyargs)
954 self.assertEqual(l, unsorted_keyword_only_parameters)
955
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500956 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000957 class A(object):
958 def m(self):
959 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500960 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000961
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000962 def test_classify_newstyle(self):
963 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000964
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000965 def s(): pass
966 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000967
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000968 def c(cls): pass
969 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000970
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000971 def getp(self): pass
972 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000973
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000974 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000975
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000976 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000977
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000978 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000979
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100980 dd = _BrokenDataDescriptor()
981 md = _BrokenMethodDescriptor()
982
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000983 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500984
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +0200985 self.assertIn(('__new__', 'static method', object), attrs,
986 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500987 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
988
Benjamin Peterson577473f2010-01-19 00:09:57 +0000989 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
990 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
991 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000992 self.assertIn(('m', 'method', A), attrs,
993 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000994 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
995 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100996 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
997 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000998
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000999 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001000
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001001 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001002
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001003 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001004 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1005 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
1006 self.assertIn(('p', 'property', A), attrs, 'missing property')
1007 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1008 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1009 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001010 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1011 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001012
1013
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001014 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001015
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001016 def m(self): pass
1017 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001018
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001019 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001020 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1021 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1022 self.assertIn(('p', 'property', A), attrs, 'missing property')
1023 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
1024 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1025 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001026 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1027 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001028
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001029 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001030
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001031 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001032
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001033 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001034 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1035 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1036 self.assertIn(('p', 'property', A), attrs, 'missing property')
1037 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1038 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1039 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001040 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1041 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1042
1043 def test_classify_builtin_types(self):
1044 # Simple sanity check that all built-in types can have their
1045 # attributes classified.
1046 for name in dir(__builtins__):
1047 builtin = getattr(__builtins__, name)
1048 if isinstance(builtin, type):
1049 inspect.classify_class_attrs(builtin)
1050
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001051 attrs = attrs_wo_objs(bool)
1052 self.assertIn(('__new__', 'static method', bool), attrs,
1053 'missing __new__')
1054 self.assertIn(('from_bytes', 'class method', int), attrs,
1055 'missing class method')
1056 self.assertIn(('to_bytes', 'method', int), attrs,
1057 'missing plain method')
1058 self.assertIn(('__add__', 'method', int), attrs,
1059 'missing plain method')
1060 self.assertIn(('__and__', 'method', bool), attrs,
1061 'missing plain method')
1062
Ethan Furman63c141c2013-10-18 00:27:39 -07001063 def test_classify_DynamicClassAttribute(self):
1064 class Meta(type):
1065 def __getattr__(self, name):
1066 if name == 'ham':
1067 return 'spam'
1068 return super().__getattr__(name)
1069 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001070 @types.DynamicClassAttribute
1071 def ham(self):
1072 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001073 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1074 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001075 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001076 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1077
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001078 def test_classify_overrides_bool(self):
1079 class NoBool(object):
1080 def __eq__(self, other):
1081 return NoBool()
1082
1083 def __bool__(self):
1084 raise NotImplementedError(
1085 "This object does not specify a boolean value")
1086
1087 class HasNB(object):
1088 dd = NoBool()
1089
1090 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1091 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1092
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001093 def test_classify_metaclass_class_attribute(self):
1094 class Meta(type):
1095 fish = 'slap'
1096 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001097 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001098 class Class(metaclass=Meta):
1099 pass
1100 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1101 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1102
Ethan Furman63c141c2013-10-18 00:27:39 -07001103 def test_classify_VirtualAttribute(self):
1104 class Meta(type):
1105 def __dir__(cls):
1106 return ['__class__', '__module__', '__name__', 'BOOM']
1107 def __getattr__(self, name):
1108 if name =='BOOM':
1109 return 42
1110 return super().__getattr(name)
1111 class Class(metaclass=Meta):
1112 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001113 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001114 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1115
1116 def test_classify_VirtualAttribute_multi_classes(self):
1117 class Meta1(type):
1118 def __dir__(cls):
1119 return ['__class__', '__module__', '__name__', 'one']
1120 def __getattr__(self, name):
1121 if name =='one':
1122 return 1
1123 return super().__getattr__(name)
1124 class Meta2(type):
1125 def __dir__(cls):
1126 return ['__class__', '__module__', '__name__', 'two']
1127 def __getattr__(self, name):
1128 if name =='two':
1129 return 2
1130 return super().__getattr__(name)
1131 class Meta3(Meta1, Meta2):
1132 def __dir__(cls):
1133 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1134 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1135 def __getattr__(self, name):
1136 if name =='three':
1137 return 3
1138 return super().__getattr__(name)
1139 class Class1(metaclass=Meta1):
1140 pass
1141 class Class2(Class1, metaclass=Meta3):
1142 pass
1143
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001144 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1145 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1146 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001147 cca = inspect.classify_class_attrs(Class2)
1148 for sf in (should_find1, should_find2, should_find3):
1149 self.assertIn(sf, cca)
1150
1151 def test_classify_class_attrs_with_buggy_dir(self):
1152 class M(type):
1153 def __dir__(cls):
1154 return ['__class__', '__name__', 'missing']
1155 class C(metaclass=M):
1156 pass
1157 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1158 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001159
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001160 def test_getmembers_descriptors(self):
1161 class A(object):
1162 dd = _BrokenDataDescriptor()
1163 md = _BrokenMethodDescriptor()
1164
1165 def pred_wrapper(pred):
1166 # A quick'n'dirty way to discard standard attributes of new-style
1167 # classes.
1168 class Empty(object):
1169 pass
1170 def wrapped(x):
1171 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1172 return False
1173 return pred(x)
1174 return wrapped
1175
1176 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1177 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1178
1179 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1180 [('md', A.__dict__['md'])])
1181 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1182 [('dd', A.__dict__['dd'])])
1183
1184 class B(A):
1185 pass
1186
1187 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1188 [('md', A.__dict__['md'])])
1189 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1190 [('dd', A.__dict__['dd'])])
1191
Antoine Pitrou0c603812012-01-18 17:40:18 +01001192 def test_getmembers_method(self):
1193 class B:
1194 def f(self):
1195 pass
1196
1197 self.assertIn(('f', B.f), inspect.getmembers(B))
1198 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1199 b = B()
1200 self.assertIn(('f', b.f), inspect.getmembers(b))
1201 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1202
Ethan Furmane03ea372013-09-25 07:14:41 -07001203 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001204 class M(type):
1205 def __getattr__(cls, name):
1206 if name == 'eggs':
1207 return 'scrambled'
1208 return super().__getattr__(name)
1209 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001210 @types.DynamicClassAttribute
1211 def eggs(self):
1212 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001213 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1214 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1215
1216 def test_getmembers_with_buggy_dir(self):
1217 class M(type):
1218 def __dir__(cls):
1219 return ['__class__', '__name__', 'missing']
1220 class C(metaclass=M):
1221 pass
1222 attrs = [a[0] for a in inspect.getmembers(C)]
1223 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001224
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001225class TestIsDataDescriptor(unittest.TestCase):
1226
1227 def test_custom_descriptors(self):
1228 class NonDataDescriptor:
1229 def __get__(self, value, type=None): pass
1230 class DataDescriptor0:
1231 def __set__(self, name, value): pass
1232 class DataDescriptor1:
1233 def __delete__(self, name): pass
1234 class DataDescriptor2:
1235 __set__ = None
1236 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1237 'class with only __get__ not a data descriptor')
1238 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1239 'class with __set__ is a data descriptor')
1240 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1241 'class with __delete__ is a data descriptor')
1242 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1243 'class with __set__ = None is a data descriptor')
1244
1245 def test_slot(self):
1246 class Slotted:
1247 __slots__ = 'foo',
1248 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1249 'a slot is a data descriptor')
1250
1251 def test_property(self):
1252 class Propertied:
1253 @property
1254 def a_property(self):
1255 pass
1256 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1257 'a property is a data descriptor')
1258
1259 def test_functions(self):
1260 class Test(object):
1261 def instance_method(self): pass
1262 @classmethod
1263 def class_method(cls): pass
1264 @staticmethod
1265 def static_method(): pass
1266 def function():
1267 pass
1268 a_lambda = lambda: None
1269 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1270 'a instance method is not a data descriptor')
1271 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1272 'a class method is not a data descriptor')
1273 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1274 'a static method is not a data descriptor')
1275 self.assertFalse(inspect.isdatadescriptor(function),
1276 'a function is not a data descriptor')
1277 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1278 'a lambda is not a data descriptor')
1279
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001280
Nick Coghlan2f92e542012-06-23 19:39:55 +10001281_global_ref = object()
1282class TestGetClosureVars(unittest.TestCase):
1283
1284 def test_name_resolution(self):
1285 # Basic test of the 4 different resolution mechanisms
1286 def f(nonlocal_ref):
1287 def g(local_ref):
1288 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1289 return g
1290 _arg = object()
1291 nonlocal_vars = {"nonlocal_ref": _arg}
1292 global_vars = {"_global_ref": _global_ref}
1293 builtin_vars = {"print": print}
1294 unbound_names = {"unbound_ref"}
1295 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1296 builtin_vars, unbound_names)
1297 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1298
1299 def test_generator_closure(self):
1300 def f(nonlocal_ref):
1301 def g(local_ref):
1302 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1303 yield
1304 return g
1305 _arg = object()
1306 nonlocal_vars = {"nonlocal_ref": _arg}
1307 global_vars = {"_global_ref": _global_ref}
1308 builtin_vars = {"print": print}
1309 unbound_names = {"unbound_ref"}
1310 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1311 builtin_vars, unbound_names)
1312 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1313
1314 def test_method_closure(self):
1315 class C:
1316 def f(self, nonlocal_ref):
1317 def g(local_ref):
1318 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1319 return g
1320 _arg = object()
1321 nonlocal_vars = {"nonlocal_ref": _arg}
1322 global_vars = {"_global_ref": _global_ref}
1323 builtin_vars = {"print": print}
1324 unbound_names = {"unbound_ref"}
1325 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1326 builtin_vars, unbound_names)
1327 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1328
1329 def test_nonlocal_vars(self):
1330 # More complex tests of nonlocal resolution
1331 def _nonlocal_vars(f):
1332 return inspect.getclosurevars(f).nonlocals
1333
1334 def make_adder(x):
1335 def add(y):
1336 return x + y
1337 return add
1338
1339 def curry(func, arg1):
1340 return lambda arg2: func(arg1, arg2)
1341
1342 def less_than(a, b):
1343 return a < b
1344
1345 # The infamous Y combinator.
1346 def Y(le):
1347 def g(f):
1348 return le(lambda x: f(f)(x))
1349 Y.g_ref = g
1350 return g(g)
1351
1352 def check_y_combinator(func):
1353 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1354
1355 inc = make_adder(1)
1356 add_two = make_adder(2)
1357 greater_than_five = curry(less_than, 5)
1358
1359 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1360 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1361 self.assertEqual(_nonlocal_vars(greater_than_five),
1362 {'arg1': 5, 'func': less_than})
1363 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1364 {'x': 3})
1365 Y(check_y_combinator)
1366
1367 def test_getclosurevars_empty(self):
1368 def foo(): pass
1369 _empty = inspect.ClosureVars({}, {}, {}, set())
1370 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1371 self.assertEqual(inspect.getclosurevars(foo), _empty)
1372
1373 def test_getclosurevars_error(self):
1374 class T: pass
1375 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1376 self.assertRaises(TypeError, inspect.getclosurevars, list)
1377 self.assertRaises(TypeError, inspect.getclosurevars, {})
1378
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001379 def _private_globals(self):
1380 code = """def f(): print(path)"""
1381 ns = {}
1382 exec(code, ns)
1383 return ns["f"], ns
1384
1385 def test_builtins_fallback(self):
1386 f, ns = self._private_globals()
1387 ns.pop("__builtins__", None)
1388 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1389 self.assertEqual(inspect.getclosurevars(f), expected)
1390
1391 def test_builtins_as_dict(self):
1392 f, ns = self._private_globals()
1393 ns["__builtins__"] = {"path":1}
1394 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1395 self.assertEqual(inspect.getclosurevars(f), expected)
1396
1397 def test_builtins_as_module(self):
1398 f, ns = self._private_globals()
1399 ns["__builtins__"] = os
1400 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1401 self.assertEqual(inspect.getclosurevars(f), expected)
1402
Nick Coghlan2f92e542012-06-23 19:39:55 +10001403
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001404class TestGetcallargsFunctions(unittest.TestCase):
1405
1406 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1407 locs = dict(locs or {}, func=func)
1408 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001409 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1410 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001411 self.assertEqual(r1, r2)
1412
1413 def assertEqualException(self, func, call_param_string, locs=None):
1414 locs = dict(locs or {}, func=func)
1415 try:
1416 eval('func(%s)' % call_param_string, None, locs)
1417 except Exception as e:
1418 ex1 = e
1419 else:
1420 self.fail('Exception not raised')
1421 try:
Pablo Galindoaee19f52019-05-16 21:08:15 +01001422 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1423 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001424 except Exception as e:
1425 ex2 = e
1426 else:
1427 self.fail('Exception not raised')
1428 self.assertIs(type(ex1), type(ex2))
1429 self.assertEqual(str(ex1), str(ex2))
1430 del ex1, ex2
1431
1432 def makeCallable(self, signature):
1433 """Create a function that returns its locals()"""
1434 code = "lambda %s: locals()"
1435 return eval(code % signature)
1436
1437 def test_plain(self):
1438 f = self.makeCallable('a, b=1')
1439 self.assertEqualCallArgs(f, '2')
1440 self.assertEqualCallArgs(f, '2, 3')
1441 self.assertEqualCallArgs(f, 'a=2')
1442 self.assertEqualCallArgs(f, 'b=3, a=2')
1443 self.assertEqualCallArgs(f, '2, b=3')
1444 # expand *iterable / **mapping
1445 self.assertEqualCallArgs(f, '*(2,)')
1446 self.assertEqualCallArgs(f, '*[2]')
1447 self.assertEqualCallArgs(f, '*(2, 3)')
1448 self.assertEqualCallArgs(f, '*[2, 3]')
1449 self.assertEqualCallArgs(f, '**{"a":2}')
1450 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1451 self.assertEqualCallArgs(f, '2, **{"b":3}')
1452 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1453 # expand UserList / UserDict
1454 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1455 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1456 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1457 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1458 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1459
1460 def test_varargs(self):
1461 f = self.makeCallable('a, b=1, *c')
1462 self.assertEqualCallArgs(f, '2')
1463 self.assertEqualCallArgs(f, '2, 3')
1464 self.assertEqualCallArgs(f, '2, 3, 4')
1465 self.assertEqualCallArgs(f, '*(2,3,4)')
1466 self.assertEqualCallArgs(f, '2, *[3,4]')
1467 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1468
1469 def test_varkw(self):
1470 f = self.makeCallable('a, b=1, **c')
1471 self.assertEqualCallArgs(f, 'a=2')
1472 self.assertEqualCallArgs(f, '2, b=3, c=4')
1473 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1474 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1475 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1476 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1477 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1478 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1479 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1480
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001481 def test_varkw_only(self):
1482 # issue11256:
1483 f = self.makeCallable('**c')
1484 self.assertEqualCallArgs(f, '')
1485 self.assertEqualCallArgs(f, 'a=1')
1486 self.assertEqualCallArgs(f, 'a=1, b=2')
1487 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1488 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1489 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1490
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001491 def test_keyword_only(self):
1492 f = self.makeCallable('a=3, *, c, d=2')
1493 self.assertEqualCallArgs(f, 'c=3')
1494 self.assertEqualCallArgs(f, 'c=3, a=3')
1495 self.assertEqualCallArgs(f, 'a=2, c=4')
1496 self.assertEqualCallArgs(f, '4, c=4')
1497 self.assertEqualException(f, '')
1498 self.assertEqualException(f, '3')
1499 self.assertEqualException(f, 'a=3')
1500 self.assertEqualException(f, 'd=4')
1501
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001502 f = self.makeCallable('*, c, d=2')
1503 self.assertEqualCallArgs(f, 'c=3')
1504 self.assertEqualCallArgs(f, 'c=3, d=4')
1505 self.assertEqualCallArgs(f, 'd=4, c=3')
1506
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001507 def test_multiple_features(self):
1508 f = self.makeCallable('a, b=2, *f, **g')
1509 self.assertEqualCallArgs(f, '2, 3, 7')
1510 self.assertEqualCallArgs(f, '2, 3, x=8')
1511 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1512 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1513 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1514 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1515 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1516 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1517 '(4,[5,6])]), **collections.UserDict('
1518 'y=9, z=10)')
1519
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001520 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1521 self.assertEqualCallArgs(f, '2, 3, x=8')
1522 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1523 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1524 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1525 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1526 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1527 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1528 '(4,[5,6])]), q=0, **collections.UserDict('
1529 'y=9, z=10)')
1530
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001531 def test_errors(self):
1532 f0 = self.makeCallable('')
1533 f1 = self.makeCallable('a, b')
1534 f2 = self.makeCallable('a, b=1')
1535 # f0 takes no arguments
1536 self.assertEqualException(f0, '1')
1537 self.assertEqualException(f0, 'x=1')
1538 self.assertEqualException(f0, '1,x=1')
1539 # f1 takes exactly 2 arguments
1540 self.assertEqualException(f1, '')
1541 self.assertEqualException(f1, '1')
1542 self.assertEqualException(f1, 'a=2')
1543 self.assertEqualException(f1, 'b=3')
1544 # f2 takes at least 1 argument
1545 self.assertEqualException(f2, '')
1546 self.assertEqualException(f2, 'b=3')
1547 for f in f1, f2:
1548 # f1/f2 takes exactly/at most 2 arguments
1549 self.assertEqualException(f, '2, 3, 4')
1550 self.assertEqualException(f, '1, 2, 3, a=1')
1551 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001552 # XXX: success of this one depends on dict order
1553 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001554 # f got an unexpected keyword argument
1555 self.assertEqualException(f, 'c=2')
1556 self.assertEqualException(f, '2, c=3')
1557 self.assertEqualException(f, '2, 3, c=4')
1558 self.assertEqualException(f, '2, c=4, b=3')
1559 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1560 # f got multiple values for keyword argument
1561 self.assertEqualException(f, '1, a=2')
1562 self.assertEqualException(f, '1, **{"a":2}')
1563 self.assertEqualException(f, '1, 2, b=3')
1564 # XXX: Python inconsistency
1565 # - for functions and bound methods: unexpected keyword 'c'
1566 # - for unbound methods: multiple values for keyword 'a'
1567 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001568 # issue11256:
1569 f3 = self.makeCallable('**c')
1570 self.assertEqualException(f3, '1, 2')
1571 self.assertEqualException(f3, '1, 2, a=1, b=2')
1572 f4 = self.makeCallable('*, a, b=0')
1573 self.assertEqualException(f3, '1, 2')
1574 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001575
Yury Selivanov875df202014-03-27 18:23:03 -04001576 # issue #20816: getcallargs() fails to iterate over non-existent
1577 # kwonlydefaults and raises a wrong TypeError
1578 def f5(*, a): pass
1579 with self.assertRaisesRegex(TypeError,
1580 'missing 1 required keyword-only'):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001581 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001582
1583
Yury Selivanovdccfa132014-03-27 18:42:52 -04001584 # issue20817:
1585 def f6(a, b, c):
1586 pass
1587 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001588 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001589
Dong-hee Naa9cab432018-05-30 00:04:08 +09001590 # bpo-33197
1591 with self.assertRaisesRegex(ValueError,
1592 'variadic keyword parameters cannot'
1593 ' have default values'):
1594 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1595 default=42)
1596 with self.assertRaisesRegex(ValueError,
1597 "value 5 is not a valid Parameter.kind"):
1598 inspect.Parameter("bar", kind=5, default=42)
1599
1600 with self.assertRaisesRegex(TypeError,
1601 'name must be a str, not a int'):
1602 inspect.Parameter(123, kind=4)
1603
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001604class TestGetcallargsMethods(TestGetcallargsFunctions):
1605
1606 def setUp(self):
1607 class Foo(object):
1608 pass
1609 self.cls = Foo
1610 self.inst = Foo()
1611
1612 def makeCallable(self, signature):
1613 assert 'self' not in signature
1614 mk = super(TestGetcallargsMethods, self).makeCallable
1615 self.cls.method = mk('self, ' + signature)
1616 return self.inst.method
1617
1618class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1619
1620 def makeCallable(self, signature):
1621 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1622 return self.cls.method
1623
1624 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1625 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1626 *self._getAssertEqualParams(func, call_params_string, locs))
1627
1628 def assertEqualException(self, func, call_params_string, locs=None):
1629 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1630 *self._getAssertEqualParams(func, call_params_string, locs))
1631
1632 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1633 assert 'inst' not in call_params_string
1634 locs = dict(locs or {}, inst=self.inst)
1635 return (func, 'inst,' + call_params_string, locs)
1636
Michael Foord95fc51d2010-11-20 15:07:30 +00001637
1638class TestGetattrStatic(unittest.TestCase):
1639
1640 def test_basic(self):
1641 class Thing(object):
1642 x = object()
1643
1644 thing = Thing()
1645 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1646 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1647 with self.assertRaises(AttributeError):
1648 inspect.getattr_static(thing, 'y')
1649
1650 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1651
1652 def test_inherited(self):
1653 class Thing(object):
1654 x = object()
1655 class OtherThing(Thing):
1656 pass
1657
1658 something = OtherThing()
1659 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1660
1661 def test_instance_attr(self):
1662 class Thing(object):
1663 x = 2
1664 def __init__(self, x):
1665 self.x = x
1666 thing = Thing(3)
1667 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1668 del thing.x
1669 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1670
1671 def test_property(self):
1672 class Thing(object):
1673 @property
1674 def x(self):
1675 raise AttributeError("I'm pretending not to exist")
1676 thing = Thing()
1677 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1678
Ezio Melotti75cbd732011-04-28 00:59:29 +03001679 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001680 class descriptor(object):
1681 def __get__(*_):
1682 raise AttributeError("I'm pretending not to exist")
1683 desc = descriptor()
1684 class Thing(object):
1685 x = desc
1686 thing = Thing()
1687 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1688
1689 def test_classAttribute(self):
1690 class Thing(object):
1691 x = object()
1692
1693 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1694
Ethan Furmane03ea372013-09-25 07:14:41 -07001695 def test_classVirtualAttribute(self):
1696 class Thing(object):
1697 @types.DynamicClassAttribute
1698 def x(self):
1699 return self._x
1700 _x = object()
1701
1702 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1703
Michael Foord95fc51d2010-11-20 15:07:30 +00001704 def test_inherited_classattribute(self):
1705 class Thing(object):
1706 x = object()
1707 class OtherThing(Thing):
1708 pass
1709
1710 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1711
1712 def test_slots(self):
1713 class Thing(object):
1714 y = 'bar'
1715 __slots__ = ['x']
1716 def __init__(self):
1717 self.x = 'foo'
1718 thing = Thing()
1719 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1720 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1721
1722 del thing.x
1723 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1724
1725 def test_metaclass(self):
1726 class meta(type):
1727 attr = 'foo'
1728 class Thing(object, metaclass=meta):
1729 pass
1730 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1731
1732 class sub(meta):
1733 pass
1734 class OtherThing(object, metaclass=sub):
1735 x = 3
1736 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1737
1738 class OtherOtherThing(OtherThing):
1739 pass
1740 # this test is odd, but it was added as it exposed a bug
1741 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1742
1743 def test_no_dict_no_slots(self):
1744 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1745 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1746
1747 def test_no_dict_no_slots_instance_member(self):
1748 # returns descriptor
1749 with open(__file__) as handle:
1750 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1751
1752 def test_inherited_slots(self):
1753 # returns descriptor
1754 class Thing(object):
1755 __slots__ = ['x']
1756 def __init__(self):
1757 self.x = 'foo'
1758
1759 class OtherThing(Thing):
1760 pass
1761 # it would be nice if this worked...
1762 # we get the descriptor instead of the instance attribute
1763 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1764
1765 def test_descriptor(self):
1766 class descriptor(object):
1767 def __get__(self, instance, owner):
1768 return 3
1769 class Foo(object):
1770 d = descriptor()
1771
1772 foo = Foo()
1773
1774 # for a non data descriptor we return the instance attribute
1775 foo.__dict__['d'] = 1
1776 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1777
Mike53f7a7c2017-12-14 14:04:53 +03001778 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001779 # descriptor
1780 descriptor.__set__ = lambda s, i, v: None
1781 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1782
1783
1784 def test_metaclass_with_descriptor(self):
1785 class descriptor(object):
1786 def __get__(self, instance, owner):
1787 return 3
1788 class meta(type):
1789 d = descriptor()
1790 class Thing(object, metaclass=meta):
1791 pass
1792 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1793
1794
Michael Foordcc7ebb82010-11-20 16:20:16 +00001795 def test_class_as_property(self):
1796 class Base(object):
1797 foo = 3
1798
1799 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001800 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001801 @property
1802 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001803 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001804 return object
1805
Michael Foord35184ed2010-11-20 16:58:30 +00001806 instance = Something()
1807 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1808 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001809 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1810
Michael Foorde5162652010-11-20 16:40:44 +00001811 def test_mro_as_property(self):
1812 class Meta(type):
1813 @property
1814 def __mro__(self):
1815 return (object,)
1816
1817 class Base(object):
1818 foo = 3
1819
1820 class Something(Base, metaclass=Meta):
1821 pass
1822
1823 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1824 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1825
Michael Foorddcebe0f2011-03-15 19:20:44 -04001826 def test_dict_as_property(self):
1827 test = self
1828 test.called = False
1829
1830 class Foo(dict):
1831 a = 3
1832 @property
1833 def __dict__(self):
1834 test.called = True
1835 return {}
1836
1837 foo = Foo()
1838 foo.a = 4
1839 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1840 self.assertFalse(test.called)
1841
1842 def test_custom_object_dict(self):
1843 test = self
1844 test.called = False
1845
1846 class Custom(dict):
1847 def get(self, key, default=None):
1848 test.called = True
1849 super().get(key, default)
1850
1851 class Foo(object):
1852 a = 3
1853 foo = Foo()
1854 foo.__dict__ = Custom()
1855 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1856 self.assertFalse(test.called)
1857
1858 def test_metaclass_dict_as_property(self):
1859 class Meta(type):
1860 @property
1861 def __dict__(self):
1862 self.executed = True
1863
1864 class Thing(metaclass=Meta):
1865 executed = False
1866
1867 def __init__(self):
1868 self.spam = 42
1869
1870 instance = Thing()
1871 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1872 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001873
Michael Foorda51623b2011-12-18 22:01:40 +00001874 def test_module(self):
1875 sentinel = object()
1876 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1877 sentinel)
1878
Michael Foord3ba95f82011-12-22 01:13:37 +00001879 def test_metaclass_with_metaclass_with_dict_as_property(self):
1880 class MetaMeta(type):
1881 @property
1882 def __dict__(self):
1883 self.executed = True
1884 return dict(spam=42)
1885
1886 class Meta(type, metaclass=MetaMeta):
1887 executed = False
1888
1889 class Thing(metaclass=Meta):
1890 pass
1891
1892 with self.assertRaises(AttributeError):
1893 inspect.getattr_static(Thing, "spam")
1894 self.assertFalse(Thing.executed)
1895
Nick Coghlane0f04652010-11-21 03:44:04 +00001896class TestGetGeneratorState(unittest.TestCase):
1897
1898 def setUp(self):
1899 def number_generator():
1900 for number in range(5):
1901 yield number
1902 self.generator = number_generator()
1903
1904 def _generatorstate(self):
1905 return inspect.getgeneratorstate(self.generator)
1906
1907 def test_created(self):
1908 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1909
1910 def test_suspended(self):
1911 next(self.generator)
1912 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1913
1914 def test_closed_after_exhaustion(self):
1915 for i in self.generator:
1916 pass
1917 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1918
1919 def test_closed_after_immediate_exception(self):
1920 with self.assertRaises(RuntimeError):
1921 self.generator.throw(RuntimeError)
1922 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1923
1924 def test_running(self):
1925 # As mentioned on issue #10220, checking for the RUNNING state only
1926 # makes sense inside the generator itself.
1927 # The following generator checks for this by using the closure's
1928 # reference to self and the generator state checking helper method
1929 def running_check_generator():
1930 for number in range(5):
1931 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1932 yield number
1933 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1934 self.generator = running_check_generator()
1935 # Running up to the first yield
1936 next(self.generator)
1937 # Running after the first yield
1938 next(self.generator)
1939
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001940 def test_easy_debugging(self):
1941 # repr() and str() of a generator state should contain the state name
1942 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1943 for name in names:
1944 state = getattr(inspect, name)
1945 self.assertIn(name, repr(state))
1946 self.assertIn(name, str(state))
1947
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001948 def test_getgeneratorlocals(self):
1949 def each(lst, a=None):
1950 b=(1, 2, 3)
1951 for v in lst:
1952 if v == 3:
1953 c = 12
1954 yield v
1955
1956 numbers = each([1, 2, 3])
1957 self.assertEqual(inspect.getgeneratorlocals(numbers),
1958 {'a': None, 'lst': [1, 2, 3]})
1959 next(numbers)
1960 self.assertEqual(inspect.getgeneratorlocals(numbers),
1961 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1962 'b': (1, 2, 3)})
1963 next(numbers)
1964 self.assertEqual(inspect.getgeneratorlocals(numbers),
1965 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1966 'b': (1, 2, 3)})
1967 next(numbers)
1968 self.assertEqual(inspect.getgeneratorlocals(numbers),
1969 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1970 'b': (1, 2, 3), 'c': 12})
1971 try:
1972 next(numbers)
1973 except StopIteration:
1974 pass
1975 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1976
1977 def test_getgeneratorlocals_empty(self):
1978 def yield_one():
1979 yield 1
1980 one = yield_one()
1981 self.assertEqual(inspect.getgeneratorlocals(one), {})
1982 try:
1983 next(one)
1984 except StopIteration:
1985 pass
1986 self.assertEqual(inspect.getgeneratorlocals(one), {})
1987
1988 def test_getgeneratorlocals_error(self):
1989 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1990 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1991 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1992 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1993
Nick Coghlane0f04652010-11-21 03:44:04 +00001994
Yury Selivanov5376ba92015-06-22 12:19:30 -04001995class TestGetCoroutineState(unittest.TestCase):
1996
1997 def setUp(self):
1998 @types.coroutine
1999 def number_coroutine():
2000 for number in range(5):
2001 yield number
2002 async def coroutine():
2003 await number_coroutine()
2004 self.coroutine = coroutine()
2005
2006 def tearDown(self):
2007 self.coroutine.close()
2008
2009 def _coroutinestate(self):
2010 return inspect.getcoroutinestate(self.coroutine)
2011
2012 def test_created(self):
2013 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
2014
2015 def test_suspended(self):
2016 self.coroutine.send(None)
2017 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
2018
2019 def test_closed_after_exhaustion(self):
2020 while True:
2021 try:
2022 self.coroutine.send(None)
2023 except StopIteration:
2024 break
2025
2026 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2027
2028 def test_closed_after_immediate_exception(self):
2029 with self.assertRaises(RuntimeError):
2030 self.coroutine.throw(RuntimeError)
2031 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2032
2033 def test_easy_debugging(self):
2034 # repr() and str() of a coroutine state should contain the state name
2035 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2036 for name in names:
2037 state = getattr(inspect, name)
2038 self.assertIn(name, repr(state))
2039 self.assertIn(name, str(state))
2040
2041 def test_getcoroutinelocals(self):
2042 @types.coroutine
2043 def gencoro():
2044 yield
2045
2046 gencoro = gencoro()
2047 async def func(a=None):
2048 b = 'spam'
2049 await gencoro
2050
2051 coro = func()
2052 self.assertEqual(inspect.getcoroutinelocals(coro),
2053 {'a': None, 'gencoro': gencoro})
2054 coro.send(None)
2055 self.assertEqual(inspect.getcoroutinelocals(coro),
2056 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2057
2058
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002059class MySignature(inspect.Signature):
2060 # Top-level to make it picklable;
2061 # used in test_signature_object_pickle
2062 pass
2063
2064class MyParameter(inspect.Parameter):
2065 # Top-level to make it picklable;
2066 # used in test_signature_object_pickle
2067 pass
2068
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002069
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002070
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002071class TestSignatureObject(unittest.TestCase):
2072 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002073 def signature(func, **kw):
2074 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002075 return (tuple((param.name,
2076 (... if param.default is param.empty else param.default),
2077 (... if param.annotation is param.empty
2078 else param.annotation),
2079 str(param.kind).lower())
2080 for param in sig.parameters.values()),
2081 (... if sig.return_annotation is sig.empty
2082 else sig.return_annotation))
2083
2084 def test_signature_object(self):
2085 S = inspect.Signature
2086 P = inspect.Parameter
2087
2088 self.assertEqual(str(S()), '()')
Jens Reidel611836a2020-03-18 03:22:46 +01002089 self.assertEqual(repr(S().parameters), 'mappingproxy(OrderedDict())')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002090
Yury Selivanov07a9e452014-01-29 10:58:16 -05002091 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002092 pass
2093 sig = inspect.signature(test)
2094 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002095 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002096 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002097 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002098 args = sig.parameters['args']
2099 ko = sig.parameters['ko']
2100 kwargs = sig.parameters['kwargs']
2101
2102 S((po, pk, args, ko, kwargs))
2103
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002104 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002105 S((pk, po, args, ko, kwargs))
2106
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002107 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002108 S((po, args, pk, ko, kwargs))
2109
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002110 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002111 S((args, po, pk, ko, kwargs))
2112
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002113 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002114 S((po, pk, args, kwargs, ko))
2115
2116 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002117 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002118 S((po, pk, args, kwargs2, ko))
2119
Yury Selivanov07a9e452014-01-29 10:58:16 -05002120 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2121 S((pod, po))
2122
2123 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2124 S((po, pkd, pk))
2125
2126 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2127 S((pkd, pk))
2128
Yury Selivanov374375d2014-03-27 12:41:53 -04002129 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002130 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002131
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002132 def test_signature_object_pickle(self):
2133 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2134 foo_partial = functools.partial(foo, a=1)
2135
2136 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002137
2138 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2139 with self.subTest(pickle_ver=ver, subclass=False):
2140 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2141 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002142
2143 # Test that basic sub-classing works
2144 sig = inspect.signature(foo)
2145 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2146 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2147 mysig = MySignature().replace(parameters=myparams.values(),
2148 return_annotation=sig.return_annotation)
2149 self.assertTrue(isinstance(mysig, MySignature))
2150 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2151
2152 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2153 with self.subTest(pickle_ver=ver, subclass=True):
2154 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2155 self.assertEqual(mysig, sig_pickled)
2156 self.assertTrue(isinstance(sig_pickled, MySignature))
2157 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2158 MyParameter))
2159
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002160 def test_signature_immutability(self):
2161 def test(a):
2162 pass
2163 sig = inspect.signature(test)
2164
2165 with self.assertRaises(AttributeError):
2166 sig.foo = 'bar'
2167
2168 with self.assertRaises(TypeError):
2169 sig.parameters['a'] = None
2170
2171 def test_signature_on_noarg(self):
2172 def test():
2173 pass
2174 self.assertEqual(self.signature(test), ((), ...))
2175
2176 def test_signature_on_wargs(self):
2177 def test(a, b:'foo') -> 123:
2178 pass
2179 self.assertEqual(self.signature(test),
2180 ((('a', ..., ..., "positional_or_keyword"),
2181 ('b', ..., 'foo', "positional_or_keyword")),
2182 123))
2183
2184 def test_signature_on_wkwonly(self):
2185 def test(*, a:float, b:str) -> int:
2186 pass
2187 self.assertEqual(self.signature(test),
2188 ((('a', ..., float, "keyword_only"),
2189 ('b', ..., str, "keyword_only")),
2190 int))
2191
2192 def test_signature_on_complex_args(self):
2193 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2194 pass
2195 self.assertEqual(self.signature(test),
2196 ((('a', ..., ..., "positional_or_keyword"),
2197 ('b', 10, 'foo', "positional_or_keyword"),
2198 ('args', ..., 'bar', "var_positional"),
2199 ('spam', ..., 'baz', "keyword_only"),
2200 ('ham', 123, ..., "keyword_only"),
2201 ('kwargs', ..., int, "var_keyword")),
2202 ...))
2203
Dong-hee Na378d7062017-05-18 04:00:51 +09002204 def test_signature_without_self(self):
2205 def test_args_only(*args): # NOQA
2206 pass
2207
2208 def test_args_kwargs_only(*args, **kwargs): # NOQA
2209 pass
2210
2211 class A:
2212 @classmethod
2213 def test_classmethod(*args): # NOQA
2214 pass
2215
2216 @staticmethod
2217 def test_staticmethod(*args): # NOQA
2218 pass
2219
2220 f1 = functools.partialmethod((test_classmethod), 1)
2221 f2 = functools.partialmethod((test_args_only), 1)
2222 f3 = functools.partialmethod((test_staticmethod), 1)
2223 f4 = functools.partialmethod((test_args_kwargs_only),1)
2224
2225 self.assertEqual(self.signature(test_args_only),
2226 ((('args', ..., ..., 'var_positional'),), ...))
2227 self.assertEqual(self.signature(test_args_kwargs_only),
2228 ((('args', ..., ..., 'var_positional'),
2229 ('kwargs', ..., ..., 'var_keyword')), ...))
2230 self.assertEqual(self.signature(A.f1),
2231 ((('args', ..., ..., 'var_positional'),), ...))
2232 self.assertEqual(self.signature(A.f2),
2233 ((('args', ..., ..., 'var_positional'),), ...))
2234 self.assertEqual(self.signature(A.f3),
2235 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002236 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002237 ((('args', ..., ..., 'var_positional'),
2238 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002239 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002240 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2241 "Signature information for builtins requires docstrings")
2242 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002243 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002244
Larry Hastings5c661892014-01-24 06:17:25 -08002245 def test_unbound_method(o):
2246 """Use this to test unbound methods (things that should have a self)"""
2247 signature = inspect.signature(o)
2248 self.assertTrue(isinstance(signature, inspect.Signature))
2249 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2250 return signature
2251
2252 def test_callable(o):
2253 """Use this to test bound methods or normal callables (things that don't expect self)"""
2254 signature = inspect.signature(o)
2255 self.assertTrue(isinstance(signature, inspect.Signature))
2256 if signature.parameters:
2257 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2258 return signature
2259
2260 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002261 def p(name): return signature.parameters[name].default
2262 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002263 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002264 self.assertEqual(p('d'), 3.14)
2265 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002266 self.assertEqual(p('n'), None)
2267 self.assertEqual(p('t'), True)
2268 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002269 self.assertEqual(p('local'), 3)
2270 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002271 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002272
Larry Hastings5c661892014-01-24 06:17:25 -08002273 test_callable(object)
2274
2275 # normal method
2276 # (PyMethodDescr_Type, "method_descriptor")
2277 test_unbound_method(_pickle.Pickler.dump)
2278 d = _pickle.Pickler(io.StringIO())
2279 test_callable(d.dump)
2280
2281 # static method
Serhiy Storchaka279f4462019-09-14 12:24:05 +03002282 test_callable(bytes.maketrans)
2283 test_callable(b'abc'.maketrans)
Larry Hastings5c661892014-01-24 06:17:25 -08002284
2285 # class method
2286 test_callable(dict.fromkeys)
2287 test_callable({}.fromkeys)
2288
2289 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2290 test_unbound_method(type.__call__)
2291 test_unbound_method(int.__add__)
2292 test_callable((3).__add__)
2293
2294 # _PyMethodWrapper_Type
2295 # support for 'method-wrapper'
2296 test_callable(min.__call__)
2297
Larry Hastings2623c8c2014-02-08 22:15:29 -08002298 # This doesn't work now.
2299 # (We don't have a valid signature for "type" in 3.4)
2300 with self.assertRaisesRegex(ValueError, "no signature found"):
2301 class ThisWorksNow:
2302 __call__ = type
2303 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002304
Yury Selivanov056e2652014-03-02 12:25:27 -05002305 # Regression test for issue #20786
2306 test_unbound_method(dict.__delitem__)
2307 test_unbound_method(property.__delete__)
2308
Zachary Ware8ef887c2015-04-13 18:22:35 -05002309 # Regression test for issue #20586
2310 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2311
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002312 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002313 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2314 "Signature information for builtins requires docstrings")
2315 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002316 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002317 func = _testcapi.docstring_with_signature_with_defaults
2318
2319 def decorator(func):
2320 @functools.wraps(func)
2321 def wrapper(*args, **kwargs) -> int:
2322 return func(*args, **kwargs)
2323 return wrapper
2324
2325 decorated_func = decorator(func)
2326
2327 self.assertEqual(inspect.signature(func),
2328 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002329
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002330 def wrapper_like(*args, **kwargs) -> int: pass
2331 self.assertEqual(inspect.signature(decorated_func,
2332 follow_wrapped=False),
2333 inspect.signature(wrapper_like))
2334
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002335 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002336 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002337 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002338 with self.assertRaisesRegex(ValueError,
2339 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002340 inspect.signature(_testcapi.docstring_no_signature)
2341
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002342 with self.assertRaisesRegex(ValueError,
2343 'no signature found for builtin'):
2344 inspect.signature(str)
2345
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002346 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002347 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002348 inspect.signature(42)
2349
Yury Selivanov63da7c72014-01-31 14:48:37 -05002350 def test_signature_from_functionlike_object(self):
2351 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2352 pass
2353
2354 class funclike:
2355 # Has to be callable, and have correct
2356 # __code__, __annotations__, __defaults__, __name__,
2357 # and __kwdefaults__ attributes
2358
2359 def __init__(self, func):
2360 self.__name__ = func.__name__
2361 self.__code__ = func.__code__
2362 self.__annotations__ = func.__annotations__
2363 self.__defaults__ = func.__defaults__
2364 self.__kwdefaults__ = func.__kwdefaults__
2365 self.func = func
2366
2367 def __call__(self, *args, **kwargs):
2368 return self.func(*args, **kwargs)
2369
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002370 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002371
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002372 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002373 self.assertEqual(sig_funclike, sig_func)
2374
2375 sig_funclike = inspect.signature(funclike(func))
2376 self.assertEqual(sig_funclike, sig_func)
2377
2378 # If object is not a duck type of function, then
2379 # signature will try to get a signature for its '__call__'
2380 # method
2381 fl = funclike(func)
2382 del fl.__defaults__
2383 self.assertEqual(self.signature(fl),
2384 ((('args', ..., ..., "var_positional"),
2385 ('kwargs', ..., ..., "var_keyword")),
2386 ...))
2387
Yury Selivanova773de02014-02-21 18:30:53 -05002388 # Test with cython-like builtins:
2389 _orig_isdesc = inspect.ismethoddescriptor
2390 def _isdesc(obj):
2391 if hasattr(obj, '_builtinmock'):
2392 return True
2393 return _orig_isdesc(obj)
2394
2395 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2396 builtin_func = funclike(func)
2397 # Make sure that our mock setup is working
2398 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2399 builtin_func._builtinmock = True
2400 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2401 self.assertEqual(inspect.signature(builtin_func), sig_func)
2402
Yury Selivanov63da7c72014-01-31 14:48:37 -05002403 def test_signature_functionlike_class(self):
2404 # We only want to duck type function-like objects,
2405 # not classes.
2406
2407 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2408 pass
2409
2410 class funclike:
2411 def __init__(self, marker):
2412 pass
2413
2414 __name__ = func.__name__
2415 __code__ = func.__code__
2416 __annotations__ = func.__annotations__
2417 __defaults__ = func.__defaults__
2418 __kwdefaults__ = func.__kwdefaults__
2419
Yury Selivanov63da7c72014-01-31 14:48:37 -05002420 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2421
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002422 def test_signature_on_method(self):
2423 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002424 def __init__(*args):
2425 pass
2426 def m1(self, arg1, arg2=1) -> int:
2427 pass
2428 def m2(*args):
2429 pass
2430 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002431 pass
2432
Yury Selivanov62560fb2014-01-28 12:26:24 -05002433 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002434 ((('arg1', ..., ..., "positional_or_keyword"),
2435 ('arg2', 1, ..., "positional_or_keyword")),
2436 int))
2437
Yury Selivanov62560fb2014-01-28 12:26:24 -05002438 self.assertEqual(self.signature(Test().m2),
2439 ((('args', ..., ..., "var_positional"),),
2440 ...))
2441
2442 self.assertEqual(self.signature(Test),
2443 ((('args', ..., ..., "var_positional"),),
2444 ...))
2445
2446 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2447 self.signature(Test())
2448
Yury Selivanov46c759d2015-05-27 21:56:53 -04002449 def test_signature_wrapped_bound_method(self):
2450 # Issue 24298
2451 class Test:
2452 def m1(self, arg1, arg2=1) -> int:
2453 pass
2454 @functools.wraps(Test().m1)
2455 def m1d(*args, **kwargs):
2456 pass
2457 self.assertEqual(self.signature(m1d),
2458 ((('arg1', ..., ..., "positional_or_keyword"),
2459 ('arg2', 1, ..., "positional_or_keyword")),
2460 int))
2461
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002462 def test_signature_on_classmethod(self):
2463 class Test:
2464 @classmethod
2465 def foo(cls, arg1, *, arg2=1):
2466 pass
2467
2468 meth = Test().foo
2469 self.assertEqual(self.signature(meth),
2470 ((('arg1', ..., ..., "positional_or_keyword"),
2471 ('arg2', 1, ..., "keyword_only")),
2472 ...))
2473
2474 meth = Test.foo
2475 self.assertEqual(self.signature(meth),
2476 ((('arg1', ..., ..., "positional_or_keyword"),
2477 ('arg2', 1, ..., "keyword_only")),
2478 ...))
2479
2480 def test_signature_on_staticmethod(self):
2481 class Test:
2482 @staticmethod
2483 def foo(cls, *, arg):
2484 pass
2485
2486 meth = Test().foo
2487 self.assertEqual(self.signature(meth),
2488 ((('cls', ..., ..., "positional_or_keyword"),
2489 ('arg', ..., ..., "keyword_only")),
2490 ...))
2491
2492 meth = Test.foo
2493 self.assertEqual(self.signature(meth),
2494 ((('cls', ..., ..., "positional_or_keyword"),
2495 ('arg', ..., ..., "keyword_only")),
2496 ...))
2497
2498 def test_signature_on_partial(self):
2499 from functools import partial
2500
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002501 Parameter = inspect.Parameter
2502
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002503 def test():
2504 pass
2505
2506 self.assertEqual(self.signature(partial(test)), ((), ...))
2507
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002508 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002509 inspect.signature(partial(test, 1))
2510
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002511 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002512 inspect.signature(partial(test, a=1))
2513
2514 def test(a, b, *, c, d):
2515 pass
2516
2517 self.assertEqual(self.signature(partial(test)),
2518 ((('a', ..., ..., "positional_or_keyword"),
2519 ('b', ..., ..., "positional_or_keyword"),
2520 ('c', ..., ..., "keyword_only"),
2521 ('d', ..., ..., "keyword_only")),
2522 ...))
2523
2524 self.assertEqual(self.signature(partial(test, 1)),
2525 ((('b', ..., ..., "positional_or_keyword"),
2526 ('c', ..., ..., "keyword_only"),
2527 ('d', ..., ..., "keyword_only")),
2528 ...))
2529
2530 self.assertEqual(self.signature(partial(test, 1, c=2)),
2531 ((('b', ..., ..., "positional_or_keyword"),
2532 ('c', 2, ..., "keyword_only"),
2533 ('d', ..., ..., "keyword_only")),
2534 ...))
2535
2536 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2537 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002538 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002539 ('c', 2, ..., "keyword_only"),
2540 ('d', ..., ..., "keyword_only")),
2541 ...))
2542
2543 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002544 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002545 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002546 ('d', ..., ..., "keyword_only")),
2547 ...))
2548
2549 self.assertEqual(self.signature(partial(test, a=1)),
2550 ((('a', 1, ..., "keyword_only"),
2551 ('b', ..., ..., "keyword_only"),
2552 ('c', ..., ..., "keyword_only"),
2553 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002554 ...))
2555
2556 def test(a, *args, b, **kwargs):
2557 pass
2558
2559 self.assertEqual(self.signature(partial(test, 1)),
2560 ((('args', ..., ..., "var_positional"),
2561 ('b', ..., ..., "keyword_only"),
2562 ('kwargs', ..., ..., "var_keyword")),
2563 ...))
2564
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002565 self.assertEqual(self.signature(partial(test, a=1)),
2566 ((('a', 1, ..., "keyword_only"),
2567 ('b', ..., ..., "keyword_only"),
2568 ('kwargs', ..., ..., "var_keyword")),
2569 ...))
2570
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002571 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2572 ((('args', ..., ..., "var_positional"),
2573 ('b', ..., ..., "keyword_only"),
2574 ('kwargs', ..., ..., "var_keyword")),
2575 ...))
2576
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002577 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2578 ((('args', ..., ..., "var_positional"),
2579 ('b', ..., ..., "keyword_only"),
2580 ('kwargs', ..., ..., "var_keyword")),
2581 ...))
2582
2583 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2584 ((('args', ..., ..., "var_positional"),
2585 ('b', 0, ..., "keyword_only"),
2586 ('kwargs', ..., ..., "var_keyword")),
2587 ...))
2588
2589 self.assertEqual(self.signature(partial(test, b=0)),
2590 ((('a', ..., ..., "positional_or_keyword"),
2591 ('args', ..., ..., "var_positional"),
2592 ('b', 0, ..., "keyword_only"),
2593 ('kwargs', ..., ..., "var_keyword")),
2594 ...))
2595
2596 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2597 ((('a', ..., ..., "positional_or_keyword"),
2598 ('args', ..., ..., "var_positional"),
2599 ('b', 0, ..., "keyword_only"),
2600 ('kwargs', ..., ..., "var_keyword")),
2601 ...))
2602
2603 def test(a, b, c:int) -> 42:
2604 pass
2605
2606 sig = test.__signature__ = inspect.signature(test)
2607
2608 self.assertEqual(self.signature(partial(partial(test, 1))),
2609 ((('b', ..., ..., "positional_or_keyword"),
2610 ('c', ..., int, "positional_or_keyword")),
2611 42))
2612
2613 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2614 ((('c', ..., int, "positional_or_keyword"),),
2615 42))
2616
2617 psig = inspect.signature(partial(partial(test, 1), 2))
2618
2619 def foo(a):
2620 return a
2621 _foo = partial(partial(foo, a=10), a=20)
2622 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002623 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002624 ...))
2625 # check that we don't have any side-effects in signature(),
2626 # and the partial object is still functioning
2627 self.assertEqual(_foo(), 20)
2628
2629 def foo(a, b, c):
2630 return a, b, c
2631 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002632
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002633 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002634 ((('b', 30, ..., "keyword_only"),
2635 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002636 ...))
2637 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002638
2639 def foo(a, b, c, *, d):
2640 return a, b, c, d
2641 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2642 self.assertEqual(self.signature(_foo),
2643 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002644 ('b', 10, ..., "keyword_only"),
2645 ('c', 20, ..., "keyword_only"),
2646 ('d', 30, ..., "keyword_only"),
2647 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002648 ...))
2649 ba = inspect.signature(_foo).bind(a=200, b=11)
2650 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2651
2652 def foo(a=1, b=2, c=3):
2653 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002654 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2655
2656 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002657 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002658
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002659 ba = inspect.signature(_foo).bind(11, 12)
2660 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002661
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002662 ba = inspect.signature(_foo).bind(11, b=12)
2663 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002664
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002665 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002666 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2667
2668 _foo = partial(_foo, b=10, c=20)
2669 ba = inspect.signature(_foo).bind(12)
2670 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2671
2672
2673 def foo(a, b, c, d, **kwargs):
2674 pass
2675 sig = inspect.signature(foo)
2676 params = sig.parameters.copy()
2677 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2678 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2679 foo.__signature__ = inspect.Signature(params.values())
2680 sig = inspect.signature(foo)
2681 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2682
2683 self.assertEqual(self.signature(partial(foo, 1)),
2684 ((('b', ..., ..., 'positional_only'),
2685 ('c', ..., ..., 'positional_or_keyword'),
2686 ('d', ..., ..., 'positional_or_keyword'),
2687 ('kwargs', ..., ..., 'var_keyword')),
2688 ...))
2689
2690 self.assertEqual(self.signature(partial(foo, 1, 2)),
2691 ((('c', ..., ..., 'positional_or_keyword'),
2692 ('d', ..., ..., 'positional_or_keyword'),
2693 ('kwargs', ..., ..., 'var_keyword')),
2694 ...))
2695
2696 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2697 ((('d', ..., ..., 'positional_or_keyword'),
2698 ('kwargs', ..., ..., 'var_keyword')),
2699 ...))
2700
2701 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2702 ((('c', 3, ..., 'keyword_only'),
2703 ('d', ..., ..., 'keyword_only'),
2704 ('kwargs', ..., ..., 'var_keyword')),
2705 ...))
2706
2707 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2708 ((('b', ..., ..., 'positional_only'),
2709 ('c', 3, ..., 'keyword_only'),
2710 ('d', ..., ..., 'keyword_only'),
2711 ('kwargs', ..., ..., 'var_keyword')),
2712 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002713
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002714 def test_signature_on_partialmethod(self):
2715 from functools import partialmethod
2716
2717 class Spam:
2718 def test():
2719 pass
2720 ham = partialmethod(test)
2721
2722 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2723 inspect.signature(Spam.ham)
2724
2725 class Spam:
2726 def test(it, a, *, c) -> 'spam':
2727 pass
2728 ham = partialmethod(test, c=1)
2729
2730 self.assertEqual(self.signature(Spam.ham),
2731 ((('it', ..., ..., 'positional_or_keyword'),
2732 ('a', ..., ..., 'positional_or_keyword'),
2733 ('c', 1, ..., 'keyword_only')),
2734 'spam'))
2735
2736 self.assertEqual(self.signature(Spam().ham),
2737 ((('a', ..., ..., 'positional_or_keyword'),
2738 ('c', 1, ..., 'keyword_only')),
2739 'spam'))
2740
Yury Selivanov8a387212018-03-06 12:59:45 -05002741 class Spam:
2742 def test(self: 'anno', x):
2743 pass
2744
2745 g = partialmethod(test, 1)
2746
2747 self.assertEqual(self.signature(Spam.g),
2748 ((('self', ..., 'anno', 'positional_or_keyword'),),
2749 ...))
2750
Yury Selivanov0486f812014-01-29 12:18:59 -05002751 def test_signature_on_fake_partialmethod(self):
2752 def foo(a): pass
2753 foo._partialmethod = 'spam'
2754 self.assertEqual(str(inspect.signature(foo)), '(a)')
2755
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002756 def test_signature_on_decorated(self):
2757 import functools
2758
2759 def decorator(func):
2760 @functools.wraps(func)
2761 def wrapper(*args, **kwargs) -> int:
2762 return func(*args, **kwargs)
2763 return wrapper
2764
2765 class Foo:
2766 @decorator
2767 def bar(self, a, b):
2768 pass
2769
2770 self.assertEqual(self.signature(Foo.bar),
2771 ((('self', ..., ..., "positional_or_keyword"),
2772 ('a', ..., ..., "positional_or_keyword"),
2773 ('b', ..., ..., "positional_or_keyword")),
2774 ...))
2775
2776 self.assertEqual(self.signature(Foo().bar),
2777 ((('a', ..., ..., "positional_or_keyword"),
2778 ('b', ..., ..., "positional_or_keyword")),
2779 ...))
2780
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002781 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2782 ((('args', ..., ..., "var_positional"),
2783 ('kwargs', ..., ..., "var_keyword")),
2784 ...)) # functools.wraps will copy __annotations__
2785 # from "func" to "wrapper", hence no
2786 # return_annotation
2787
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002788 # Test that we handle method wrappers correctly
2789 def decorator(func):
2790 @functools.wraps(func)
2791 def wrapper(*args, **kwargs) -> int:
2792 return func(42, *args, **kwargs)
2793 sig = inspect.signature(func)
2794 new_params = tuple(sig.parameters.values())[1:]
2795 wrapper.__signature__ = sig.replace(parameters=new_params)
2796 return wrapper
2797
2798 class Foo:
2799 @decorator
2800 def __call__(self, a, b):
2801 pass
2802
2803 self.assertEqual(self.signature(Foo.__call__),
2804 ((('a', ..., ..., "positional_or_keyword"),
2805 ('b', ..., ..., "positional_or_keyword")),
2806 ...))
2807
2808 self.assertEqual(self.signature(Foo().__call__),
2809 ((('b', ..., ..., "positional_or_keyword"),),
2810 ...))
2811
Nick Coghlane8c45d62013-07-28 20:00:01 +10002812 # Test we handle __signature__ partway down the wrapper stack
2813 def wrapped_foo_call():
2814 pass
2815 wrapped_foo_call.__wrapped__ = Foo.__call__
2816
2817 self.assertEqual(self.signature(wrapped_foo_call),
2818 ((('a', ..., ..., "positional_or_keyword"),
2819 ('b', ..., ..., "positional_or_keyword")),
2820 ...))
2821
2822
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002823 def test_signature_on_class(self):
2824 class C:
2825 def __init__(self, a):
2826 pass
2827
2828 self.assertEqual(self.signature(C),
2829 ((('a', ..., ..., "positional_or_keyword"),),
2830 ...))
2831
2832 class CM(type):
2833 def __call__(cls, a):
2834 pass
2835 class C(metaclass=CM):
2836 def __init__(self, b):
2837 pass
2838
2839 self.assertEqual(self.signature(C),
2840 ((('a', ..., ..., "positional_or_keyword"),),
2841 ...))
2842
2843 class CM(type):
2844 def __new__(mcls, name, bases, dct, *, foo=1):
2845 return super().__new__(mcls, name, bases, dct)
2846 class C(metaclass=CM):
2847 def __init__(self, b):
2848 pass
2849
2850 self.assertEqual(self.signature(C),
2851 ((('b', ..., ..., "positional_or_keyword"),),
2852 ...))
2853
2854 self.assertEqual(self.signature(CM),
2855 ((('name', ..., ..., "positional_or_keyword"),
2856 ('bases', ..., ..., "positional_or_keyword"),
2857 ('dct', ..., ..., "positional_or_keyword"),
2858 ('foo', 1, ..., "keyword_only")),
2859 ...))
2860
2861 class CMM(type):
2862 def __new__(mcls, name, bases, dct, *, foo=1):
2863 return super().__new__(mcls, name, bases, dct)
2864 def __call__(cls, nm, bs, dt):
2865 return type(nm, bs, dt)
2866 class CM(type, metaclass=CMM):
2867 def __new__(mcls, name, bases, dct, *, bar=2):
2868 return super().__new__(mcls, name, bases, dct)
2869 class C(metaclass=CM):
2870 def __init__(self, b):
2871 pass
2872
2873 self.assertEqual(self.signature(CMM),
2874 ((('name', ..., ..., "positional_or_keyword"),
2875 ('bases', ..., ..., "positional_or_keyword"),
2876 ('dct', ..., ..., "positional_or_keyword"),
2877 ('foo', 1, ..., "keyword_only")),
2878 ...))
2879
2880 self.assertEqual(self.signature(CM),
2881 ((('nm', ..., ..., "positional_or_keyword"),
2882 ('bs', ..., ..., "positional_or_keyword"),
2883 ('dt', ..., ..., "positional_or_keyword")),
2884 ...))
2885
2886 self.assertEqual(self.signature(C),
2887 ((('b', ..., ..., "positional_or_keyword"),),
2888 ...))
2889
2890 class CM(type):
2891 def __init__(cls, name, bases, dct, *, bar=2):
2892 return super().__init__(name, bases, dct)
2893 class C(metaclass=CM):
2894 def __init__(self, b):
2895 pass
2896
2897 self.assertEqual(self.signature(CM),
2898 ((('name', ..., ..., "positional_or_keyword"),
2899 ('bases', ..., ..., "positional_or_keyword"),
2900 ('dct', ..., ..., "positional_or_keyword"),
2901 ('bar', 2, ..., "keyword_only")),
2902 ...))
2903
Yury Selivanov145dff82014-02-01 13:49:29 -05002904 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2905 "Signature information for builtins requires docstrings")
2906 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002907 # Test classes without user-defined __init__ or __new__
2908 class C: pass
2909 self.assertEqual(str(inspect.signature(C)), '()')
2910 class D(C): pass
2911 self.assertEqual(str(inspect.signature(D)), '()')
2912
2913 # Test meta-classes without user-defined __init__ or __new__
2914 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002915 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002916 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2917 self.assertEqual(inspect.signature(C), None)
2918 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2919 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002920
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002921 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2922 "Signature information for builtins requires docstrings")
2923 def test_signature_on_builtin_class(self):
Antoine Pitrou91f43802019-05-26 17:10:09 +02002924 expected = ('(file, protocol=None, fix_imports=True, '
2925 'buffer_callback=None)')
2926 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002927
2928 class P(_pickle.Pickler): pass
2929 class EmptyTrait: pass
2930 class P2(EmptyTrait, P): pass
Antoine Pitrou91f43802019-05-26 17:10:09 +02002931 self.assertEqual(str(inspect.signature(P)), expected)
2932 self.assertEqual(str(inspect.signature(P2)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002933
2934 class P3(P2):
2935 def __init__(self, spam):
2936 pass
2937 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2938
2939 class MetaP(type):
2940 def __call__(cls, foo, bar):
2941 pass
2942 class P4(P2, metaclass=MetaP):
2943 pass
2944 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2945
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002946 def test_signature_on_callable_objects(self):
2947 class Foo:
2948 def __call__(self, a):
2949 pass
2950
2951 self.assertEqual(self.signature(Foo()),
2952 ((('a', ..., ..., "positional_or_keyword"),),
2953 ...))
2954
2955 class Spam:
2956 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002957 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002958 inspect.signature(Spam())
2959
2960 class Bar(Spam, Foo):
2961 pass
2962
2963 self.assertEqual(self.signature(Bar()),
2964 ((('a', ..., ..., "positional_or_keyword"),),
2965 ...))
2966
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002967 class Wrapped:
2968 pass
2969 Wrapped.__wrapped__ = lambda a: None
2970 self.assertEqual(self.signature(Wrapped),
2971 ((('a', ..., ..., "positional_or_keyword"),),
2972 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002973 # wrapper loop:
2974 Wrapped.__wrapped__ = Wrapped
2975 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2976 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002977
2978 def test_signature_on_lambdas(self):
2979 self.assertEqual(self.signature((lambda a=10: a)),
2980 ((('a', 10, ..., "positional_or_keyword"),),
2981 ...))
2982
2983 def test_signature_equality(self):
2984 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002985 self.assertFalse(inspect.signature(foo) == 42)
2986 self.assertTrue(inspect.signature(foo) != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03002987 self.assertTrue(inspect.signature(foo) == ALWAYS_EQ)
2988 self.assertFalse(inspect.signature(foo) != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002989
2990 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002991 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2992 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002993 self.assertEqual(
2994 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002995
2996 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002997 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2998 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002999 self.assertNotEqual(
3000 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003001
3002 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003003 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3004 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003005 self.assertNotEqual(
3006 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003007
3008 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003009 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3010 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003011 self.assertNotEqual(
3012 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003013
3014 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003015 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3016 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003017 self.assertNotEqual(
3018 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003019
3020 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003021 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3022 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003023 self.assertNotEqual(
3024 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003025 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003026 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3027 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003028 self.assertNotEqual(
3029 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003030
3031 def foo(*, a, b, c): pass
3032 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003033 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3034 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003035 self.assertEqual(
3036 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003037
3038 def foo(*, a=1, b, c): pass
3039 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003040 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3041 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003042 self.assertEqual(
3043 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003044
3045 def foo(pos, *, a=1, b, c): pass
3046 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003047 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3048 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003049 self.assertEqual(
3050 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003051
3052 def foo(pos, *, a, b, c): pass
3053 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003054 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3055 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003056 self.assertNotEqual(
3057 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003058
3059 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3060 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003061 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3062 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003063 self.assertEqual(
3064 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003065
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003066 def test_signature_hashable(self):
3067 S = inspect.Signature
3068 P = inspect.Parameter
3069
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003070 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003071 foo_sig = inspect.signature(foo)
3072
3073 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3074
3075 self.assertEqual(hash(foo_sig), hash(manual_sig))
3076 self.assertNotEqual(hash(foo_sig),
3077 hash(manual_sig.replace(return_annotation='spam')))
3078
3079 def bar(a) -> 1: pass
3080 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3081
3082 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003083 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003084 hash(inspect.signature(foo))
3085
3086 def foo(a) -> {}: pass
3087 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3088 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003089
3090 def test_signature_str(self):
3091 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3092 pass
3093 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003094 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003095
3096 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3097 pass
3098 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003099 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003100
3101 def foo():
3102 pass
3103 self.assertEqual(str(inspect.signature(foo)), '()')
3104
3105 def test_signature_str_positional_only(self):
3106 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003107 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003108
3109 def test(a_po, *, b, **kwargs):
3110 return a_po, kwargs
3111
3112 sig = inspect.signature(test)
3113 new_params = list(sig.parameters.values())
3114 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3115 test.__signature__ = sig.replace(parameters=new_params)
3116
3117 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003118 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003119
Yury Selivanov2393dca2014-01-27 15:07:58 -05003120 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3121 '(foo, /)')
3122
3123 self.assertEqual(str(S(parameters=[
3124 P('foo', P.POSITIONAL_ONLY),
3125 P('bar', P.VAR_KEYWORD)])),
3126 '(foo, /, **bar)')
3127
3128 self.assertEqual(str(S(parameters=[
3129 P('foo', P.POSITIONAL_ONLY),
3130 P('bar', P.VAR_POSITIONAL)])),
3131 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003132
3133 def test_signature_replace_anno(self):
3134 def test() -> 42:
3135 pass
3136
3137 sig = inspect.signature(test)
3138 sig = sig.replace(return_annotation=None)
3139 self.assertIs(sig.return_annotation, None)
3140 sig = sig.replace(return_annotation=sig.empty)
3141 self.assertIs(sig.return_annotation, sig.empty)
3142 sig = sig.replace(return_annotation=42)
3143 self.assertEqual(sig.return_annotation, 42)
3144 self.assertEqual(sig, inspect.signature(test))
3145
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003146 def test_signature_on_mangled_parameters(self):
3147 class Spam:
3148 def foo(self, __p1:1=2, *, __p2:2=3):
3149 pass
3150 class Ham(Spam):
3151 pass
3152
3153 self.assertEqual(self.signature(Spam.foo),
3154 ((('self', ..., ..., "positional_or_keyword"),
3155 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3156 ('_Spam__p2', 3, 2, "keyword_only")),
3157 ...))
3158
3159 self.assertEqual(self.signature(Spam.foo),
3160 self.signature(Ham.foo))
3161
Yury Selivanovda396452014-03-27 12:09:24 -04003162 def test_signature_from_callable_python_obj(self):
3163 class MySignature(inspect.Signature): pass
3164 def foo(a, *, b:1): pass
3165 foo_sig = MySignature.from_callable(foo)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003166 self.assertIsInstance(foo_sig, MySignature)
3167
3168 def test_signature_from_callable_class(self):
3169 # A regression test for a class inheriting its signature from `object`.
3170 class MySignature(inspect.Signature): pass
3171 class foo: pass
3172 foo_sig = MySignature.from_callable(foo)
3173 self.assertIsInstance(foo_sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003174
3175 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3176 "Signature information for builtins requires docstrings")
3177 def test_signature_from_callable_builtin_obj(self):
3178 class MySignature(inspect.Signature): pass
3179 sig = MySignature.from_callable(_pickle.Pickler)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003180 self.assertIsInstance(sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003181
larryhastingsf36ba122018-01-28 11:13:09 -08003182 def test_signature_definition_order_preserved_on_kwonly(self):
3183 for fn in signatures_with_lexicographic_keyword_only_parameters():
3184 signature = inspect.signature(fn)
3185 l = list(signature.parameters)
3186 sorted_l = sorted(l)
3187 self.assertTrue(l)
3188 self.assertEqual(l, sorted_l)
3189 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3190 l = list(signature.parameters)
3191 self.assertEqual(l, unsorted_keyword_only_parameters)
3192
Jens Reidel611836a2020-03-18 03:22:46 +01003193 def test_signater_parameters_is_ordered(self):
3194 p1 = inspect.signature(lambda x, y: None).parameters
3195 p2 = inspect.signature(lambda y, x: None).parameters
3196 self.assertNotEqual(p1, p2)
3197
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003198
3199class TestParameterObject(unittest.TestCase):
3200 def test_signature_parameter_kinds(self):
3201 P = inspect.Parameter
3202 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3203 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3204
3205 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3206 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3207
3208 def test_signature_parameter_object(self):
3209 p = inspect.Parameter('foo', default=10,
3210 kind=inspect.Parameter.POSITIONAL_ONLY)
3211 self.assertEqual(p.name, 'foo')
3212 self.assertEqual(p.default, 10)
3213 self.assertIs(p.annotation, p.empty)
3214 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3215
Dong-hee Naa9cab432018-05-30 00:04:08 +09003216 with self.assertRaisesRegex(ValueError, "value '123' is "
3217 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003218 inspect.Parameter('foo', default=10, kind='123')
3219
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003220 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003221 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3222
Yury Selivanov2393dca2014-01-27 15:07:58 -05003223 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003224 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3225
Yury Selivanov2393dca2014-01-27 15:07:58 -05003226 with self.assertRaisesRegex(ValueError,
3227 'is not a valid parameter name'):
3228 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3229
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003230 with self.assertRaisesRegex(ValueError,
3231 'is not a valid parameter name'):
3232 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3233
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003234 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003235 inspect.Parameter('a', default=42,
3236 kind=inspect.Parameter.VAR_KEYWORD)
3237
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003238 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003239 inspect.Parameter('a', default=42,
3240 kind=inspect.Parameter.VAR_POSITIONAL)
3241
3242 p = inspect.Parameter('a', default=42,
3243 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003244 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003245 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3246
3247 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003248 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003249
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003250 def test_signature_parameter_hashable(self):
3251 P = inspect.Parameter
3252 foo = P('foo', kind=P.POSITIONAL_ONLY)
3253 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3254 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3255 default=42)))
3256 self.assertNotEqual(hash(foo),
3257 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3258
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003259 def test_signature_parameter_equality(self):
3260 P = inspect.Parameter
3261 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3262
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003263 self.assertTrue(p == p)
3264 self.assertFalse(p != p)
3265 self.assertFalse(p == 42)
3266 self.assertTrue(p != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003267 self.assertTrue(p == ALWAYS_EQ)
3268 self.assertFalse(p != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003269
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003270 self.assertTrue(p == P('foo', default=42,
3271 kind=inspect.Parameter.KEYWORD_ONLY))
3272 self.assertFalse(p != P('foo', default=42,
3273 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003274
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003275 def test_signature_parameter_replace(self):
3276 p = inspect.Parameter('foo', default=42,
3277 kind=inspect.Parameter.KEYWORD_ONLY)
3278
3279 self.assertIsNot(p, p.replace())
3280 self.assertEqual(p, p.replace())
3281
3282 p2 = p.replace(annotation=1)
3283 self.assertEqual(p2.annotation, 1)
3284 p2 = p2.replace(annotation=p2.empty)
3285 self.assertEqual(p, p2)
3286
3287 p2 = p2.replace(name='bar')
3288 self.assertEqual(p2.name, 'bar')
3289 self.assertNotEqual(p2, p)
3290
Yury Selivanov2393dca2014-01-27 15:07:58 -05003291 with self.assertRaisesRegex(ValueError,
3292 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003293 p2 = p2.replace(name=p2.empty)
3294
3295 p2 = p2.replace(name='foo', default=None)
3296 self.assertIs(p2.default, None)
3297 self.assertNotEqual(p2, p)
3298
3299 p2 = p2.replace(name='foo', default=p2.empty)
3300 self.assertIs(p2.default, p2.empty)
3301
3302
3303 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3304 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3305 self.assertNotEqual(p2, p)
3306
Dong-hee Naa9cab432018-05-30 00:04:08 +09003307 with self.assertRaisesRegex(ValueError,
3308 "value <class 'inspect._empty'> "
3309 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003310 p2 = p2.replace(kind=p2.empty)
3311
3312 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3313 self.assertEqual(p2, p)
3314
3315 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003316 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3317 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003318
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003319 @cpython_only
3320 def test_signature_parameter_implicit(self):
3321 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003322 'implicit arguments must be passed as '
3323 'positional or keyword arguments, '
3324 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003325 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3326
3327 param = inspect.Parameter(
3328 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3329 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3330 self.assertEqual(param.name, 'implicit0')
3331
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003332 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003333 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003334
3335 with self.assertRaises(AttributeError):
3336 p.foo = 'bar'
3337
3338 with self.assertRaises(AttributeError):
3339 p.kind = 123
3340
3341
3342class TestSignatureBind(unittest.TestCase):
3343 @staticmethod
3344 def call(func, *args, **kwargs):
3345 sig = inspect.signature(func)
3346 ba = sig.bind(*args, **kwargs)
3347 return func(*ba.args, **ba.kwargs)
3348
3349 def test_signature_bind_empty(self):
3350 def test():
3351 return 42
3352
3353 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003354 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003355 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003356 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003357 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003358 with self.assertRaisesRegex(
3359 TypeError, "got an unexpected keyword argument 'spam'"):
3360
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003361 self.call(test, spam=1)
3362
3363 def test_signature_bind_var(self):
3364 def test(*args, **kwargs):
3365 return args, kwargs
3366
3367 self.assertEqual(self.call(test), ((), {}))
3368 self.assertEqual(self.call(test, 1), ((1,), {}))
3369 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3370 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3371 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3372 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3373 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3374 ((1, 2), {'foo': 'bar'}))
3375
3376 def test_signature_bind_just_args(self):
3377 def test(a, b, c):
3378 return a, b, c
3379
3380 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3381
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003382 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003383 self.call(test, 1, 2, 3, 4)
3384
Yury Selivanov86872752015-05-19 00:27:49 -04003385 with self.assertRaisesRegex(TypeError,
3386 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003387 self.call(test, 1)
3388
Yury Selivanov86872752015-05-19 00:27:49 -04003389 with self.assertRaisesRegex(TypeError,
3390 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003391 self.call(test)
3392
3393 def test(a, b, c=10):
3394 return a, b, c
3395 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3396 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3397
3398 def test(a=1, b=2, c=3):
3399 return a, b, c
3400 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3401 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3402 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3403
3404 def test_signature_bind_varargs_order(self):
3405 def test(*args):
3406 return args
3407
3408 self.assertEqual(self.call(test), ())
3409 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3410
3411 def test_signature_bind_args_and_varargs(self):
3412 def test(a, b, c=3, *args):
3413 return a, b, c, args
3414
3415 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3416 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3417 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3418 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3419
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003420 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003421 "multiple values for argument 'c'"):
3422 self.call(test, 1, 2, 3, c=4)
3423
3424 def test_signature_bind_just_kwargs(self):
3425 def test(**kwargs):
3426 return kwargs
3427
3428 self.assertEqual(self.call(test), {})
3429 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3430 {'foo': 'bar', 'spam': 'ham'})
3431
3432 def test_signature_bind_args_and_kwargs(self):
3433 def test(a, b, c=3, **kwargs):
3434 return a, b, c, kwargs
3435
3436 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3437 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3438 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3439 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3440 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3441 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3442 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3443 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3444 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3445 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3446 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3447 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3448 (1, 2, 4, {'foo': 'bar'}))
3449 self.assertEqual(self.call(test, c=5, a=4, b=3),
3450 (4, 3, 5, {}))
3451
3452 def test_signature_bind_kwonly(self):
3453 def test(*, foo):
3454 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003455 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003456 'too many positional arguments'):
3457 self.call(test, 1)
3458 self.assertEqual(self.call(test, foo=1), 1)
3459
3460 def test(a, *, foo=1, bar):
3461 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003462 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003463 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003464 self.call(test, 1)
3465
3466 def test(foo, *, bar):
3467 return foo, bar
3468 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3469 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3470
Yury Selivanov86872752015-05-19 00:27:49 -04003471 with self.assertRaisesRegex(
3472 TypeError, "got an unexpected keyword argument 'spam'"):
3473
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003474 self.call(test, bar=2, foo=1, spam=10)
3475
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003476 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003477 'too many positional arguments'):
3478 self.call(test, 1, 2)
3479
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003480 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003481 'too many positional arguments'):
3482 self.call(test, 1, 2, bar=2)
3483
Yury Selivanov86872752015-05-19 00:27:49 -04003484 with self.assertRaisesRegex(
3485 TypeError, "got an unexpected keyword argument 'spam'"):
3486
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003487 self.call(test, 1, bar=2, spam='ham')
3488
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003489 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003490 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003491 self.call(test, 1)
3492
3493 def test(foo, *, bar, **bin):
3494 return foo, bar, bin
3495 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3496 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3497 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3498 (1, 2, {'spam': 'ham'}))
3499 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3500 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003501 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003502 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003503 self.call(test, spam='ham', bar=2)
3504 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3505 (1, 2, {'bin': 1, 'spam': 10}))
3506
3507 def test_signature_bind_arguments(self):
3508 def test(a, *args, b, z=100, **kwargs):
3509 pass
3510 sig = inspect.signature(test)
3511 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3512 # we won't have 'z' argument in the bound arguments object, as we didn't
3513 # pass it to the 'bind'
3514 self.assertEqual(tuple(ba.arguments.items()),
3515 (('a', 10), ('args', (20,)), ('b', 30),
3516 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3517 self.assertEqual(ba.kwargs,
3518 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3519 self.assertEqual(ba.args, (10, 20))
3520
3521 def test_signature_bind_positional_only(self):
3522 P = inspect.Parameter
3523
3524 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3525 return a_po, b_po, c_po, foo, bar, kwargs
3526
3527 sig = inspect.signature(test)
3528 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3529 for name in ('a_po', 'b_po', 'c_po'):
3530 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3531 new_sig = sig.replace(parameters=new_params.values())
3532 test.__signature__ = new_sig
3533
3534 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3535 (1, 2, 4, 5, 6, {}))
3536
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003537 self.assertEqual(self.call(test, 1, 2),
3538 (1, 2, 3, 42, 50, {}))
3539
3540 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3541 (1, 2, 3, 4, 5, {}))
3542
3543 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3544 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3545
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003546 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003547 self.call(test, 1, 2, c_po=4)
3548
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003549 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003550 self.call(test, a_po=1, b_po=2)
3551
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003552 def test_signature_bind_with_self_arg(self):
3553 # Issue #17071: one of the parameters is named "self
3554 def test(a, self, b):
3555 pass
3556 sig = inspect.signature(test)
3557 ba = sig.bind(1, 2, 3)
3558 self.assertEqual(ba.args, (1, 2, 3))
3559 ba = sig.bind(1, self=2, b=3)
3560 self.assertEqual(ba.args, (1, 2, 3))
3561
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003562 def test_signature_bind_vararg_name(self):
3563 def test(a, *args):
3564 return a, args
3565 sig = inspect.signature(test)
3566
Yury Selivanov86872752015-05-19 00:27:49 -04003567 with self.assertRaisesRegex(
3568 TypeError, "got an unexpected keyword argument 'args'"):
3569
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003570 sig.bind(a=0, args=1)
3571
3572 def test(*args, **kwargs):
3573 return args, kwargs
3574 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3575
3576 sig = inspect.signature(test)
3577 ba = sig.bind(args=1)
3578 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3579
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003580 @cpython_only
3581 def test_signature_bind_implicit_arg(self):
3582 # Issue #19611: getcallargs should work with set comprehensions
3583 def make_set():
3584 return {z * z for z in range(5)}
3585 setcomp_code = make_set.__code__.co_consts[1]
3586 setcomp_func = types.FunctionType(setcomp_code, {})
3587
3588 iterator = iter(range(5))
3589 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3590
Pablo Galindof3ef06a2019-10-15 12:40:02 +01003591 def test_signature_bind_posonly_kwargs(self):
3592 def foo(bar, /, **kwargs):
3593 return bar, kwargs.get(bar)
3594
3595 sig = inspect.signature(foo)
3596 result = sig.bind("pos-only", bar="keyword")
3597
3598 self.assertEqual(result.kwargs, {"bar": "keyword"})
3599 self.assertIn(("bar", "pos-only"), result.arguments.items())
3600
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003601
3602class TestBoundArguments(unittest.TestCase):
3603 def test_signature_bound_arguments_unhashable(self):
3604 def foo(a): pass
3605 ba = inspect.signature(foo).bind(1)
3606
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003607 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003608 hash(ba)
3609
3610 def test_signature_bound_arguments_equality(self):
3611 def foo(a): pass
3612 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003613 self.assertTrue(ba == ba)
3614 self.assertFalse(ba != ba)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003615 self.assertTrue(ba == ALWAYS_EQ)
3616 self.assertFalse(ba != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003617
3618 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003619 self.assertTrue(ba == ba2)
3620 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003621
3622 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003623 self.assertFalse(ba == ba3)
3624 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003625 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003626 self.assertTrue(ba == ba3)
3627 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003628
3629 def bar(b): pass
3630 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003631 self.assertFalse(ba == ba4)
3632 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003633
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003634 def foo(*, a, b): pass
3635 sig = inspect.signature(foo)
3636 ba1 = sig.bind(a=1, b=2)
3637 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003638 self.assertTrue(ba1 == ba2)
3639 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003640
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003641 def test_signature_bound_arguments_pickle(self):
3642 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3643 sig = inspect.signature(foo)
3644 ba = sig.bind(20, 30, z={})
3645
3646 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3647 with self.subTest(pickle_ver=ver):
3648 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3649 self.assertEqual(ba, ba_pickled)
3650
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003651 def test_signature_bound_arguments_repr(self):
3652 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3653 sig = inspect.signature(foo)
3654 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003655 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003656
Yury Selivanovb907a512015-05-16 13:45:09 -04003657 def test_signature_bound_arguments_apply_defaults(self):
3658 def foo(a, b=1, *args, c:1={}, **kw): pass
3659 sig = inspect.signature(foo)
3660
3661 ba = sig.bind(20)
3662 ba.apply_defaults()
3663 self.assertEqual(
3664 list(ba.arguments.items()),
3665 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3666
3667 # Make sure that we preserve the order:
3668 # i.e. 'c' should be *before* 'kw'.
3669 ba = sig.bind(10, 20, 30, d=1)
3670 ba.apply_defaults()
3671 self.assertEqual(
3672 list(ba.arguments.items()),
3673 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3674
3675 # Make sure that BoundArguments produced by bind_partial()
3676 # are supported.
3677 def foo(a, b): pass
3678 sig = inspect.signature(foo)
3679 ba = sig.bind_partial(20)
3680 ba.apply_defaults()
3681 self.assertEqual(
3682 list(ba.arguments.items()),
3683 [('a', 20)])
3684
3685 # Test no args
3686 def foo(): pass
3687 sig = inspect.signature(foo)
3688 ba = sig.bind()
3689 ba.apply_defaults()
3690 self.assertEqual(list(ba.arguments.items()), [])
3691
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003692 # Make sure a no-args binding still acquires proper defaults.
3693 def foo(a='spam'): pass
3694 sig = inspect.signature(foo)
3695 ba = sig.bind()
3696 ba.apply_defaults()
3697 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3698
Rémi Lapeyre2cca8ef2020-01-28 13:47:03 +01003699 def test_signature_bound_arguments_arguments_type(self):
3700 def foo(a): pass
3701 ba = inspect.signature(foo).bind(1)
3702 self.assertIs(type(ba.arguments), dict)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003703
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003704class TestSignaturePrivateHelpers(unittest.TestCase):
3705 def test_signature_get_bound_param(self):
3706 getter = inspect._signature_get_bound_param
3707
3708 self.assertEqual(getter('($self)'), 'self')
3709 self.assertEqual(getter('($self, obj)'), 'self')
3710 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3711
Larry Hastings2623c8c2014-02-08 22:15:29 -08003712 def _strip_non_python_syntax(self, input,
3713 clean_signature, self_parameter, last_positional_only):
3714 computed_clean_signature, \
3715 computed_self_parameter, \
3716 computed_last_positional_only = \
3717 inspect._signature_strip_non_python_syntax(input)
3718 self.assertEqual(computed_clean_signature, clean_signature)
3719 self.assertEqual(computed_self_parameter, self_parameter)
3720 self.assertEqual(computed_last_positional_only, last_positional_only)
3721
3722 def test_signature_strip_non_python_syntax(self):
3723 self._strip_non_python_syntax(
3724 "($module, /, path, mode, *, dir_fd=None, " +
3725 "effective_ids=False,\n follow_symlinks=True)",
3726 "(module, path, mode, *, dir_fd=None, " +
3727 "effective_ids=False, follow_symlinks=True)",
3728 0,
3729 0)
3730
3731 self._strip_non_python_syntax(
3732 "($module, word, salt, /)",
3733 "(module, word, salt)",
3734 0,
3735 2)
3736
3737 self._strip_non_python_syntax(
3738 "(x, y=None, z=None, /)",
3739 "(x, y=None, z=None)",
3740 None,
3741 2)
3742
3743 self._strip_non_python_syntax(
3744 "(x, y=None, z=None)",
3745 "(x, y=None, z=None)",
3746 None,
3747 None)
3748
3749 self._strip_non_python_syntax(
3750 "(x,\n y=None,\n z = None )",
3751 "(x, y=None, z=None)",
3752 None,
3753 None)
3754
3755 self._strip_non_python_syntax(
3756 "",
3757 "",
3758 None,
3759 None)
3760
3761 self._strip_non_python_syntax(
3762 None,
3763 None,
3764 None,
3765 None)
3766
Nick Coghlan9c680b02015-04-13 12:54:54 -04003767class TestSignatureDefinitions(unittest.TestCase):
3768 # This test case provides a home for checking that particular APIs
3769 # have signatures available for introspection
3770
3771 @cpython_only
3772 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3773 "Signature information for builtins requires docstrings")
3774 def test_builtins_have_signatures(self):
3775 # This checks all builtin callables in CPython have signatures
3776 # A few have signatures Signature can't yet handle, so we skip those
3777 # since they will have to wait until PEP 457 adds the required
3778 # introspection support to the inspect module
3779 # Some others also haven't been converted yet for various other
3780 # reasons, so we also skip those for the time being, but design
3781 # the test to fail in order to indicate when it needs to be
3782 # updated.
3783 no_signature = set()
3784 # These need PEP 457 groups
3785 needs_groups = {"range", "slice", "dir", "getattr",
3786 "next", "iter", "vars"}
3787 no_signature |= needs_groups
3788 # These need PEP 457 groups or a signature change to accept None
3789 needs_semantic_update = {"round"}
3790 no_signature |= needs_semantic_update
3791 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003792 needs_varargs = {"breakpoint", "min", "max", "print",
3793 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003794 no_signature |= needs_varargs
3795 # These simply weren't covered in the initial AC conversion
3796 # for builtin callables
3797 not_converted_yet = {"open", "__import__"}
3798 no_signature |= not_converted_yet
3799 # These builtin types are expected to provide introspection info
3800 types_with_signatures = set()
3801 # Check the signatures we expect to be there
3802 ns = vars(builtins)
3803 for name, obj in sorted(ns.items()):
3804 if not callable(obj):
3805 continue
3806 # The builtin types haven't been converted to AC yet
3807 if isinstance(obj, type) and (name not in types_with_signatures):
3808 # Note that this also skips all the exception types
3809 no_signature.add(name)
3810 if (name in no_signature):
3811 # Not yet converted
3812 continue
3813 with self.subTest(builtin=name):
3814 self.assertIsNotNone(inspect.signature(obj))
3815 # Check callables that haven't been converted don't claim a signature
3816 # This ensures this test will start failing as more signatures are
3817 # added, so the affected items can be moved into the scope of the
3818 # regression test above
3819 for name in no_signature:
3820 with self.subTest(builtin=name):
3821 self.assertIsNone(obj.__text_signature__)
3822
Serhiy Storchakad53cf992019-05-06 22:40:27 +03003823 def test_python_function_override_signature(self):
3824 def func(*args, **kwargs):
3825 pass
3826 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
3827 sig = inspect.signature(func)
3828 self.assertIsNotNone(sig)
3829 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
3830 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
3831 sig = inspect.signature(func)
3832 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
3833
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003834
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003835class NTimesUnwrappable:
3836 def __init__(self, n):
3837 self.n = n
3838 self._next = None
3839
3840 @property
3841 def __wrapped__(self):
3842 if self.n <= 0:
3843 raise Exception("Unwrapped too many times")
3844 if self._next is None:
3845 self._next = NTimesUnwrappable(self.n - 1)
3846 return self._next
3847
Nick Coghlane8c45d62013-07-28 20:00:01 +10003848class TestUnwrap(unittest.TestCase):
3849
3850 def test_unwrap_one(self):
3851 def func(a, b):
3852 return a + b
3853 wrapper = functools.lru_cache(maxsize=20)(func)
3854 self.assertIs(inspect.unwrap(wrapper), func)
3855
3856 def test_unwrap_several(self):
3857 def func(a, b):
3858 return a + b
3859 wrapper = func
3860 for __ in range(10):
3861 @functools.wraps(wrapper)
3862 def wrapper():
3863 pass
3864 self.assertIsNot(wrapper.__wrapped__, func)
3865 self.assertIs(inspect.unwrap(wrapper), func)
3866
3867 def test_stop(self):
3868 def func1(a, b):
3869 return a + b
3870 @functools.wraps(func1)
3871 def func2():
3872 pass
3873 @functools.wraps(func2)
3874 def wrapper():
3875 pass
3876 func2.stop_here = 1
3877 unwrapped = inspect.unwrap(wrapper,
3878 stop=(lambda f: hasattr(f, "stop_here")))
3879 self.assertIs(unwrapped, func2)
3880
3881 def test_cycle(self):
3882 def func1(): pass
3883 func1.__wrapped__ = func1
3884 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3885 inspect.unwrap(func1)
3886
3887 def func2(): pass
3888 func2.__wrapped__ = func1
3889 func1.__wrapped__ = func2
3890 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3891 inspect.unwrap(func1)
3892 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3893 inspect.unwrap(func2)
3894
3895 def test_unhashable(self):
3896 def func(): pass
3897 func.__wrapped__ = None
3898 class C:
3899 __hash__ = None
3900 __wrapped__ = func
3901 self.assertIsNone(inspect.unwrap(C()))
3902
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003903 def test_recursion_limit(self):
3904 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3905 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3906 inspect.unwrap(obj)
3907
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003908class TestMain(unittest.TestCase):
3909 def test_only_source(self):
3910 module = importlib.import_module('unittest')
3911 rc, out, err = assert_python_ok('-m', 'inspect',
3912 'unittest')
3913 lines = out.decode().splitlines()
3914 # ignore the final newline
3915 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3916 self.assertEqual(err, b'')
3917
Yury Selivanov42407ab2014-06-23 10:23:50 -07003918 def test_custom_getattr(self):
3919 def foo():
3920 pass
3921 foo.__signature__ = 42
3922 with self.assertRaises(TypeError):
3923 inspect.signature(foo)
3924
Brett Cannon634a8fc2013-10-02 10:25:42 -04003925 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003926 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003927 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003928 rc, out, err = assert_python_ok('-m', 'inspect',
3929 'concurrent.futures:ThreadPoolExecutor')
3930 lines = out.decode().splitlines()
3931 # ignore the final newline
3932 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003933 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003934 self.assertEqual(err, b'')
3935
3936 def test_builtins(self):
3937 module = importlib.import_module('unittest')
3938 _, out, err = assert_python_failure('-m', 'inspect',
3939 'sys')
3940 lines = err.decode().splitlines()
3941 self.assertEqual(lines, ["Can't get info for builtin modules."])
3942
3943 def test_details(self):
3944 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003945 args = support.optim_args_from_interpreter_flags()
3946 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003947 'unittest', '--details')
3948 output = out.decode()
3949 # Just a quick sanity check on the output
3950 self.assertIn(module.__name__, output)
3951 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003952 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003953 self.assertEqual(err, b'')
3954
3955
Yury Selivanovef1e7502014-12-08 16:05:34 -05003956class TestReload(unittest.TestCase):
3957
3958 src_before = textwrap.dedent("""\
3959def foo():
3960 print("Bla")
3961 """)
3962
3963 src_after = textwrap.dedent("""\
3964def foo():
3965 print("Oh no!")
3966 """)
3967
3968 def assertInspectEqual(self, path, source):
3969 inspected_src = inspect.getsource(source)
3970 with open(path) as src:
3971 self.assertEqual(
3972 src.read().splitlines(True),
3973 inspected_src.splitlines(True)
3974 )
3975
3976 def test_getsource_reload(self):
3977 # see issue 1218234
3978 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3979 module = importlib.import_module(name)
3980 self.assertInspectEqual(path, module)
3981 with open(path, 'w') as src:
3982 src.write(self.src_after)
3983 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003984
Nick Coghlane8c45d62013-07-28 20:00:01 +10003985
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003986def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003987 run_unittest(
3988 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3989 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3990 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003991 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003992 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003993 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04003994 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003995 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07003996 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00003997 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003998
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003999if __name__ == "__main__":
4000 test_main()