blob: 7148dfa0bab94f8ae667d72e546c68b518f4d20d [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):
442 self.assertEqual(inspect.getdoc(mod.FesteringGob),
443 'A longer,\n\nindented\n\ndocstring.')
444 self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse),
445 'Another\n\ndocstring\n\ncontaining\n\ntabs')
446 self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse),
447 'Another\n\ndocstring\n\ncontaining\n\ntabs')
448 self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction),
449 'The automatic gainsaying.')
450
451 @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings")
452 def test_finddoc(self):
453 finddoc = inspect._finddoc
454 self.assertEqual(finddoc(int), int.__doc__)
455 self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__)
456 self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__)
457 self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__)
458 self.assertEqual(finddoc(int.real), int.real.__doc__)
459
Georg Brandl0c77a822008-06-10 16:37:50 +0000460 def test_cleandoc(self):
461 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
462 'An\nindented\ndocstring.')
463
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000464 def test_getcomments(self):
465 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
466 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Marco Buttu3f2155f2017-03-17 09:50:23 +0100467 # If the object source file is not available, return None.
468 co = compile('x=1', '_non_existing_filename.py', 'exec')
469 self.assertIsNone(inspect.getcomments(co))
470 # If the object has been defined in C, return None.
471 self.assertIsNone(inspect.getcomments(list))
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000472
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000473 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000474 # Check actual module
475 self.assertEqual(inspect.getmodule(mod), mod)
476 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000477 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000478 # Check a method (no __module__ attribute, falls back to filename)
479 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
480 # Do it again (check the caching isn't broken)
481 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
482 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000483 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000484 # Check filename override
485 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000486
Berker Peksagff0e3b72017-01-02 06:57:43 +0300487 def test_getframeinfo_get_first_line(self):
488 frame_info = inspect.getframeinfo(self.fodderModule.fr, 50)
489 self.assertEqual(frame_info.code_context[0], "# line 1\n")
490 self.assertEqual(frame_info.code_context[1], "'A module docstring.'\n")
491
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000492 def test_getsource(self):
493 self.assertSourceEqual(git.abuse, 29, 39)
Serhiy Storchakaac4bdcc2015-10-29 08:15:50 +0200494 self.assertSourceEqual(mod.StupidGit, 21, 51)
495 self.assertSourceEqual(mod.lobbest, 75, 76)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000496
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000497 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000498 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
499 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000500 fn = "_non_existing_filename_used_for_sourcefile_test.py"
Victor Stinner51d8c522016-02-08 17:57:02 +0100501 co = compile("x=1", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000502 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000503 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200504 try:
505 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
506 finally:
507 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000508
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000509 def test_getfile(self):
510 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000511
Philipp Ad407d2a2019-06-08 14:05:46 +0200512 def test_getfile_builtin_module(self):
513 with self.assertRaises(TypeError) as e:
514 inspect.getfile(sys)
515 self.assertTrue(str(e.exception).startswith('<module'))
516
517 def test_getfile_builtin_class(self):
518 with self.assertRaises(TypeError) as e:
519 inspect.getfile(int)
520 self.assertTrue(str(e.exception).startswith('<class'))
521
522 def test_getfile_builtin_function_or_method(self):
523 with self.assertRaises(TypeError) as e_abs:
524 inspect.getfile(abs)
525 self.assertIn('expected, got', str(e_abs.exception))
526 with self.assertRaises(TypeError) as e_append:
527 inspect.getfile(list.append)
528 self.assertIn('expected, got', str(e_append.exception))
529
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500530 def test_getfile_class_without_module(self):
531 class CM(type):
532 @property
533 def __module__(cls):
534 raise AttributeError
535 class C(metaclass=CM):
536 pass
537 with self.assertRaises(TypeError):
538 inspect.getfile(C)
539
Thomas Kluyvere968bc732017-10-24 13:42:36 +0100540 def test_getfile_broken_repr(self):
541 class ErrorRepr:
542 def __repr__(self):
543 raise Exception('xyz')
544 er = ErrorRepr()
545 with self.assertRaises(TypeError):
546 inspect.getfile(er)
547
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000548 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000549 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000550 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000551 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000552 m.__file__ = "<string>" # hopefully not a real filename...
553 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000554 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000555 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000556 del sys.modules[name]
557 inspect.getmodule(compile('a=10','','single'))
558
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500559 def test_proceed_with_fake_filename(self):
560 '''doctest monkeypatches linecache to enable inspection'''
561 fn, source = '<test>', 'def x(): pass\n'
562 getlines = linecache.getlines
563 def monkey(filename, module_globals=None):
564 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300565 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500566 else:
567 return getlines(filename, module_globals)
568 linecache.getlines = monkey
569 try:
570 ns = {}
571 exec(compile(source, fn, 'single'), ns)
572 inspect.getsource(ns["x"])
573 finally:
574 linecache.getlines = getlines
575
Antoine Pitroua8723a02015-04-15 00:41:29 +0200576 def test_getsource_on_code_object(self):
577 self.assertSourceEqual(mod.eggs.__code__, 12, 18)
578
Vladimir Matveev91cb2982018-08-24 07:18:00 -0700579class TestGettingSourceOfToplevelFrames(GetSourceBase):
580 fodderModule = mod
581
582 def test_range_toplevel_frame(self):
583 self.maxDiff = None
584 self.assertSourceEqual(mod.currentframe, 1, None)
585
586 def test_range_traceback_toplevel_frame(self):
587 self.assertSourceEqual(mod.tb, 1, None)
588
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000589class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000590 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000591
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000592 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000593 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000594
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000595 def test_replacing_decorator(self):
596 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000597
Yury Selivanov081bbf62014-09-26 17:34:54 -0400598 def test_getsource_unwrap(self):
Antoine Pitroua8723a02015-04-15 00:41:29 +0200599 self.assertSourceEqual(mod2.real, 130, 132)
600
601 def test_decorator_with_lambda(self):
602 self.assertSourceEqual(mod2.func114, 113, 115)
Yury Selivanov081bbf62014-09-26 17:34:54 -0400603
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000604class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000605 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000606 def test_oneline_lambda(self):
607 # Test inspect.getsource with a one-line lambda function.
608 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000609
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000610 def test_threeline_lambda(self):
611 # Test inspect.getsource with a three-line lambda function,
612 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000613 self.assertSourceEqual(mod2.tll, 28, 30)
614
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000615 def test_twoline_indented_lambda(self):
616 # Test inspect.getsource with a two-line lambda function,
617 # where the second line _is_ indented.
618 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000619
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000620 def test_onelinefunc(self):
621 # Test inspect.getsource with a regular one-line function.
622 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000623
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000624 def test_manyargs(self):
625 # Test inspect.getsource with a regular function where
626 # the arguments are on two lines and _not_ indented and
627 # the body on the second line with the last arguments.
628 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000629
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000630 def test_twolinefunc(self):
631 # Test inspect.getsource with a regular function where
632 # the body is on two lines, following the argument list and
633 # continued on the next line by a \\.
634 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000635
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000636 def test_lambda_in_list(self):
637 # Test inspect.getsource with a one-line lambda function
638 # defined in a list, indented.
639 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000640
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000641 def test_anonymous(self):
642 # Test inspect.getsource with a lambda function defined
643 # as argument to another function.
644 self.assertSourceEqual(mod2.anonymous, 55, 55)
645
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000646class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000647 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000648
649 def test_with_comment(self):
650 self.assertSourceEqual(mod2.with_comment, 58, 59)
651
652 def test_multiline_sig(self):
653 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
654
Armin Rigodd5c0232005-09-25 11:45:45 +0000655 def test_nested_class(self):
656 self.assertSourceEqual(mod2.func69().func71, 71, 72)
657
658 def test_one_liner_followed_by_non_name(self):
659 self.assertSourceEqual(mod2.func77, 77, 77)
660
661 def test_one_liner_dedent_non_name(self):
662 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
663
664 def test_with_comment_instead_of_docstring(self):
665 self.assertSourceEqual(mod2.func88, 88, 90)
666
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000667 def test_method_in_dynamic_class(self):
668 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
669
R David Murray32562d72014-10-03 11:15:38 -0400670 # This should not skip for CPython, but might on a repackaged python where
671 # unicodedata is not an external module, or on pypy.
672 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
673 unicodedata.__file__.endswith('.py'),
674 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000675 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200676 self.assertRaises(OSError, inspect.getsource, unicodedata)
677 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000678
R. David Murraya1b37402010-06-17 02:04:29 +0000679 def test_findsource_code_in_linecache(self):
680 lines = ["x=1"]
681 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200682 self.assertRaises(OSError, inspect.findsource, co)
683 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000684 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200685 try:
686 self.assertEqual(inspect.findsource(co), (lines,0))
687 self.assertEqual(inspect.getsource(co), lines[0])
688 finally:
689 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000690
Ezio Melotti1b145922013-03-30 05:17:24 +0200691 def test_findsource_without_filename(self):
692 for fname in ['', '<string>']:
693 co = compile('x=1', fname, "exec")
694 self.assertRaises(IOError, inspect.findsource, co)
695 self.assertRaises(IOError, inspect.getsource, co)
696
Antoine Pitroua8723a02015-04-15 00:41:29 +0200697 def test_getsource_on_method(self):
698 self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
699
Yury Selivanov4f4913b2015-07-23 17:10:00 +0300700 def test_nested_func(self):
701 self.assertSourceEqual(mod2.cls135.func136, 136, 139)
702
703
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000704class TestNoEOL(GetSourceBase):
Yury Selivanov6738b112015-05-16 10:10:21 -0400705 def setUp(self):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000706 self.tempdir = TESTFN + '_dir'
707 os.mkdir(self.tempdir)
708 with open(os.path.join(self.tempdir,
709 'inspect_fodder3%spy' % os.extsep), 'w') as f:
710 f.write("class X:\n pass # No EOL")
711 with DirsOnSysPath(self.tempdir):
712 import inspect_fodder3 as mod3
713 self.fodderModule = mod3
Yury Selivanov6738b112015-05-16 10:10:21 -0400714 super().setUp()
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000715
716 def tearDown(self):
717 shutil.rmtree(self.tempdir)
718
719 def test_class(self):
720 self.assertSourceEqual(self.fodderModule.X, 1, 2)
721
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100722
723class _BrokenDataDescriptor(object):
724 """
725 A broken data descriptor. See bug #1785.
726 """
727 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700728 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100729
730 def __set__(*args):
731 raise RuntimeError
732
733 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700734 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100735
736
737class _BrokenMethodDescriptor(object):
738 """
739 A broken method descriptor. See bug #1785.
740 """
741 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700742 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100743
744 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700745 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100746
747
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000748# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000749def attrs_wo_objs(cls):
750 return [t[:3] for t in inspect.classify_class_attrs(cls)]
751
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100752
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000753class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000754 def test_newstyle_mro(self):
755 # The same w/ new-class MRO.
756 class A(object): pass
757 class B(A): pass
758 class C(A): pass
759 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000760
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000761 expected = (D, B, C, A, object)
762 got = inspect.getmro(D)
763 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000764
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500765 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
766 varkw_e=None, defaults_e=None, formatted=None):
Xtreak6d0b7472019-05-30 17:31:39 +0530767 with self.assertWarns(DeprecationWarning):
768 args, varargs, varkw, defaults = inspect.getargspec(routine)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500769 self.assertEqual(args, args_e)
770 self.assertEqual(varargs, varargs_e)
771 self.assertEqual(varkw, varkw_e)
772 self.assertEqual(defaults, defaults_e)
773 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530774 with self.assertWarns(DeprecationWarning):
775 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
776 formatted)
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500777
Christian Heimes3795b532007-11-08 13:48:53 +0000778 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
779 varkw_e=None, defaults_e=None,
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100780 posonlyargs_e=[], kwonlyargs_e=[],
781 kwonlydefaults_e=None,
Christian Heimes3795b532007-11-08 13:48:53 +0000782 ann_e={}, formatted=None):
Pablo Galindoaee19f52019-05-16 21:08:15 +0100783 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
784 inspect.getfullargspec(routine)
Christian Heimes3795b532007-11-08 13:48:53 +0000785 self.assertEqual(args, args_e)
786 self.assertEqual(varargs, varargs_e)
787 self.assertEqual(varkw, varkw_e)
788 self.assertEqual(defaults, defaults_e)
789 self.assertEqual(kwonlyargs, kwonlyargs_e)
790 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
791 self.assertEqual(ann, ann_e)
792 if formatted is not None:
Xtreak6d0b7472019-05-30 17:31:39 +0530793 with self.assertWarns(DeprecationWarning):
794 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
795 kwonlyargs, kwonlydefaults, ann),
796 formatted)
Christian Heimes3795b532007-11-08 13:48:53 +0000797
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500798 def test_getargspec(self):
799 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
800
Pablo Galindod5d2b452019-04-30 02:01:14 +0100801 self.assertArgSpecEquals(mod.spam,
802 ['a', 'b', 'c', 'd', 'e', 'f'],
803 'g', 'h', (3, 4, 5),
804 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500805
806 self.assertRaises(ValueError, self.assertArgSpecEquals,
807 mod2.keyworded, [])
808
809 self.assertRaises(ValueError, self.assertArgSpecEquals,
810 mod2.annotated, [])
811 self.assertRaises(ValueError, self.assertArgSpecEquals,
812 mod2.keyword_only_arg, [])
813
814
Christian Heimes3795b532007-11-08 13:48:53 +0000815 def test_getfullargspec(self):
816 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
817 kwonlyargs_e=['arg2'],
818 kwonlydefaults_e={'arg2':1},
819 formatted='(*arg1, arg2=1)')
820
821 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000822 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000823 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000824 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
825 kwonlyargs_e=['arg'],
826 formatted='(*, arg)')
827
Pablo Galindod5d2b452019-04-30 02:01:14 +0100828 self.assertFullArgSpecEquals(mod2.all_markers, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100829 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100830 formatted='(a, b, c, d, *, e, f)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100831
832 self.assertFullArgSpecEquals(mod2.all_markers_with_args_and_kwargs,
Pablo Galindod5d2b452019-04-30 02:01:14 +0100833 ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100834 varargs_e='args',
835 varkw_e='kwargs',
836 kwonlyargs_e=['e', 'f'],
Pablo Galindod5d2b452019-04-30 02:01:14 +0100837 formatted='(a, b, c, d, *args, e, f, **kwargs)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100838
Pablo Galindod5d2b452019-04-30 02:01:14 +0100839 self.assertFullArgSpecEquals(mod2.all_markers_with_defaults, ['a', 'b', 'c', 'd'],
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100840 defaults_e=(1,2,3),
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100841 kwonlyargs_e=['e', 'f'],
842 kwonlydefaults_e={'e': 4, 'f': 5},
Pablo Galindod5d2b452019-04-30 02:01:14 +0100843 formatted='(a, b=1, c=2, d=3, *, e=4, f=5)')
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100844
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500845 def test_argspec_api_ignores_wrapped(self):
Yury Selivanov57d240e2014-02-19 16:27:23 -0500846 # Issue 20684: low level introspection API must ignore __wrapped__
847 @functools.wraps(mod.spam)
848 def ham(x, y):
849 pass
850 # Basic check
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500851 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500852 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
853 self.assertFullArgSpecEquals(functools.partial(ham),
854 ['x', 'y'], formatted='(x, y)')
855 # Other variants
856 def check_method(f):
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500857 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
858 formatted='(self, x, y)')
Yury Selivanov57d240e2014-02-19 16:27:23 -0500859 class C:
860 @functools.wraps(mod.spam)
861 def ham(self, x, y):
862 pass
863 pham = functools.partialmethod(ham)
864 @functools.wraps(mod.spam)
865 def __call__(self, x, y):
866 pass
867 check_method(C())
868 check_method(C.ham)
869 check_method(C().ham)
870 check_method(C.pham)
871 check_method(C().pham)
872
873 class C_new:
874 @functools.wraps(mod.spam)
875 def __new__(self, x, y):
876 pass
877 check_method(C_new)
878
879 class C_init:
880 @functools.wraps(mod.spam)
881 def __init__(self, x, y):
882 pass
883 check_method(C_init)
884
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500885 def test_getfullargspec_signature_attr(self):
886 def test():
887 pass
888 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
889 test.__signature__ = inspect.Signature(parameters=(spam_param,))
890
Pablo Galindod5d2b452019-04-30 02:01:14 +0100891 self.assertFullArgSpecEquals(test, ['spam'], formatted='(spam)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500892
Yury Selivanov4cb93912014-01-29 11:54:12 -0500893 def test_getfullargspec_signature_annos(self):
894 def test(a:'spam') -> 'ham': pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100895 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500896 self.assertEqual(test.__annotations__, spec.annotations)
897
898 def test(): pass
Pablo Galindoaee19f52019-05-16 21:08:15 +0100899 spec = inspect.getfullargspec(test)
Yury Selivanov4cb93912014-01-29 11:54:12 -0500900 self.assertEqual(test.__annotations__, spec.annotations)
901
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500902 @unittest.skipIf(MISSING_C_DOCSTRINGS,
903 "Signature information for builtins requires docstrings")
904 def test_getfullargspec_builtin_methods(self):
Pablo Galindod5d2b452019-04-30 02:01:14 +0100905 self.assertFullArgSpecEquals(_pickle.Pickler.dump, ['self', 'obj'],
906 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500907
Pablo Galindod5d2b452019-04-30 02:01:14 +0100908 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, ['self', 'obj'],
909 formatted='(self, obj)')
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500910
Yury Selivanov8c185ee2014-02-21 01:32:42 -0500911 self.assertFullArgSpecEquals(
912 os.stat,
913 args_e=['path'],
914 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
915 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
916 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
917
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200918 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500919 @unittest.skipIf(MISSING_C_DOCSTRINGS,
920 "Signature information for builtins requires docstrings")
Chih-Hsuan Yenc57eb9a2018-10-04 21:15:00 +0800921 def test_getfullargspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200922 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500923 builtin = _testcapi.docstring_with_signature_with_defaults
Pablo Galindoaee19f52019-05-16 21:08:15 +0100924 spec = inspect.getfullargspec(builtin)
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500925 self.assertEqual(spec.defaults[0], 'avocado')
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_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200931 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500932 builtin = _testcapi.docstring_no_signature
Pablo Galindoaee19f52019-05-16 21:08:15 +0100933 with self.assertRaises(TypeError):
934 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000935
larryhastingsf36ba122018-01-28 11:13:09 -0800936 def test_getfullargspec_definition_order_preserved_on_kwonly(self):
937 for fn in signatures_with_lexicographic_keyword_only_parameters():
Pablo Galindoaee19f52019-05-16 21:08:15 +0100938 signature = inspect.getfullargspec(fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800939 l = list(signature.kwonlyargs)
940 sorted_l = sorted(l)
941 self.assertTrue(l)
942 self.assertEqual(l, sorted_l)
Pablo Galindoaee19f52019-05-16 21:08:15 +0100943 signature = inspect.getfullargspec(unsorted_keyword_only_parameters_fn)
larryhastingsf36ba122018-01-28 11:13:09 -0800944 l = list(signature.kwonlyargs)
945 self.assertEqual(l, unsorted_keyword_only_parameters)
946
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500947 def test_getargspec_method(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000948 class A(object):
949 def m(self):
950 pass
Yury Selivanov37dc2b22016-01-11 15:15:01 -0500951 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000952
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000953 def test_classify_newstyle(self):
954 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000955
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000956 def s(): pass
957 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000958
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000959 def c(cls): pass
960 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000961
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000962 def getp(self): pass
963 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000964
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000965 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000966
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000967 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000968
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000969 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000970
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100971 dd = _BrokenDataDescriptor()
972 md = _BrokenMethodDescriptor()
973
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000974 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500975
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +0200976 self.assertIn(('__new__', 'static method', object), attrs,
977 'missing __new__')
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500978 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
979
Benjamin Peterson577473f2010-01-19 00:09:57 +0000980 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
981 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
982 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000983 self.assertIn(('m', 'method', A), attrs,
984 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000985 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
986 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100987 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
988 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000989
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000990 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000991
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000992 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000993
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000994 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000995 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
996 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
997 self.assertIn(('p', 'property', A), attrs, 'missing property')
998 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
999 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1000 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001001 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1002 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001003
1004
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001005 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +00001006
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001007 def m(self): pass
1008 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001009
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001010 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001011 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1012 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1013 self.assertIn(('p', 'property', A), attrs, 'missing property')
1014 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
1015 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
1016 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001017 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1018 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +00001019
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001020 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +00001021
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001022 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +00001023
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00001024 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001025 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
1026 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
1027 self.assertIn(('p', 'property', A), attrs, 'missing property')
1028 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
1029 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
1030 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001031 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
1032 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
1033
1034 def test_classify_builtin_types(self):
1035 # Simple sanity check that all built-in types can have their
1036 # attributes classified.
1037 for name in dir(__builtins__):
1038 builtin = getattr(__builtins__, name)
1039 if isinstance(builtin, type):
1040 inspect.classify_class_attrs(builtin)
1041
Serhiy Storchaka3327a2d2017-12-15 14:13:41 +02001042 attrs = attrs_wo_objs(bool)
1043 self.assertIn(('__new__', 'static method', bool), attrs,
1044 'missing __new__')
1045 self.assertIn(('from_bytes', 'class method', int), attrs,
1046 'missing class method')
1047 self.assertIn(('to_bytes', 'method', int), attrs,
1048 'missing plain method')
1049 self.assertIn(('__add__', 'method', int), attrs,
1050 'missing plain method')
1051 self.assertIn(('__and__', 'method', bool), attrs,
1052 'missing plain method')
1053
Ethan Furman63c141c2013-10-18 00:27:39 -07001054 def test_classify_DynamicClassAttribute(self):
1055 class Meta(type):
1056 def __getattr__(self, name):
1057 if name == 'ham':
1058 return 'spam'
1059 return super().__getattr__(name)
1060 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -07001061 @types.DynamicClassAttribute
1062 def ham(self):
1063 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -07001064 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
1065 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001066 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -07001067 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
1068
Yury Selivanovbf341fb2015-05-21 15:41:57 -04001069 def test_classify_overrides_bool(self):
1070 class NoBool(object):
1071 def __eq__(self, other):
1072 return NoBool()
1073
1074 def __bool__(self):
1075 raise NotImplementedError(
1076 "This object does not specify a boolean value")
1077
1078 class HasNB(object):
1079 dd = NoBool()
1080
1081 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
1082 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
1083
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001084 def test_classify_metaclass_class_attribute(self):
1085 class Meta(type):
1086 fish = 'slap'
1087 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001088 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001089 class Class(metaclass=Meta):
1090 pass
1091 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
1092 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1093
Ethan Furman63c141c2013-10-18 00:27:39 -07001094 def test_classify_VirtualAttribute(self):
1095 class Meta(type):
1096 def __dir__(cls):
1097 return ['__class__', '__module__', '__name__', 'BOOM']
1098 def __getattr__(self, name):
1099 if name =='BOOM':
1100 return 42
1101 return super().__getattr(name)
1102 class Class(metaclass=Meta):
1103 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001104 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -07001105 self.assertIn(should_find, inspect.classify_class_attrs(Class))
1106
1107 def test_classify_VirtualAttribute_multi_classes(self):
1108 class Meta1(type):
1109 def __dir__(cls):
1110 return ['__class__', '__module__', '__name__', 'one']
1111 def __getattr__(self, name):
1112 if name =='one':
1113 return 1
1114 return super().__getattr__(name)
1115 class Meta2(type):
1116 def __dir__(cls):
1117 return ['__class__', '__module__', '__name__', 'two']
1118 def __getattr__(self, name):
1119 if name =='two':
1120 return 2
1121 return super().__getattr__(name)
1122 class Meta3(Meta1, Meta2):
1123 def __dir__(cls):
1124 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
1125 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
1126 def __getattr__(self, name):
1127 if name =='three':
1128 return 3
1129 return super().__getattr__(name)
1130 class Class1(metaclass=Meta1):
1131 pass
1132 class Class2(Class1, metaclass=Meta3):
1133 pass
1134
Ethan Furmanb0c84cd2013-10-20 22:37:39 -07001135 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
1136 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
1137 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -07001138 cca = inspect.classify_class_attrs(Class2)
1139 for sf in (should_find1, should_find2, should_find3):
1140 self.assertIn(sf, cca)
1141
1142 def test_classify_class_attrs_with_buggy_dir(self):
1143 class M(type):
1144 def __dir__(cls):
1145 return ['__class__', '__name__', 'missing']
1146 class C(metaclass=M):
1147 pass
1148 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
1149 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001150
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +01001151 def test_getmembers_descriptors(self):
1152 class A(object):
1153 dd = _BrokenDataDescriptor()
1154 md = _BrokenMethodDescriptor()
1155
1156 def pred_wrapper(pred):
1157 # A quick'n'dirty way to discard standard attributes of new-style
1158 # classes.
1159 class Empty(object):
1160 pass
1161 def wrapped(x):
1162 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
1163 return False
1164 return pred(x)
1165 return wrapped
1166
1167 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
1168 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
1169
1170 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
1171 [('md', A.__dict__['md'])])
1172 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
1173 [('dd', A.__dict__['dd'])])
1174
1175 class B(A):
1176 pass
1177
1178 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
1179 [('md', A.__dict__['md'])])
1180 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
1181 [('dd', A.__dict__['dd'])])
1182
Antoine Pitrou0c603812012-01-18 17:40:18 +01001183 def test_getmembers_method(self):
1184 class B:
1185 def f(self):
1186 pass
1187
1188 self.assertIn(('f', B.f), inspect.getmembers(B))
1189 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
1190 b = B()
1191 self.assertIn(('f', b.f), inspect.getmembers(b))
1192 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
1193
Ethan Furmane03ea372013-09-25 07:14:41 -07001194 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -07001195 class M(type):
1196 def __getattr__(cls, name):
1197 if name == 'eggs':
1198 return 'scrambled'
1199 return super().__getattr__(name)
1200 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -07001201 @types.DynamicClassAttribute
1202 def eggs(self):
1203 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -07001204 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
1205 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
1206
1207 def test_getmembers_with_buggy_dir(self):
1208 class M(type):
1209 def __dir__(cls):
1210 return ['__class__', '__name__', 'missing']
1211 class C(metaclass=M):
1212 pass
1213 attrs = [a[0] for a in inspect.getmembers(C)]
1214 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -07001215
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04001216class TestIsDataDescriptor(unittest.TestCase):
1217
1218 def test_custom_descriptors(self):
1219 class NonDataDescriptor:
1220 def __get__(self, value, type=None): pass
1221 class DataDescriptor0:
1222 def __set__(self, name, value): pass
1223 class DataDescriptor1:
1224 def __delete__(self, name): pass
1225 class DataDescriptor2:
1226 __set__ = None
1227 self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()),
1228 'class with only __get__ not a data descriptor')
1229 self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()),
1230 'class with __set__ is a data descriptor')
1231 self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()),
1232 'class with __delete__ is a data descriptor')
1233 self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()),
1234 'class with __set__ = None is a data descriptor')
1235
1236 def test_slot(self):
1237 class Slotted:
1238 __slots__ = 'foo',
1239 self.assertTrue(inspect.isdatadescriptor(Slotted.foo),
1240 'a slot is a data descriptor')
1241
1242 def test_property(self):
1243 class Propertied:
1244 @property
1245 def a_property(self):
1246 pass
1247 self.assertTrue(inspect.isdatadescriptor(Propertied.a_property),
1248 'a property is a data descriptor')
1249
1250 def test_functions(self):
1251 class Test(object):
1252 def instance_method(self): pass
1253 @classmethod
1254 def class_method(cls): pass
1255 @staticmethod
1256 def static_method(): pass
1257 def function():
1258 pass
1259 a_lambda = lambda: None
1260 self.assertFalse(inspect.isdatadescriptor(Test().instance_method),
1261 'a instance method is not a data descriptor')
1262 self.assertFalse(inspect.isdatadescriptor(Test().class_method),
1263 'a class method is not a data descriptor')
1264 self.assertFalse(inspect.isdatadescriptor(Test().static_method),
1265 'a static method is not a data descriptor')
1266 self.assertFalse(inspect.isdatadescriptor(function),
1267 'a function is not a data descriptor')
1268 self.assertFalse(inspect.isdatadescriptor(a_lambda),
1269 'a lambda is not a data descriptor')
1270
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +00001271
Nick Coghlan2f92e542012-06-23 19:39:55 +10001272_global_ref = object()
1273class TestGetClosureVars(unittest.TestCase):
1274
1275 def test_name_resolution(self):
1276 # Basic test of the 4 different resolution mechanisms
1277 def f(nonlocal_ref):
1278 def g(local_ref):
1279 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1280 return g
1281 _arg = object()
1282 nonlocal_vars = {"nonlocal_ref": _arg}
1283 global_vars = {"_global_ref": _global_ref}
1284 builtin_vars = {"print": print}
1285 unbound_names = {"unbound_ref"}
1286 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1287 builtin_vars, unbound_names)
1288 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1289
1290 def test_generator_closure(self):
1291 def f(nonlocal_ref):
1292 def g(local_ref):
1293 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1294 yield
1295 return g
1296 _arg = object()
1297 nonlocal_vars = {"nonlocal_ref": _arg}
1298 global_vars = {"_global_ref": _global_ref}
1299 builtin_vars = {"print": print}
1300 unbound_names = {"unbound_ref"}
1301 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1302 builtin_vars, unbound_names)
1303 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
1304
1305 def test_method_closure(self):
1306 class C:
1307 def f(self, nonlocal_ref):
1308 def g(local_ref):
1309 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
1310 return g
1311 _arg = object()
1312 nonlocal_vars = {"nonlocal_ref": _arg}
1313 global_vars = {"_global_ref": _global_ref}
1314 builtin_vars = {"print": print}
1315 unbound_names = {"unbound_ref"}
1316 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
1317 builtin_vars, unbound_names)
1318 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
1319
1320 def test_nonlocal_vars(self):
1321 # More complex tests of nonlocal resolution
1322 def _nonlocal_vars(f):
1323 return inspect.getclosurevars(f).nonlocals
1324
1325 def make_adder(x):
1326 def add(y):
1327 return x + y
1328 return add
1329
1330 def curry(func, arg1):
1331 return lambda arg2: func(arg1, arg2)
1332
1333 def less_than(a, b):
1334 return a < b
1335
1336 # The infamous Y combinator.
1337 def Y(le):
1338 def g(f):
1339 return le(lambda x: f(f)(x))
1340 Y.g_ref = g
1341 return g(g)
1342
1343 def check_y_combinator(func):
1344 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1345
1346 inc = make_adder(1)
1347 add_two = make_adder(2)
1348 greater_than_five = curry(less_than, 5)
1349
1350 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1351 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1352 self.assertEqual(_nonlocal_vars(greater_than_five),
1353 {'arg1': 5, 'func': less_than})
1354 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1355 {'x': 3})
1356 Y(check_y_combinator)
1357
1358 def test_getclosurevars_empty(self):
1359 def foo(): pass
1360 _empty = inspect.ClosureVars({}, {}, {}, set())
1361 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1362 self.assertEqual(inspect.getclosurevars(foo), _empty)
1363
1364 def test_getclosurevars_error(self):
1365 class T: pass
1366 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1367 self.assertRaises(TypeError, inspect.getclosurevars, list)
1368 self.assertRaises(TypeError, inspect.getclosurevars, {})
1369
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001370 def _private_globals(self):
1371 code = """def f(): print(path)"""
1372 ns = {}
1373 exec(code, ns)
1374 return ns["f"], ns
1375
1376 def test_builtins_fallback(self):
1377 f, ns = self._private_globals()
1378 ns.pop("__builtins__", None)
1379 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1380 self.assertEqual(inspect.getclosurevars(f), expected)
1381
1382 def test_builtins_as_dict(self):
1383 f, ns = self._private_globals()
1384 ns["__builtins__"] = {"path":1}
1385 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1386 self.assertEqual(inspect.getclosurevars(f), expected)
1387
1388 def test_builtins_as_module(self):
1389 f, ns = self._private_globals()
1390 ns["__builtins__"] = os
1391 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1392 self.assertEqual(inspect.getclosurevars(f), expected)
1393
Nick Coghlan2f92e542012-06-23 19:39:55 +10001394
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001395class TestGetcallargsFunctions(unittest.TestCase):
1396
1397 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1398 locs = dict(locs or {}, func=func)
1399 r1 = eval('func(%s)' % call_params_string, None, locs)
Pablo Galindoaee19f52019-05-16 21:08:15 +01001400 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1401 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001402 self.assertEqual(r1, r2)
1403
1404 def assertEqualException(self, func, call_param_string, locs=None):
1405 locs = dict(locs or {}, func=func)
1406 try:
1407 eval('func(%s)' % call_param_string, None, locs)
1408 except Exception as e:
1409 ex1 = e
1410 else:
1411 self.fail('Exception not raised')
1412 try:
Pablo Galindoaee19f52019-05-16 21:08:15 +01001413 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1414 locs)
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001415 except Exception as e:
1416 ex2 = e
1417 else:
1418 self.fail('Exception not raised')
1419 self.assertIs(type(ex1), type(ex2))
1420 self.assertEqual(str(ex1), str(ex2))
1421 del ex1, ex2
1422
1423 def makeCallable(self, signature):
1424 """Create a function that returns its locals()"""
1425 code = "lambda %s: locals()"
1426 return eval(code % signature)
1427
1428 def test_plain(self):
1429 f = self.makeCallable('a, b=1')
1430 self.assertEqualCallArgs(f, '2')
1431 self.assertEqualCallArgs(f, '2, 3')
1432 self.assertEqualCallArgs(f, 'a=2')
1433 self.assertEqualCallArgs(f, 'b=3, a=2')
1434 self.assertEqualCallArgs(f, '2, b=3')
1435 # expand *iterable / **mapping
1436 self.assertEqualCallArgs(f, '*(2,)')
1437 self.assertEqualCallArgs(f, '*[2]')
1438 self.assertEqualCallArgs(f, '*(2, 3)')
1439 self.assertEqualCallArgs(f, '*[2, 3]')
1440 self.assertEqualCallArgs(f, '**{"a":2}')
1441 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1442 self.assertEqualCallArgs(f, '2, **{"b":3}')
1443 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1444 # expand UserList / UserDict
1445 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1446 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1447 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1448 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1449 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1450
1451 def test_varargs(self):
1452 f = self.makeCallable('a, b=1, *c')
1453 self.assertEqualCallArgs(f, '2')
1454 self.assertEqualCallArgs(f, '2, 3')
1455 self.assertEqualCallArgs(f, '2, 3, 4')
1456 self.assertEqualCallArgs(f, '*(2,3,4)')
1457 self.assertEqualCallArgs(f, '2, *[3,4]')
1458 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1459
1460 def test_varkw(self):
1461 f = self.makeCallable('a, b=1, **c')
1462 self.assertEqualCallArgs(f, 'a=2')
1463 self.assertEqualCallArgs(f, '2, b=3, c=4')
1464 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1465 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1466 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1467 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1468 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1469 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1470 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1471
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001472 def test_varkw_only(self):
1473 # issue11256:
1474 f = self.makeCallable('**c')
1475 self.assertEqualCallArgs(f, '')
1476 self.assertEqualCallArgs(f, 'a=1')
1477 self.assertEqualCallArgs(f, 'a=1, b=2')
1478 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1479 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1480 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1481
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001482 def test_keyword_only(self):
1483 f = self.makeCallable('a=3, *, c, d=2')
1484 self.assertEqualCallArgs(f, 'c=3')
1485 self.assertEqualCallArgs(f, 'c=3, a=3')
1486 self.assertEqualCallArgs(f, 'a=2, c=4')
1487 self.assertEqualCallArgs(f, '4, c=4')
1488 self.assertEqualException(f, '')
1489 self.assertEqualException(f, '3')
1490 self.assertEqualException(f, 'a=3')
1491 self.assertEqualException(f, 'd=4')
1492
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001493 f = self.makeCallable('*, c, d=2')
1494 self.assertEqualCallArgs(f, 'c=3')
1495 self.assertEqualCallArgs(f, 'c=3, d=4')
1496 self.assertEqualCallArgs(f, 'd=4, c=3')
1497
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001498 def test_multiple_features(self):
1499 f = self.makeCallable('a, b=2, *f, **g')
1500 self.assertEqualCallArgs(f, '2, 3, 7')
1501 self.assertEqualCallArgs(f, '2, 3, x=8')
1502 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1503 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1504 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1505 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1506 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1507 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1508 '(4,[5,6])]), **collections.UserDict('
1509 'y=9, z=10)')
1510
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001511 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1512 self.assertEqualCallArgs(f, '2, 3, x=8')
1513 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1514 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1515 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1516 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1517 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1518 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1519 '(4,[5,6])]), q=0, **collections.UserDict('
1520 'y=9, z=10)')
1521
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001522 def test_errors(self):
1523 f0 = self.makeCallable('')
1524 f1 = self.makeCallable('a, b')
1525 f2 = self.makeCallable('a, b=1')
1526 # f0 takes no arguments
1527 self.assertEqualException(f0, '1')
1528 self.assertEqualException(f0, 'x=1')
1529 self.assertEqualException(f0, '1,x=1')
1530 # f1 takes exactly 2 arguments
1531 self.assertEqualException(f1, '')
1532 self.assertEqualException(f1, '1')
1533 self.assertEqualException(f1, 'a=2')
1534 self.assertEqualException(f1, 'b=3')
1535 # f2 takes at least 1 argument
1536 self.assertEqualException(f2, '')
1537 self.assertEqualException(f2, 'b=3')
1538 for f in f1, f2:
1539 # f1/f2 takes exactly/at most 2 arguments
1540 self.assertEqualException(f, '2, 3, 4')
1541 self.assertEqualException(f, '1, 2, 3, a=1')
1542 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001543 # XXX: success of this one depends on dict order
1544 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001545 # f got an unexpected keyword argument
1546 self.assertEqualException(f, 'c=2')
1547 self.assertEqualException(f, '2, c=3')
1548 self.assertEqualException(f, '2, 3, c=4')
1549 self.assertEqualException(f, '2, c=4, b=3')
1550 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1551 # f got multiple values for keyword argument
1552 self.assertEqualException(f, '1, a=2')
1553 self.assertEqualException(f, '1, **{"a":2}')
1554 self.assertEqualException(f, '1, 2, b=3')
1555 # XXX: Python inconsistency
1556 # - for functions and bound methods: unexpected keyword 'c'
1557 # - for unbound methods: multiple values for keyword 'a'
1558 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001559 # issue11256:
1560 f3 = self.makeCallable('**c')
1561 self.assertEqualException(f3, '1, 2')
1562 self.assertEqualException(f3, '1, 2, a=1, b=2')
1563 f4 = self.makeCallable('*, a, b=0')
1564 self.assertEqualException(f3, '1, 2')
1565 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001566
Yury Selivanov875df202014-03-27 18:23:03 -04001567 # issue #20816: getcallargs() fails to iterate over non-existent
1568 # kwonlydefaults and raises a wrong TypeError
1569 def f5(*, a): pass
1570 with self.assertRaisesRegex(TypeError,
1571 'missing 1 required keyword-only'):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001572 inspect.getcallargs(f5)
Yury Selivanov875df202014-03-27 18:23:03 -04001573
1574
Yury Selivanovdccfa132014-03-27 18:42:52 -04001575 # issue20817:
1576 def f6(a, b, c):
1577 pass
1578 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
Pablo Galindoaee19f52019-05-16 21:08:15 +01001579 inspect.getcallargs(f6)
Yury Selivanovdccfa132014-03-27 18:42:52 -04001580
Dong-hee Naa9cab432018-05-30 00:04:08 +09001581 # bpo-33197
1582 with self.assertRaisesRegex(ValueError,
1583 'variadic keyword parameters cannot'
1584 ' have default values'):
1585 inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD,
1586 default=42)
1587 with self.assertRaisesRegex(ValueError,
1588 "value 5 is not a valid Parameter.kind"):
1589 inspect.Parameter("bar", kind=5, default=42)
1590
1591 with self.assertRaisesRegex(TypeError,
1592 'name must be a str, not a int'):
1593 inspect.Parameter(123, kind=4)
1594
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001595class TestGetcallargsMethods(TestGetcallargsFunctions):
1596
1597 def setUp(self):
1598 class Foo(object):
1599 pass
1600 self.cls = Foo
1601 self.inst = Foo()
1602
1603 def makeCallable(self, signature):
1604 assert 'self' not in signature
1605 mk = super(TestGetcallargsMethods, self).makeCallable
1606 self.cls.method = mk('self, ' + signature)
1607 return self.inst.method
1608
1609class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1610
1611 def makeCallable(self, signature):
1612 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1613 return self.cls.method
1614
1615 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1616 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1617 *self._getAssertEqualParams(func, call_params_string, locs))
1618
1619 def assertEqualException(self, func, call_params_string, locs=None):
1620 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1621 *self._getAssertEqualParams(func, call_params_string, locs))
1622
1623 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1624 assert 'inst' not in call_params_string
1625 locs = dict(locs or {}, inst=self.inst)
1626 return (func, 'inst,' + call_params_string, locs)
1627
Michael Foord95fc51d2010-11-20 15:07:30 +00001628
1629class TestGetattrStatic(unittest.TestCase):
1630
1631 def test_basic(self):
1632 class Thing(object):
1633 x = object()
1634
1635 thing = Thing()
1636 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1637 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1638 with self.assertRaises(AttributeError):
1639 inspect.getattr_static(thing, 'y')
1640
1641 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1642
1643 def test_inherited(self):
1644 class Thing(object):
1645 x = object()
1646 class OtherThing(Thing):
1647 pass
1648
1649 something = OtherThing()
1650 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1651
1652 def test_instance_attr(self):
1653 class Thing(object):
1654 x = 2
1655 def __init__(self, x):
1656 self.x = x
1657 thing = Thing(3)
1658 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1659 del thing.x
1660 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1661
1662 def test_property(self):
1663 class Thing(object):
1664 @property
1665 def x(self):
1666 raise AttributeError("I'm pretending not to exist")
1667 thing = Thing()
1668 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1669
Ezio Melotti75cbd732011-04-28 00:59:29 +03001670 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001671 class descriptor(object):
1672 def __get__(*_):
1673 raise AttributeError("I'm pretending not to exist")
1674 desc = descriptor()
1675 class Thing(object):
1676 x = desc
1677 thing = Thing()
1678 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1679
1680 def test_classAttribute(self):
1681 class Thing(object):
1682 x = object()
1683
1684 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1685
Ethan Furmane03ea372013-09-25 07:14:41 -07001686 def test_classVirtualAttribute(self):
1687 class Thing(object):
1688 @types.DynamicClassAttribute
1689 def x(self):
1690 return self._x
1691 _x = object()
1692
1693 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1694
Michael Foord95fc51d2010-11-20 15:07:30 +00001695 def test_inherited_classattribute(self):
1696 class Thing(object):
1697 x = object()
1698 class OtherThing(Thing):
1699 pass
1700
1701 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1702
1703 def test_slots(self):
1704 class Thing(object):
1705 y = 'bar'
1706 __slots__ = ['x']
1707 def __init__(self):
1708 self.x = 'foo'
1709 thing = Thing()
1710 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1711 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1712
1713 del thing.x
1714 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1715
1716 def test_metaclass(self):
1717 class meta(type):
1718 attr = 'foo'
1719 class Thing(object, metaclass=meta):
1720 pass
1721 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1722
1723 class sub(meta):
1724 pass
1725 class OtherThing(object, metaclass=sub):
1726 x = 3
1727 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1728
1729 class OtherOtherThing(OtherThing):
1730 pass
1731 # this test is odd, but it was added as it exposed a bug
1732 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1733
1734 def test_no_dict_no_slots(self):
1735 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1736 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1737
1738 def test_no_dict_no_slots_instance_member(self):
1739 # returns descriptor
1740 with open(__file__) as handle:
1741 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1742
1743 def test_inherited_slots(self):
1744 # returns descriptor
1745 class Thing(object):
1746 __slots__ = ['x']
1747 def __init__(self):
1748 self.x = 'foo'
1749
1750 class OtherThing(Thing):
1751 pass
1752 # it would be nice if this worked...
1753 # we get the descriptor instead of the instance attribute
1754 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1755
1756 def test_descriptor(self):
1757 class descriptor(object):
1758 def __get__(self, instance, owner):
1759 return 3
1760 class Foo(object):
1761 d = descriptor()
1762
1763 foo = Foo()
1764
1765 # for a non data descriptor we return the instance attribute
1766 foo.__dict__['d'] = 1
1767 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1768
Mike53f7a7c2017-12-14 14:04:53 +03001769 # if the descriptor is a data-descriptor we should return the
Michael Foord95fc51d2010-11-20 15:07:30 +00001770 # descriptor
1771 descriptor.__set__ = lambda s, i, v: None
1772 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1773
1774
1775 def test_metaclass_with_descriptor(self):
1776 class descriptor(object):
1777 def __get__(self, instance, owner):
1778 return 3
1779 class meta(type):
1780 d = descriptor()
1781 class Thing(object, metaclass=meta):
1782 pass
1783 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1784
1785
Michael Foordcc7ebb82010-11-20 16:20:16 +00001786 def test_class_as_property(self):
1787 class Base(object):
1788 foo = 3
1789
1790 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001791 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001792 @property
1793 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001794 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001795 return object
1796
Michael Foord35184ed2010-11-20 16:58:30 +00001797 instance = Something()
1798 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1799 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001800 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1801
Michael Foorde5162652010-11-20 16:40:44 +00001802 def test_mro_as_property(self):
1803 class Meta(type):
1804 @property
1805 def __mro__(self):
1806 return (object,)
1807
1808 class Base(object):
1809 foo = 3
1810
1811 class Something(Base, metaclass=Meta):
1812 pass
1813
1814 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1815 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1816
Michael Foorddcebe0f2011-03-15 19:20:44 -04001817 def test_dict_as_property(self):
1818 test = self
1819 test.called = False
1820
1821 class Foo(dict):
1822 a = 3
1823 @property
1824 def __dict__(self):
1825 test.called = True
1826 return {}
1827
1828 foo = Foo()
1829 foo.a = 4
1830 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1831 self.assertFalse(test.called)
1832
1833 def test_custom_object_dict(self):
1834 test = self
1835 test.called = False
1836
1837 class Custom(dict):
1838 def get(self, key, default=None):
1839 test.called = True
1840 super().get(key, default)
1841
1842 class Foo(object):
1843 a = 3
1844 foo = Foo()
1845 foo.__dict__ = Custom()
1846 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1847 self.assertFalse(test.called)
1848
1849 def test_metaclass_dict_as_property(self):
1850 class Meta(type):
1851 @property
1852 def __dict__(self):
1853 self.executed = True
1854
1855 class Thing(metaclass=Meta):
1856 executed = False
1857
1858 def __init__(self):
1859 self.spam = 42
1860
1861 instance = Thing()
1862 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1863 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001864
Michael Foorda51623b2011-12-18 22:01:40 +00001865 def test_module(self):
1866 sentinel = object()
1867 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1868 sentinel)
1869
Michael Foord3ba95f82011-12-22 01:13:37 +00001870 def test_metaclass_with_metaclass_with_dict_as_property(self):
1871 class MetaMeta(type):
1872 @property
1873 def __dict__(self):
1874 self.executed = True
1875 return dict(spam=42)
1876
1877 class Meta(type, metaclass=MetaMeta):
1878 executed = False
1879
1880 class Thing(metaclass=Meta):
1881 pass
1882
1883 with self.assertRaises(AttributeError):
1884 inspect.getattr_static(Thing, "spam")
1885 self.assertFalse(Thing.executed)
1886
Nick Coghlane0f04652010-11-21 03:44:04 +00001887class TestGetGeneratorState(unittest.TestCase):
1888
1889 def setUp(self):
1890 def number_generator():
1891 for number in range(5):
1892 yield number
1893 self.generator = number_generator()
1894
1895 def _generatorstate(self):
1896 return inspect.getgeneratorstate(self.generator)
1897
1898 def test_created(self):
1899 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1900
1901 def test_suspended(self):
1902 next(self.generator)
1903 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1904
1905 def test_closed_after_exhaustion(self):
1906 for i in self.generator:
1907 pass
1908 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1909
1910 def test_closed_after_immediate_exception(self):
1911 with self.assertRaises(RuntimeError):
1912 self.generator.throw(RuntimeError)
1913 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1914
1915 def test_running(self):
1916 # As mentioned on issue #10220, checking for the RUNNING state only
1917 # makes sense inside the generator itself.
1918 # The following generator checks for this by using the closure's
1919 # reference to self and the generator state checking helper method
1920 def running_check_generator():
1921 for number in range(5):
1922 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1923 yield number
1924 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1925 self.generator = running_check_generator()
1926 # Running up to the first yield
1927 next(self.generator)
1928 # Running after the first yield
1929 next(self.generator)
1930
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001931 def test_easy_debugging(self):
1932 # repr() and str() of a generator state should contain the state name
1933 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1934 for name in names:
1935 state = getattr(inspect, name)
1936 self.assertIn(name, repr(state))
1937 self.assertIn(name, str(state))
1938
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001939 def test_getgeneratorlocals(self):
1940 def each(lst, a=None):
1941 b=(1, 2, 3)
1942 for v in lst:
1943 if v == 3:
1944 c = 12
1945 yield v
1946
1947 numbers = each([1, 2, 3])
1948 self.assertEqual(inspect.getgeneratorlocals(numbers),
1949 {'a': None, 'lst': [1, 2, 3]})
1950 next(numbers)
1951 self.assertEqual(inspect.getgeneratorlocals(numbers),
1952 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1953 'b': (1, 2, 3)})
1954 next(numbers)
1955 self.assertEqual(inspect.getgeneratorlocals(numbers),
1956 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1957 'b': (1, 2, 3)})
1958 next(numbers)
1959 self.assertEqual(inspect.getgeneratorlocals(numbers),
1960 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1961 'b': (1, 2, 3), 'c': 12})
1962 try:
1963 next(numbers)
1964 except StopIteration:
1965 pass
1966 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1967
1968 def test_getgeneratorlocals_empty(self):
1969 def yield_one():
1970 yield 1
1971 one = yield_one()
1972 self.assertEqual(inspect.getgeneratorlocals(one), {})
1973 try:
1974 next(one)
1975 except StopIteration:
1976 pass
1977 self.assertEqual(inspect.getgeneratorlocals(one), {})
1978
1979 def test_getgeneratorlocals_error(self):
1980 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1981 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1982 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1983 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1984
Nick Coghlane0f04652010-11-21 03:44:04 +00001985
Yury Selivanov5376ba92015-06-22 12:19:30 -04001986class TestGetCoroutineState(unittest.TestCase):
1987
1988 def setUp(self):
1989 @types.coroutine
1990 def number_coroutine():
1991 for number in range(5):
1992 yield number
1993 async def coroutine():
1994 await number_coroutine()
1995 self.coroutine = coroutine()
1996
1997 def tearDown(self):
1998 self.coroutine.close()
1999
2000 def _coroutinestate(self):
2001 return inspect.getcoroutinestate(self.coroutine)
2002
2003 def test_created(self):
2004 self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED)
2005
2006 def test_suspended(self):
2007 self.coroutine.send(None)
2008 self.assertEqual(self._coroutinestate(), inspect.CORO_SUSPENDED)
2009
2010 def test_closed_after_exhaustion(self):
2011 while True:
2012 try:
2013 self.coroutine.send(None)
2014 except StopIteration:
2015 break
2016
2017 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2018
2019 def test_closed_after_immediate_exception(self):
2020 with self.assertRaises(RuntimeError):
2021 self.coroutine.throw(RuntimeError)
2022 self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
2023
2024 def test_easy_debugging(self):
2025 # repr() and str() of a coroutine state should contain the state name
2026 names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
2027 for name in names:
2028 state = getattr(inspect, name)
2029 self.assertIn(name, repr(state))
2030 self.assertIn(name, str(state))
2031
2032 def test_getcoroutinelocals(self):
2033 @types.coroutine
2034 def gencoro():
2035 yield
2036
2037 gencoro = gencoro()
2038 async def func(a=None):
2039 b = 'spam'
2040 await gencoro
2041
2042 coro = func()
2043 self.assertEqual(inspect.getcoroutinelocals(coro),
2044 {'a': None, 'gencoro': gencoro})
2045 coro.send(None)
2046 self.assertEqual(inspect.getcoroutinelocals(coro),
2047 {'a': None, 'gencoro': gencoro, 'b': 'spam'})
2048
2049
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002050class MySignature(inspect.Signature):
2051 # Top-level to make it picklable;
2052 # used in test_signature_object_pickle
2053 pass
2054
2055class MyParameter(inspect.Parameter):
2056 # Top-level to make it picklable;
2057 # used in test_signature_object_pickle
2058 pass
2059
Nick Coghlanf9e227e2014-08-17 14:01:19 +10002060
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002061
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002062class TestSignatureObject(unittest.TestCase):
2063 @staticmethod
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002064 def signature(func, **kw):
2065 sig = inspect.signature(func, **kw)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002066 return (tuple((param.name,
2067 (... if param.default is param.empty else param.default),
2068 (... if param.annotation is param.empty
2069 else param.annotation),
2070 str(param.kind).lower())
2071 for param in sig.parameters.values()),
2072 (... if sig.return_annotation is sig.empty
2073 else sig.return_annotation))
2074
2075 def test_signature_object(self):
2076 S = inspect.Signature
2077 P = inspect.Parameter
2078
2079 self.assertEqual(str(S()), '()')
2080
Yury Selivanov07a9e452014-01-29 10:58:16 -05002081 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002082 pass
2083 sig = inspect.signature(test)
2084 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002085 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002086 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002087 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002088 args = sig.parameters['args']
2089 ko = sig.parameters['ko']
2090 kwargs = sig.parameters['kwargs']
2091
2092 S((po, pk, args, ko, kwargs))
2093
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002094 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002095 S((pk, po, args, ko, kwargs))
2096
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002097 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002098 S((po, args, pk, ko, kwargs))
2099
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002100 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002101 S((args, po, pk, ko, kwargs))
2102
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002103 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002104 S((po, pk, args, kwargs, ko))
2105
2106 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002107 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002108 S((po, pk, args, kwargs2, ko))
2109
Yury Selivanov07a9e452014-01-29 10:58:16 -05002110 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2111 S((pod, po))
2112
2113 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2114 S((po, pkd, pk))
2115
2116 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2117 S((pkd, pk))
2118
Yury Selivanov374375d2014-03-27 12:41:53 -04002119 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002120 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002121
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002122 def test_signature_object_pickle(self):
2123 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2124 foo_partial = functools.partial(foo, a=1)
2125
2126 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002127
2128 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2129 with self.subTest(pickle_ver=ver, subclass=False):
2130 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2131 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002132
2133 # Test that basic sub-classing works
2134 sig = inspect.signature(foo)
2135 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2136 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2137 mysig = MySignature().replace(parameters=myparams.values(),
2138 return_annotation=sig.return_annotation)
2139 self.assertTrue(isinstance(mysig, MySignature))
2140 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2141
2142 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2143 with self.subTest(pickle_ver=ver, subclass=True):
2144 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2145 self.assertEqual(mysig, sig_pickled)
2146 self.assertTrue(isinstance(sig_pickled, MySignature))
2147 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2148 MyParameter))
2149
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002150 def test_signature_immutability(self):
2151 def test(a):
2152 pass
2153 sig = inspect.signature(test)
2154
2155 with self.assertRaises(AttributeError):
2156 sig.foo = 'bar'
2157
2158 with self.assertRaises(TypeError):
2159 sig.parameters['a'] = None
2160
2161 def test_signature_on_noarg(self):
2162 def test():
2163 pass
2164 self.assertEqual(self.signature(test), ((), ...))
2165
2166 def test_signature_on_wargs(self):
2167 def test(a, b:'foo') -> 123:
2168 pass
2169 self.assertEqual(self.signature(test),
2170 ((('a', ..., ..., "positional_or_keyword"),
2171 ('b', ..., 'foo', "positional_or_keyword")),
2172 123))
2173
2174 def test_signature_on_wkwonly(self):
2175 def test(*, a:float, b:str) -> int:
2176 pass
2177 self.assertEqual(self.signature(test),
2178 ((('a', ..., float, "keyword_only"),
2179 ('b', ..., str, "keyword_only")),
2180 int))
2181
2182 def test_signature_on_complex_args(self):
2183 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2184 pass
2185 self.assertEqual(self.signature(test),
2186 ((('a', ..., ..., "positional_or_keyword"),
2187 ('b', 10, 'foo', "positional_or_keyword"),
2188 ('args', ..., 'bar', "var_positional"),
2189 ('spam', ..., 'baz', "keyword_only"),
2190 ('ham', 123, ..., "keyword_only"),
2191 ('kwargs', ..., int, "var_keyword")),
2192 ...))
2193
Dong-hee Na378d7062017-05-18 04:00:51 +09002194 def test_signature_without_self(self):
2195 def test_args_only(*args): # NOQA
2196 pass
2197
2198 def test_args_kwargs_only(*args, **kwargs): # NOQA
2199 pass
2200
2201 class A:
2202 @classmethod
2203 def test_classmethod(*args): # NOQA
2204 pass
2205
2206 @staticmethod
2207 def test_staticmethod(*args): # NOQA
2208 pass
2209
2210 f1 = functools.partialmethod((test_classmethod), 1)
2211 f2 = functools.partialmethod((test_args_only), 1)
2212 f3 = functools.partialmethod((test_staticmethod), 1)
2213 f4 = functools.partialmethod((test_args_kwargs_only),1)
2214
2215 self.assertEqual(self.signature(test_args_only),
2216 ((('args', ..., ..., 'var_positional'),), ...))
2217 self.assertEqual(self.signature(test_args_kwargs_only),
2218 ((('args', ..., ..., 'var_positional'),
2219 ('kwargs', ..., ..., 'var_keyword')), ...))
2220 self.assertEqual(self.signature(A.f1),
2221 ((('args', ..., ..., 'var_positional'),), ...))
2222 self.assertEqual(self.signature(A.f2),
2223 ((('args', ..., ..., 'var_positional'),), ...))
2224 self.assertEqual(self.signature(A.f3),
2225 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002226 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002227 ((('args', ..., ..., 'var_positional'),
2228 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002229 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002230 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2231 "Signature information for builtins requires docstrings")
2232 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002233 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002234
Larry Hastings5c661892014-01-24 06:17:25 -08002235 def test_unbound_method(o):
2236 """Use this to test unbound methods (things that should have a self)"""
2237 signature = inspect.signature(o)
2238 self.assertTrue(isinstance(signature, inspect.Signature))
2239 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2240 return signature
2241
2242 def test_callable(o):
2243 """Use this to test bound methods or normal callables (things that don't expect self)"""
2244 signature = inspect.signature(o)
2245 self.assertTrue(isinstance(signature, inspect.Signature))
2246 if signature.parameters:
2247 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2248 return signature
2249
2250 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002251 def p(name): return signature.parameters[name].default
2252 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002253 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002254 self.assertEqual(p('d'), 3.14)
2255 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002256 self.assertEqual(p('n'), None)
2257 self.assertEqual(p('t'), True)
2258 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002259 self.assertEqual(p('local'), 3)
2260 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002261 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002262
Larry Hastings5c661892014-01-24 06:17:25 -08002263 test_callable(object)
2264
2265 # normal method
2266 # (PyMethodDescr_Type, "method_descriptor")
2267 test_unbound_method(_pickle.Pickler.dump)
2268 d = _pickle.Pickler(io.StringIO())
2269 test_callable(d.dump)
2270
2271 # static method
2272 test_callable(str.maketrans)
2273 test_callable('abc'.maketrans)
2274
2275 # class method
2276 test_callable(dict.fromkeys)
2277 test_callable({}.fromkeys)
2278
2279 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2280 test_unbound_method(type.__call__)
2281 test_unbound_method(int.__add__)
2282 test_callable((3).__add__)
2283
2284 # _PyMethodWrapper_Type
2285 # support for 'method-wrapper'
2286 test_callable(min.__call__)
2287
Larry Hastings2623c8c2014-02-08 22:15:29 -08002288 # This doesn't work now.
2289 # (We don't have a valid signature for "type" in 3.4)
2290 with self.assertRaisesRegex(ValueError, "no signature found"):
2291 class ThisWorksNow:
2292 __call__ = type
2293 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002294
Yury Selivanov056e2652014-03-02 12:25:27 -05002295 # Regression test for issue #20786
2296 test_unbound_method(dict.__delitem__)
2297 test_unbound_method(property.__delete__)
2298
Zachary Ware8ef887c2015-04-13 18:22:35 -05002299 # Regression test for issue #20586
2300 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2301
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002302 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002303 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2304 "Signature information for builtins requires docstrings")
2305 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002306 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002307 func = _testcapi.docstring_with_signature_with_defaults
2308
2309 def decorator(func):
2310 @functools.wraps(func)
2311 def wrapper(*args, **kwargs) -> int:
2312 return func(*args, **kwargs)
2313 return wrapper
2314
2315 decorated_func = decorator(func)
2316
2317 self.assertEqual(inspect.signature(func),
2318 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002319
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002320 def wrapper_like(*args, **kwargs) -> int: pass
2321 self.assertEqual(inspect.signature(decorated_func,
2322 follow_wrapped=False),
2323 inspect.signature(wrapper_like))
2324
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002325 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002326 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002327 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002328 with self.assertRaisesRegex(ValueError,
2329 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002330 inspect.signature(_testcapi.docstring_no_signature)
2331
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002332 with self.assertRaisesRegex(ValueError,
2333 'no signature found for builtin'):
2334 inspect.signature(str)
2335
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002336 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002337 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002338 inspect.signature(42)
2339
Yury Selivanov63da7c72014-01-31 14:48:37 -05002340 def test_signature_from_functionlike_object(self):
2341 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2342 pass
2343
2344 class funclike:
2345 # Has to be callable, and have correct
2346 # __code__, __annotations__, __defaults__, __name__,
2347 # and __kwdefaults__ attributes
2348
2349 def __init__(self, func):
2350 self.__name__ = func.__name__
2351 self.__code__ = func.__code__
2352 self.__annotations__ = func.__annotations__
2353 self.__defaults__ = func.__defaults__
2354 self.__kwdefaults__ = func.__kwdefaults__
2355 self.func = func
2356
2357 def __call__(self, *args, **kwargs):
2358 return self.func(*args, **kwargs)
2359
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002360 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002361
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002362 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002363 self.assertEqual(sig_funclike, sig_func)
2364
2365 sig_funclike = inspect.signature(funclike(func))
2366 self.assertEqual(sig_funclike, sig_func)
2367
2368 # If object is not a duck type of function, then
2369 # signature will try to get a signature for its '__call__'
2370 # method
2371 fl = funclike(func)
2372 del fl.__defaults__
2373 self.assertEqual(self.signature(fl),
2374 ((('args', ..., ..., "var_positional"),
2375 ('kwargs', ..., ..., "var_keyword")),
2376 ...))
2377
Yury Selivanova773de02014-02-21 18:30:53 -05002378 # Test with cython-like builtins:
2379 _orig_isdesc = inspect.ismethoddescriptor
2380 def _isdesc(obj):
2381 if hasattr(obj, '_builtinmock'):
2382 return True
2383 return _orig_isdesc(obj)
2384
2385 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2386 builtin_func = funclike(func)
2387 # Make sure that our mock setup is working
2388 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2389 builtin_func._builtinmock = True
2390 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2391 self.assertEqual(inspect.signature(builtin_func), sig_func)
2392
Yury Selivanov63da7c72014-01-31 14:48:37 -05002393 def test_signature_functionlike_class(self):
2394 # We only want to duck type function-like objects,
2395 # not classes.
2396
2397 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2398 pass
2399
2400 class funclike:
2401 def __init__(self, marker):
2402 pass
2403
2404 __name__ = func.__name__
2405 __code__ = func.__code__
2406 __annotations__ = func.__annotations__
2407 __defaults__ = func.__defaults__
2408 __kwdefaults__ = func.__kwdefaults__
2409
Yury Selivanov63da7c72014-01-31 14:48:37 -05002410 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2411
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002412 def test_signature_on_method(self):
2413 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002414 def __init__(*args):
2415 pass
2416 def m1(self, arg1, arg2=1) -> int:
2417 pass
2418 def m2(*args):
2419 pass
2420 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002421 pass
2422
Yury Selivanov62560fb2014-01-28 12:26:24 -05002423 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002424 ((('arg1', ..., ..., "positional_or_keyword"),
2425 ('arg2', 1, ..., "positional_or_keyword")),
2426 int))
2427
Yury Selivanov62560fb2014-01-28 12:26:24 -05002428 self.assertEqual(self.signature(Test().m2),
2429 ((('args', ..., ..., "var_positional"),),
2430 ...))
2431
2432 self.assertEqual(self.signature(Test),
2433 ((('args', ..., ..., "var_positional"),),
2434 ...))
2435
2436 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2437 self.signature(Test())
2438
Yury Selivanov46c759d2015-05-27 21:56:53 -04002439 def test_signature_wrapped_bound_method(self):
2440 # Issue 24298
2441 class Test:
2442 def m1(self, arg1, arg2=1) -> int:
2443 pass
2444 @functools.wraps(Test().m1)
2445 def m1d(*args, **kwargs):
2446 pass
2447 self.assertEqual(self.signature(m1d),
2448 ((('arg1', ..., ..., "positional_or_keyword"),
2449 ('arg2', 1, ..., "positional_or_keyword")),
2450 int))
2451
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002452 def test_signature_on_classmethod(self):
2453 class Test:
2454 @classmethod
2455 def foo(cls, arg1, *, arg2=1):
2456 pass
2457
2458 meth = Test().foo
2459 self.assertEqual(self.signature(meth),
2460 ((('arg1', ..., ..., "positional_or_keyword"),
2461 ('arg2', 1, ..., "keyword_only")),
2462 ...))
2463
2464 meth = Test.foo
2465 self.assertEqual(self.signature(meth),
2466 ((('arg1', ..., ..., "positional_or_keyword"),
2467 ('arg2', 1, ..., "keyword_only")),
2468 ...))
2469
2470 def test_signature_on_staticmethod(self):
2471 class Test:
2472 @staticmethod
2473 def foo(cls, *, arg):
2474 pass
2475
2476 meth = Test().foo
2477 self.assertEqual(self.signature(meth),
2478 ((('cls', ..., ..., "positional_or_keyword"),
2479 ('arg', ..., ..., "keyword_only")),
2480 ...))
2481
2482 meth = Test.foo
2483 self.assertEqual(self.signature(meth),
2484 ((('cls', ..., ..., "positional_or_keyword"),
2485 ('arg', ..., ..., "keyword_only")),
2486 ...))
2487
2488 def test_signature_on_partial(self):
2489 from functools import partial
2490
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002491 Parameter = inspect.Parameter
2492
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002493 def test():
2494 pass
2495
2496 self.assertEqual(self.signature(partial(test)), ((), ...))
2497
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002498 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002499 inspect.signature(partial(test, 1))
2500
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002501 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002502 inspect.signature(partial(test, a=1))
2503
2504 def test(a, b, *, c, d):
2505 pass
2506
2507 self.assertEqual(self.signature(partial(test)),
2508 ((('a', ..., ..., "positional_or_keyword"),
2509 ('b', ..., ..., "positional_or_keyword"),
2510 ('c', ..., ..., "keyword_only"),
2511 ('d', ..., ..., "keyword_only")),
2512 ...))
2513
2514 self.assertEqual(self.signature(partial(test, 1)),
2515 ((('b', ..., ..., "positional_or_keyword"),
2516 ('c', ..., ..., "keyword_only"),
2517 ('d', ..., ..., "keyword_only")),
2518 ...))
2519
2520 self.assertEqual(self.signature(partial(test, 1, c=2)),
2521 ((('b', ..., ..., "positional_or_keyword"),
2522 ('c', 2, ..., "keyword_only"),
2523 ('d', ..., ..., "keyword_only")),
2524 ...))
2525
2526 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2527 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002528 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002529 ('c', 2, ..., "keyword_only"),
2530 ('d', ..., ..., "keyword_only")),
2531 ...))
2532
2533 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002534 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002535 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002536 ('d', ..., ..., "keyword_only")),
2537 ...))
2538
2539 self.assertEqual(self.signature(partial(test, a=1)),
2540 ((('a', 1, ..., "keyword_only"),
2541 ('b', ..., ..., "keyword_only"),
2542 ('c', ..., ..., "keyword_only"),
2543 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002544 ...))
2545
2546 def test(a, *args, b, **kwargs):
2547 pass
2548
2549 self.assertEqual(self.signature(partial(test, 1)),
2550 ((('args', ..., ..., "var_positional"),
2551 ('b', ..., ..., "keyword_only"),
2552 ('kwargs', ..., ..., "var_keyword")),
2553 ...))
2554
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002555 self.assertEqual(self.signature(partial(test, a=1)),
2556 ((('a', 1, ..., "keyword_only"),
2557 ('b', ..., ..., "keyword_only"),
2558 ('kwargs', ..., ..., "var_keyword")),
2559 ...))
2560
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002561 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2562 ((('args', ..., ..., "var_positional"),
2563 ('b', ..., ..., "keyword_only"),
2564 ('kwargs', ..., ..., "var_keyword")),
2565 ...))
2566
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002567 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2568 ((('args', ..., ..., "var_positional"),
2569 ('b', ..., ..., "keyword_only"),
2570 ('kwargs', ..., ..., "var_keyword")),
2571 ...))
2572
2573 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2574 ((('args', ..., ..., "var_positional"),
2575 ('b', 0, ..., "keyword_only"),
2576 ('kwargs', ..., ..., "var_keyword")),
2577 ...))
2578
2579 self.assertEqual(self.signature(partial(test, b=0)),
2580 ((('a', ..., ..., "positional_or_keyword"),
2581 ('args', ..., ..., "var_positional"),
2582 ('b', 0, ..., "keyword_only"),
2583 ('kwargs', ..., ..., "var_keyword")),
2584 ...))
2585
2586 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2587 ((('a', ..., ..., "positional_or_keyword"),
2588 ('args', ..., ..., "var_positional"),
2589 ('b', 0, ..., "keyword_only"),
2590 ('kwargs', ..., ..., "var_keyword")),
2591 ...))
2592
2593 def test(a, b, c:int) -> 42:
2594 pass
2595
2596 sig = test.__signature__ = inspect.signature(test)
2597
2598 self.assertEqual(self.signature(partial(partial(test, 1))),
2599 ((('b', ..., ..., "positional_or_keyword"),
2600 ('c', ..., int, "positional_or_keyword")),
2601 42))
2602
2603 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2604 ((('c', ..., int, "positional_or_keyword"),),
2605 42))
2606
2607 psig = inspect.signature(partial(partial(test, 1), 2))
2608
2609 def foo(a):
2610 return a
2611 _foo = partial(partial(foo, a=10), a=20)
2612 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002613 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002614 ...))
2615 # check that we don't have any side-effects in signature(),
2616 # and the partial object is still functioning
2617 self.assertEqual(_foo(), 20)
2618
2619 def foo(a, b, c):
2620 return a, b, c
2621 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002622
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002623 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002624 ((('b', 30, ..., "keyword_only"),
2625 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002626 ...))
2627 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002628
2629 def foo(a, b, c, *, d):
2630 return a, b, c, d
2631 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2632 self.assertEqual(self.signature(_foo),
2633 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002634 ('b', 10, ..., "keyword_only"),
2635 ('c', 20, ..., "keyword_only"),
2636 ('d', 30, ..., "keyword_only"),
2637 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002638 ...))
2639 ba = inspect.signature(_foo).bind(a=200, b=11)
2640 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2641
2642 def foo(a=1, b=2, c=3):
2643 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002644 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2645
2646 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002647 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002648
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002649 ba = inspect.signature(_foo).bind(11, 12)
2650 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002651
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002652 ba = inspect.signature(_foo).bind(11, b=12)
2653 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002654
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002655 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002656 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2657
2658 _foo = partial(_foo, b=10, c=20)
2659 ba = inspect.signature(_foo).bind(12)
2660 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2661
2662
2663 def foo(a, b, c, d, **kwargs):
2664 pass
2665 sig = inspect.signature(foo)
2666 params = sig.parameters.copy()
2667 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2668 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2669 foo.__signature__ = inspect.Signature(params.values())
2670 sig = inspect.signature(foo)
2671 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2672
2673 self.assertEqual(self.signature(partial(foo, 1)),
2674 ((('b', ..., ..., 'positional_only'),
2675 ('c', ..., ..., 'positional_or_keyword'),
2676 ('d', ..., ..., 'positional_or_keyword'),
2677 ('kwargs', ..., ..., 'var_keyword')),
2678 ...))
2679
2680 self.assertEqual(self.signature(partial(foo, 1, 2)),
2681 ((('c', ..., ..., 'positional_or_keyword'),
2682 ('d', ..., ..., 'positional_or_keyword'),
2683 ('kwargs', ..., ..., 'var_keyword')),
2684 ...))
2685
2686 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2687 ((('d', ..., ..., 'positional_or_keyword'),
2688 ('kwargs', ..., ..., 'var_keyword')),
2689 ...))
2690
2691 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2692 ((('c', 3, ..., 'keyword_only'),
2693 ('d', ..., ..., 'keyword_only'),
2694 ('kwargs', ..., ..., 'var_keyword')),
2695 ...))
2696
2697 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2698 ((('b', ..., ..., 'positional_only'),
2699 ('c', 3, ..., 'keyword_only'),
2700 ('d', ..., ..., 'keyword_only'),
2701 ('kwargs', ..., ..., 'var_keyword')),
2702 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002703
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002704 def test_signature_on_partialmethod(self):
2705 from functools import partialmethod
2706
2707 class Spam:
2708 def test():
2709 pass
2710 ham = partialmethod(test)
2711
2712 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2713 inspect.signature(Spam.ham)
2714
2715 class Spam:
2716 def test(it, a, *, c) -> 'spam':
2717 pass
2718 ham = partialmethod(test, c=1)
2719
2720 self.assertEqual(self.signature(Spam.ham),
2721 ((('it', ..., ..., 'positional_or_keyword'),
2722 ('a', ..., ..., 'positional_or_keyword'),
2723 ('c', 1, ..., 'keyword_only')),
2724 'spam'))
2725
2726 self.assertEqual(self.signature(Spam().ham),
2727 ((('a', ..., ..., 'positional_or_keyword'),
2728 ('c', 1, ..., 'keyword_only')),
2729 'spam'))
2730
Yury Selivanov8a387212018-03-06 12:59:45 -05002731 class Spam:
2732 def test(self: 'anno', x):
2733 pass
2734
2735 g = partialmethod(test, 1)
2736
2737 self.assertEqual(self.signature(Spam.g),
2738 ((('self', ..., 'anno', 'positional_or_keyword'),),
2739 ...))
2740
Yury Selivanov0486f812014-01-29 12:18:59 -05002741 def test_signature_on_fake_partialmethod(self):
2742 def foo(a): pass
2743 foo._partialmethod = 'spam'
2744 self.assertEqual(str(inspect.signature(foo)), '(a)')
2745
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002746 def test_signature_on_decorated(self):
2747 import functools
2748
2749 def decorator(func):
2750 @functools.wraps(func)
2751 def wrapper(*args, **kwargs) -> int:
2752 return func(*args, **kwargs)
2753 return wrapper
2754
2755 class Foo:
2756 @decorator
2757 def bar(self, a, b):
2758 pass
2759
2760 self.assertEqual(self.signature(Foo.bar),
2761 ((('self', ..., ..., "positional_or_keyword"),
2762 ('a', ..., ..., "positional_or_keyword"),
2763 ('b', ..., ..., "positional_or_keyword")),
2764 ...))
2765
2766 self.assertEqual(self.signature(Foo().bar),
2767 ((('a', ..., ..., "positional_or_keyword"),
2768 ('b', ..., ..., "positional_or_keyword")),
2769 ...))
2770
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002771 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2772 ((('args', ..., ..., "var_positional"),
2773 ('kwargs', ..., ..., "var_keyword")),
2774 ...)) # functools.wraps will copy __annotations__
2775 # from "func" to "wrapper", hence no
2776 # return_annotation
2777
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002778 # Test that we handle method wrappers correctly
2779 def decorator(func):
2780 @functools.wraps(func)
2781 def wrapper(*args, **kwargs) -> int:
2782 return func(42, *args, **kwargs)
2783 sig = inspect.signature(func)
2784 new_params = tuple(sig.parameters.values())[1:]
2785 wrapper.__signature__ = sig.replace(parameters=new_params)
2786 return wrapper
2787
2788 class Foo:
2789 @decorator
2790 def __call__(self, a, b):
2791 pass
2792
2793 self.assertEqual(self.signature(Foo.__call__),
2794 ((('a', ..., ..., "positional_or_keyword"),
2795 ('b', ..., ..., "positional_or_keyword")),
2796 ...))
2797
2798 self.assertEqual(self.signature(Foo().__call__),
2799 ((('b', ..., ..., "positional_or_keyword"),),
2800 ...))
2801
Nick Coghlane8c45d62013-07-28 20:00:01 +10002802 # Test we handle __signature__ partway down the wrapper stack
2803 def wrapped_foo_call():
2804 pass
2805 wrapped_foo_call.__wrapped__ = Foo.__call__
2806
2807 self.assertEqual(self.signature(wrapped_foo_call),
2808 ((('a', ..., ..., "positional_or_keyword"),
2809 ('b', ..., ..., "positional_or_keyword")),
2810 ...))
2811
2812
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002813 def test_signature_on_class(self):
2814 class C:
2815 def __init__(self, a):
2816 pass
2817
2818 self.assertEqual(self.signature(C),
2819 ((('a', ..., ..., "positional_or_keyword"),),
2820 ...))
2821
2822 class CM(type):
2823 def __call__(cls, a):
2824 pass
2825 class C(metaclass=CM):
2826 def __init__(self, b):
2827 pass
2828
2829 self.assertEqual(self.signature(C),
2830 ((('a', ..., ..., "positional_or_keyword"),),
2831 ...))
2832
2833 class CM(type):
2834 def __new__(mcls, name, bases, dct, *, foo=1):
2835 return super().__new__(mcls, name, bases, dct)
2836 class C(metaclass=CM):
2837 def __init__(self, b):
2838 pass
2839
2840 self.assertEqual(self.signature(C),
2841 ((('b', ..., ..., "positional_or_keyword"),),
2842 ...))
2843
2844 self.assertEqual(self.signature(CM),
2845 ((('name', ..., ..., "positional_or_keyword"),
2846 ('bases', ..., ..., "positional_or_keyword"),
2847 ('dct', ..., ..., "positional_or_keyword"),
2848 ('foo', 1, ..., "keyword_only")),
2849 ...))
2850
2851 class CMM(type):
2852 def __new__(mcls, name, bases, dct, *, foo=1):
2853 return super().__new__(mcls, name, bases, dct)
2854 def __call__(cls, nm, bs, dt):
2855 return type(nm, bs, dt)
2856 class CM(type, metaclass=CMM):
2857 def __new__(mcls, name, bases, dct, *, bar=2):
2858 return super().__new__(mcls, name, bases, dct)
2859 class C(metaclass=CM):
2860 def __init__(self, b):
2861 pass
2862
2863 self.assertEqual(self.signature(CMM),
2864 ((('name', ..., ..., "positional_or_keyword"),
2865 ('bases', ..., ..., "positional_or_keyword"),
2866 ('dct', ..., ..., "positional_or_keyword"),
2867 ('foo', 1, ..., "keyword_only")),
2868 ...))
2869
2870 self.assertEqual(self.signature(CM),
2871 ((('nm', ..., ..., "positional_or_keyword"),
2872 ('bs', ..., ..., "positional_or_keyword"),
2873 ('dt', ..., ..., "positional_or_keyword")),
2874 ...))
2875
2876 self.assertEqual(self.signature(C),
2877 ((('b', ..., ..., "positional_or_keyword"),),
2878 ...))
2879
2880 class CM(type):
2881 def __init__(cls, name, bases, dct, *, bar=2):
2882 return super().__init__(name, bases, dct)
2883 class C(metaclass=CM):
2884 def __init__(self, b):
2885 pass
2886
2887 self.assertEqual(self.signature(CM),
2888 ((('name', ..., ..., "positional_or_keyword"),
2889 ('bases', ..., ..., "positional_or_keyword"),
2890 ('dct', ..., ..., "positional_or_keyword"),
2891 ('bar', 2, ..., "keyword_only")),
2892 ...))
2893
Yury Selivanov145dff82014-02-01 13:49:29 -05002894 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2895 "Signature information for builtins requires docstrings")
2896 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002897 # Test classes without user-defined __init__ or __new__
2898 class C: pass
2899 self.assertEqual(str(inspect.signature(C)), '()')
2900 class D(C): pass
2901 self.assertEqual(str(inspect.signature(D)), '()')
2902
2903 # Test meta-classes without user-defined __init__ or __new__
2904 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002905 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002906 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2907 self.assertEqual(inspect.signature(C), None)
2908 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2909 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002910
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002911 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2912 "Signature information for builtins requires docstrings")
2913 def test_signature_on_builtin_class(self):
Antoine Pitrou91f43802019-05-26 17:10:09 +02002914 expected = ('(file, protocol=None, fix_imports=True, '
2915 'buffer_callback=None)')
2916 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002917
2918 class P(_pickle.Pickler): pass
2919 class EmptyTrait: pass
2920 class P2(EmptyTrait, P): pass
Antoine Pitrou91f43802019-05-26 17:10:09 +02002921 self.assertEqual(str(inspect.signature(P)), expected)
2922 self.assertEqual(str(inspect.signature(P2)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002923
2924 class P3(P2):
2925 def __init__(self, spam):
2926 pass
2927 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2928
2929 class MetaP(type):
2930 def __call__(cls, foo, bar):
2931 pass
2932 class P4(P2, metaclass=MetaP):
2933 pass
2934 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2935
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002936 def test_signature_on_callable_objects(self):
2937 class Foo:
2938 def __call__(self, a):
2939 pass
2940
2941 self.assertEqual(self.signature(Foo()),
2942 ((('a', ..., ..., "positional_or_keyword"),),
2943 ...))
2944
2945 class Spam:
2946 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002947 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002948 inspect.signature(Spam())
2949
2950 class Bar(Spam, Foo):
2951 pass
2952
2953 self.assertEqual(self.signature(Bar()),
2954 ((('a', ..., ..., "positional_or_keyword"),),
2955 ...))
2956
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002957 class Wrapped:
2958 pass
2959 Wrapped.__wrapped__ = lambda a: None
2960 self.assertEqual(self.signature(Wrapped),
2961 ((('a', ..., ..., "positional_or_keyword"),),
2962 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002963 # wrapper loop:
2964 Wrapped.__wrapped__ = Wrapped
2965 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2966 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002967
2968 def test_signature_on_lambdas(self):
2969 self.assertEqual(self.signature((lambda a=10: a)),
2970 ((('a', 10, ..., "positional_or_keyword"),),
2971 ...))
2972
2973 def test_signature_equality(self):
2974 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002975 self.assertFalse(inspect.signature(foo) == 42)
2976 self.assertTrue(inspect.signature(foo) != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03002977 self.assertTrue(inspect.signature(foo) == ALWAYS_EQ)
2978 self.assertFalse(inspect.signature(foo) != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002979
2980 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002981 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2982 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002983 self.assertEqual(
2984 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002985
2986 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002987 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2988 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002989 self.assertNotEqual(
2990 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002991
2992 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002993 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2994 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002995 self.assertNotEqual(
2996 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002997
2998 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002999 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3000 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003001 self.assertNotEqual(
3002 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003003
3004 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003005 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3006 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003007 self.assertNotEqual(
3008 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003009
3010 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003011 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3012 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003013 self.assertNotEqual(
3014 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003015 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003016 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3017 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003018 self.assertNotEqual(
3019 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003020
3021 def foo(*, a, b, c): pass
3022 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003023 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3024 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003025 self.assertEqual(
3026 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003027
3028 def foo(*, a=1, b, c): pass
3029 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003030 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3031 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003032 self.assertEqual(
3033 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003034
3035 def foo(pos, *, a=1, b, c): pass
3036 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003037 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3038 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003039 self.assertEqual(
3040 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003041
3042 def foo(pos, *, a, b, c): pass
3043 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003044 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3045 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003046 self.assertNotEqual(
3047 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003048
3049 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3050 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003051 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3052 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003053 self.assertEqual(
3054 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003055
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003056 def test_signature_hashable(self):
3057 S = inspect.Signature
3058 P = inspect.Parameter
3059
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003060 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003061 foo_sig = inspect.signature(foo)
3062
3063 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3064
3065 self.assertEqual(hash(foo_sig), hash(manual_sig))
3066 self.assertNotEqual(hash(foo_sig),
3067 hash(manual_sig.replace(return_annotation='spam')))
3068
3069 def bar(a) -> 1: pass
3070 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3071
3072 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003073 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003074 hash(inspect.signature(foo))
3075
3076 def foo(a) -> {}: pass
3077 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3078 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003079
3080 def test_signature_str(self):
3081 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3082 pass
3083 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003084 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003085
3086 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3087 pass
3088 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003089 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003090
3091 def foo():
3092 pass
3093 self.assertEqual(str(inspect.signature(foo)), '()')
3094
3095 def test_signature_str_positional_only(self):
3096 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003097 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003098
3099 def test(a_po, *, b, **kwargs):
3100 return a_po, kwargs
3101
3102 sig = inspect.signature(test)
3103 new_params = list(sig.parameters.values())
3104 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3105 test.__signature__ = sig.replace(parameters=new_params)
3106
3107 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003108 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003109
Yury Selivanov2393dca2014-01-27 15:07:58 -05003110 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3111 '(foo, /)')
3112
3113 self.assertEqual(str(S(parameters=[
3114 P('foo', P.POSITIONAL_ONLY),
3115 P('bar', P.VAR_KEYWORD)])),
3116 '(foo, /, **bar)')
3117
3118 self.assertEqual(str(S(parameters=[
3119 P('foo', P.POSITIONAL_ONLY),
3120 P('bar', P.VAR_POSITIONAL)])),
3121 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003122
3123 def test_signature_replace_anno(self):
3124 def test() -> 42:
3125 pass
3126
3127 sig = inspect.signature(test)
3128 sig = sig.replace(return_annotation=None)
3129 self.assertIs(sig.return_annotation, None)
3130 sig = sig.replace(return_annotation=sig.empty)
3131 self.assertIs(sig.return_annotation, sig.empty)
3132 sig = sig.replace(return_annotation=42)
3133 self.assertEqual(sig.return_annotation, 42)
3134 self.assertEqual(sig, inspect.signature(test))
3135
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003136 def test_signature_on_mangled_parameters(self):
3137 class Spam:
3138 def foo(self, __p1:1=2, *, __p2:2=3):
3139 pass
3140 class Ham(Spam):
3141 pass
3142
3143 self.assertEqual(self.signature(Spam.foo),
3144 ((('self', ..., ..., "positional_or_keyword"),
3145 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3146 ('_Spam__p2', 3, 2, "keyword_only")),
3147 ...))
3148
3149 self.assertEqual(self.signature(Spam.foo),
3150 self.signature(Ham.foo))
3151
Yury Selivanovda396452014-03-27 12:09:24 -04003152 def test_signature_from_callable_python_obj(self):
3153 class MySignature(inspect.Signature): pass
3154 def foo(a, *, b:1): pass
3155 foo_sig = MySignature.from_callable(foo)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003156 self.assertIsInstance(foo_sig, MySignature)
3157
3158 def test_signature_from_callable_class(self):
3159 # A regression test for a class inheriting its signature from `object`.
3160 class MySignature(inspect.Signature): pass
3161 class foo: pass
3162 foo_sig = MySignature.from_callable(foo)
3163 self.assertIsInstance(foo_sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003164
3165 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3166 "Signature information for builtins requires docstrings")
3167 def test_signature_from_callable_builtin_obj(self):
3168 class MySignature(inspect.Signature): pass
3169 sig = MySignature.from_callable(_pickle.Pickler)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003170 self.assertIsInstance(sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003171
larryhastingsf36ba122018-01-28 11:13:09 -08003172 def test_signature_definition_order_preserved_on_kwonly(self):
3173 for fn in signatures_with_lexicographic_keyword_only_parameters():
3174 signature = inspect.signature(fn)
3175 l = list(signature.parameters)
3176 sorted_l = sorted(l)
3177 self.assertTrue(l)
3178 self.assertEqual(l, sorted_l)
3179 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3180 l = list(signature.parameters)
3181 self.assertEqual(l, unsorted_keyword_only_parameters)
3182
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003183
3184class TestParameterObject(unittest.TestCase):
3185 def test_signature_parameter_kinds(self):
3186 P = inspect.Parameter
3187 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3188 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3189
3190 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3191 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3192
3193 def test_signature_parameter_object(self):
3194 p = inspect.Parameter('foo', default=10,
3195 kind=inspect.Parameter.POSITIONAL_ONLY)
3196 self.assertEqual(p.name, 'foo')
3197 self.assertEqual(p.default, 10)
3198 self.assertIs(p.annotation, p.empty)
3199 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3200
Dong-hee Naa9cab432018-05-30 00:04:08 +09003201 with self.assertRaisesRegex(ValueError, "value '123' is "
3202 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003203 inspect.Parameter('foo', default=10, kind='123')
3204
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003205 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003206 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3207
Yury Selivanov2393dca2014-01-27 15:07:58 -05003208 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003209 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3210
Yury Selivanov2393dca2014-01-27 15:07:58 -05003211 with self.assertRaisesRegex(ValueError,
3212 'is not a valid parameter name'):
3213 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3214
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003215 with self.assertRaisesRegex(ValueError,
3216 'is not a valid parameter name'):
3217 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3218
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003219 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003220 inspect.Parameter('a', default=42,
3221 kind=inspect.Parameter.VAR_KEYWORD)
3222
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003223 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003224 inspect.Parameter('a', default=42,
3225 kind=inspect.Parameter.VAR_POSITIONAL)
3226
3227 p = inspect.Parameter('a', default=42,
3228 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003229 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003230 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3231
3232 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003233 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003234
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003235 def test_signature_parameter_hashable(self):
3236 P = inspect.Parameter
3237 foo = P('foo', kind=P.POSITIONAL_ONLY)
3238 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3239 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3240 default=42)))
3241 self.assertNotEqual(hash(foo),
3242 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3243
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003244 def test_signature_parameter_equality(self):
3245 P = inspect.Parameter
3246 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3247
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003248 self.assertTrue(p == p)
3249 self.assertFalse(p != p)
3250 self.assertFalse(p == 42)
3251 self.assertTrue(p != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003252 self.assertTrue(p == ALWAYS_EQ)
3253 self.assertFalse(p != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003254
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003255 self.assertTrue(p == P('foo', default=42,
3256 kind=inspect.Parameter.KEYWORD_ONLY))
3257 self.assertFalse(p != P('foo', default=42,
3258 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003259
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003260 def test_signature_parameter_replace(self):
3261 p = inspect.Parameter('foo', default=42,
3262 kind=inspect.Parameter.KEYWORD_ONLY)
3263
3264 self.assertIsNot(p, p.replace())
3265 self.assertEqual(p, p.replace())
3266
3267 p2 = p.replace(annotation=1)
3268 self.assertEqual(p2.annotation, 1)
3269 p2 = p2.replace(annotation=p2.empty)
3270 self.assertEqual(p, p2)
3271
3272 p2 = p2.replace(name='bar')
3273 self.assertEqual(p2.name, 'bar')
3274 self.assertNotEqual(p2, p)
3275
Yury Selivanov2393dca2014-01-27 15:07:58 -05003276 with self.assertRaisesRegex(ValueError,
3277 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003278 p2 = p2.replace(name=p2.empty)
3279
3280 p2 = p2.replace(name='foo', default=None)
3281 self.assertIs(p2.default, None)
3282 self.assertNotEqual(p2, p)
3283
3284 p2 = p2.replace(name='foo', default=p2.empty)
3285 self.assertIs(p2.default, p2.empty)
3286
3287
3288 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3289 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3290 self.assertNotEqual(p2, p)
3291
Dong-hee Naa9cab432018-05-30 00:04:08 +09003292 with self.assertRaisesRegex(ValueError,
3293 "value <class 'inspect._empty'> "
3294 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003295 p2 = p2.replace(kind=p2.empty)
3296
3297 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3298 self.assertEqual(p2, p)
3299
3300 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003301 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3302 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003303
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003304 @cpython_only
3305 def test_signature_parameter_implicit(self):
3306 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003307 'implicit arguments must be passed as '
3308 'positional or keyword arguments, '
3309 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003310 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3311
3312 param = inspect.Parameter(
3313 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3314 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3315 self.assertEqual(param.name, 'implicit0')
3316
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003317 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003318 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003319
3320 with self.assertRaises(AttributeError):
3321 p.foo = 'bar'
3322
3323 with self.assertRaises(AttributeError):
3324 p.kind = 123
3325
3326
3327class TestSignatureBind(unittest.TestCase):
3328 @staticmethod
3329 def call(func, *args, **kwargs):
3330 sig = inspect.signature(func)
3331 ba = sig.bind(*args, **kwargs)
3332 return func(*ba.args, **ba.kwargs)
3333
3334 def test_signature_bind_empty(self):
3335 def test():
3336 return 42
3337
3338 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003339 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003340 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003341 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003342 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003343 with self.assertRaisesRegex(
3344 TypeError, "got an unexpected keyword argument 'spam'"):
3345
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003346 self.call(test, spam=1)
3347
3348 def test_signature_bind_var(self):
3349 def test(*args, **kwargs):
3350 return args, kwargs
3351
3352 self.assertEqual(self.call(test), ((), {}))
3353 self.assertEqual(self.call(test, 1), ((1,), {}))
3354 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3355 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3356 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3357 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3358 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3359 ((1, 2), {'foo': 'bar'}))
3360
3361 def test_signature_bind_just_args(self):
3362 def test(a, b, c):
3363 return a, b, c
3364
3365 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3366
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003367 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003368 self.call(test, 1, 2, 3, 4)
3369
Yury Selivanov86872752015-05-19 00:27:49 -04003370 with self.assertRaisesRegex(TypeError,
3371 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003372 self.call(test, 1)
3373
Yury Selivanov86872752015-05-19 00:27:49 -04003374 with self.assertRaisesRegex(TypeError,
3375 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003376 self.call(test)
3377
3378 def test(a, b, c=10):
3379 return a, b, c
3380 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3381 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3382
3383 def test(a=1, b=2, c=3):
3384 return a, b, c
3385 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3386 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3387 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3388
3389 def test_signature_bind_varargs_order(self):
3390 def test(*args):
3391 return args
3392
3393 self.assertEqual(self.call(test), ())
3394 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3395
3396 def test_signature_bind_args_and_varargs(self):
3397 def test(a, b, c=3, *args):
3398 return a, b, c, args
3399
3400 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3401 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3402 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3403 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3404
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003405 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003406 "multiple values for argument 'c'"):
3407 self.call(test, 1, 2, 3, c=4)
3408
3409 def test_signature_bind_just_kwargs(self):
3410 def test(**kwargs):
3411 return kwargs
3412
3413 self.assertEqual(self.call(test), {})
3414 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3415 {'foo': 'bar', 'spam': 'ham'})
3416
3417 def test_signature_bind_args_and_kwargs(self):
3418 def test(a, b, c=3, **kwargs):
3419 return a, b, c, kwargs
3420
3421 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3422 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3423 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3424 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3425 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3426 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3427 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3428 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3429 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3430 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3431 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3432 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3433 (1, 2, 4, {'foo': 'bar'}))
3434 self.assertEqual(self.call(test, c=5, a=4, b=3),
3435 (4, 3, 5, {}))
3436
3437 def test_signature_bind_kwonly(self):
3438 def test(*, foo):
3439 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003440 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003441 'too many positional arguments'):
3442 self.call(test, 1)
3443 self.assertEqual(self.call(test, foo=1), 1)
3444
3445 def test(a, *, foo=1, bar):
3446 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003447 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003448 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003449 self.call(test, 1)
3450
3451 def test(foo, *, bar):
3452 return foo, bar
3453 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3454 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3455
Yury Selivanov86872752015-05-19 00:27:49 -04003456 with self.assertRaisesRegex(
3457 TypeError, "got an unexpected keyword argument 'spam'"):
3458
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003459 self.call(test, bar=2, foo=1, spam=10)
3460
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003461 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003462 'too many positional arguments'):
3463 self.call(test, 1, 2)
3464
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003465 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003466 'too many positional arguments'):
3467 self.call(test, 1, 2, bar=2)
3468
Yury Selivanov86872752015-05-19 00:27:49 -04003469 with self.assertRaisesRegex(
3470 TypeError, "got an unexpected keyword argument 'spam'"):
3471
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003472 self.call(test, 1, bar=2, spam='ham')
3473
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003474 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003475 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003476 self.call(test, 1)
3477
3478 def test(foo, *, bar, **bin):
3479 return foo, bar, bin
3480 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3481 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3482 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3483 (1, 2, {'spam': 'ham'}))
3484 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3485 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003486 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003487 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003488 self.call(test, spam='ham', bar=2)
3489 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3490 (1, 2, {'bin': 1, 'spam': 10}))
3491
3492 def test_signature_bind_arguments(self):
3493 def test(a, *args, b, z=100, **kwargs):
3494 pass
3495 sig = inspect.signature(test)
3496 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3497 # we won't have 'z' argument in the bound arguments object, as we didn't
3498 # pass it to the 'bind'
3499 self.assertEqual(tuple(ba.arguments.items()),
3500 (('a', 10), ('args', (20,)), ('b', 30),
3501 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3502 self.assertEqual(ba.kwargs,
3503 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3504 self.assertEqual(ba.args, (10, 20))
3505
3506 def test_signature_bind_positional_only(self):
3507 P = inspect.Parameter
3508
3509 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3510 return a_po, b_po, c_po, foo, bar, kwargs
3511
3512 sig = inspect.signature(test)
3513 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3514 for name in ('a_po', 'b_po', 'c_po'):
3515 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3516 new_sig = sig.replace(parameters=new_params.values())
3517 test.__signature__ = new_sig
3518
3519 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3520 (1, 2, 4, 5, 6, {}))
3521
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003522 self.assertEqual(self.call(test, 1, 2),
3523 (1, 2, 3, 42, 50, {}))
3524
3525 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3526 (1, 2, 3, 4, 5, {}))
3527
3528 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3529 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3530
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003531 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003532 self.call(test, 1, 2, c_po=4)
3533
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003534 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003535 self.call(test, a_po=1, b_po=2)
3536
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003537 def test_signature_bind_with_self_arg(self):
3538 # Issue #17071: one of the parameters is named "self
3539 def test(a, self, b):
3540 pass
3541 sig = inspect.signature(test)
3542 ba = sig.bind(1, 2, 3)
3543 self.assertEqual(ba.args, (1, 2, 3))
3544 ba = sig.bind(1, self=2, b=3)
3545 self.assertEqual(ba.args, (1, 2, 3))
3546
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003547 def test_signature_bind_vararg_name(self):
3548 def test(a, *args):
3549 return a, args
3550 sig = inspect.signature(test)
3551
Yury Selivanov86872752015-05-19 00:27:49 -04003552 with self.assertRaisesRegex(
3553 TypeError, "got an unexpected keyword argument 'args'"):
3554
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003555 sig.bind(a=0, args=1)
3556
3557 def test(*args, **kwargs):
3558 return args, kwargs
3559 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3560
3561 sig = inspect.signature(test)
3562 ba = sig.bind(args=1)
3563 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3564
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003565 @cpython_only
3566 def test_signature_bind_implicit_arg(self):
3567 # Issue #19611: getcallargs should work with set comprehensions
3568 def make_set():
3569 return {z * z for z in range(5)}
3570 setcomp_code = make_set.__code__.co_consts[1]
3571 setcomp_func = types.FunctionType(setcomp_code, {})
3572
3573 iterator = iter(range(5))
3574 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3575
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003576
3577class TestBoundArguments(unittest.TestCase):
3578 def test_signature_bound_arguments_unhashable(self):
3579 def foo(a): pass
3580 ba = inspect.signature(foo).bind(1)
3581
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003582 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003583 hash(ba)
3584
3585 def test_signature_bound_arguments_equality(self):
3586 def foo(a): pass
3587 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003588 self.assertTrue(ba == ba)
3589 self.assertFalse(ba != ba)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003590 self.assertTrue(ba == ALWAYS_EQ)
3591 self.assertFalse(ba != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003592
3593 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003594 self.assertTrue(ba == ba2)
3595 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003596
3597 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003598 self.assertFalse(ba == ba3)
3599 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003600 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003601 self.assertTrue(ba == ba3)
3602 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003603
3604 def bar(b): pass
3605 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003606 self.assertFalse(ba == ba4)
3607 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003608
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003609 def foo(*, a, b): pass
3610 sig = inspect.signature(foo)
3611 ba1 = sig.bind(a=1, b=2)
3612 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003613 self.assertTrue(ba1 == ba2)
3614 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003615
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003616 def test_signature_bound_arguments_pickle(self):
3617 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3618 sig = inspect.signature(foo)
3619 ba = sig.bind(20, 30, z={})
3620
3621 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3622 with self.subTest(pickle_ver=ver):
3623 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3624 self.assertEqual(ba, ba_pickled)
3625
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003626 def test_signature_bound_arguments_repr(self):
3627 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3628 sig = inspect.signature(foo)
3629 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003630 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003631
Yury Selivanovb907a512015-05-16 13:45:09 -04003632 def test_signature_bound_arguments_apply_defaults(self):
3633 def foo(a, b=1, *args, c:1={}, **kw): pass
3634 sig = inspect.signature(foo)
3635
3636 ba = sig.bind(20)
3637 ba.apply_defaults()
3638 self.assertEqual(
3639 list(ba.arguments.items()),
3640 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3641
3642 # Make sure that we preserve the order:
3643 # i.e. 'c' should be *before* 'kw'.
3644 ba = sig.bind(10, 20, 30, d=1)
3645 ba.apply_defaults()
3646 self.assertEqual(
3647 list(ba.arguments.items()),
3648 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3649
3650 # Make sure that BoundArguments produced by bind_partial()
3651 # are supported.
3652 def foo(a, b): pass
3653 sig = inspect.signature(foo)
3654 ba = sig.bind_partial(20)
3655 ba.apply_defaults()
3656 self.assertEqual(
3657 list(ba.arguments.items()),
3658 [('a', 20)])
3659
3660 # Test no args
3661 def foo(): pass
3662 sig = inspect.signature(foo)
3663 ba = sig.bind()
3664 ba.apply_defaults()
3665 self.assertEqual(list(ba.arguments.items()), [])
3666
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003667 # Make sure a no-args binding still acquires proper defaults.
3668 def foo(a='spam'): pass
3669 sig = inspect.signature(foo)
3670 ba = sig.bind()
3671 ba.apply_defaults()
3672 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3673
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003674
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003675class TestSignaturePrivateHelpers(unittest.TestCase):
3676 def test_signature_get_bound_param(self):
3677 getter = inspect._signature_get_bound_param
3678
3679 self.assertEqual(getter('($self)'), 'self')
3680 self.assertEqual(getter('($self, obj)'), 'self')
3681 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3682
Larry Hastings2623c8c2014-02-08 22:15:29 -08003683 def _strip_non_python_syntax(self, input,
3684 clean_signature, self_parameter, last_positional_only):
3685 computed_clean_signature, \
3686 computed_self_parameter, \
3687 computed_last_positional_only = \
3688 inspect._signature_strip_non_python_syntax(input)
3689 self.assertEqual(computed_clean_signature, clean_signature)
3690 self.assertEqual(computed_self_parameter, self_parameter)
3691 self.assertEqual(computed_last_positional_only, last_positional_only)
3692
3693 def test_signature_strip_non_python_syntax(self):
3694 self._strip_non_python_syntax(
3695 "($module, /, path, mode, *, dir_fd=None, " +
3696 "effective_ids=False,\n follow_symlinks=True)",
3697 "(module, path, mode, *, dir_fd=None, " +
3698 "effective_ids=False, follow_symlinks=True)",
3699 0,
3700 0)
3701
3702 self._strip_non_python_syntax(
3703 "($module, word, salt, /)",
3704 "(module, word, salt)",
3705 0,
3706 2)
3707
3708 self._strip_non_python_syntax(
3709 "(x, y=None, z=None, /)",
3710 "(x, y=None, z=None)",
3711 None,
3712 2)
3713
3714 self._strip_non_python_syntax(
3715 "(x, y=None, z=None)",
3716 "(x, y=None, z=None)",
3717 None,
3718 None)
3719
3720 self._strip_non_python_syntax(
3721 "(x,\n y=None,\n z = None )",
3722 "(x, y=None, z=None)",
3723 None,
3724 None)
3725
3726 self._strip_non_python_syntax(
3727 "",
3728 "",
3729 None,
3730 None)
3731
3732 self._strip_non_python_syntax(
3733 None,
3734 None,
3735 None,
3736 None)
3737
Nick Coghlan9c680b02015-04-13 12:54:54 -04003738class TestSignatureDefinitions(unittest.TestCase):
3739 # This test case provides a home for checking that particular APIs
3740 # have signatures available for introspection
3741
3742 @cpython_only
3743 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3744 "Signature information for builtins requires docstrings")
3745 def test_builtins_have_signatures(self):
3746 # This checks all builtin callables in CPython have signatures
3747 # A few have signatures Signature can't yet handle, so we skip those
3748 # since they will have to wait until PEP 457 adds the required
3749 # introspection support to the inspect module
3750 # Some others also haven't been converted yet for various other
3751 # reasons, so we also skip those for the time being, but design
3752 # the test to fail in order to indicate when it needs to be
3753 # updated.
3754 no_signature = set()
3755 # These need PEP 457 groups
3756 needs_groups = {"range", "slice", "dir", "getattr",
3757 "next", "iter", "vars"}
3758 no_signature |= needs_groups
3759 # These need PEP 457 groups or a signature change to accept None
3760 needs_semantic_update = {"round"}
3761 no_signature |= needs_semantic_update
3762 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003763 needs_varargs = {"breakpoint", "min", "max", "print",
3764 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003765 no_signature |= needs_varargs
3766 # These simply weren't covered in the initial AC conversion
3767 # for builtin callables
3768 not_converted_yet = {"open", "__import__"}
3769 no_signature |= not_converted_yet
3770 # These builtin types are expected to provide introspection info
3771 types_with_signatures = set()
3772 # Check the signatures we expect to be there
3773 ns = vars(builtins)
3774 for name, obj in sorted(ns.items()):
3775 if not callable(obj):
3776 continue
3777 # The builtin types haven't been converted to AC yet
3778 if isinstance(obj, type) and (name not in types_with_signatures):
3779 # Note that this also skips all the exception types
3780 no_signature.add(name)
3781 if (name in no_signature):
3782 # Not yet converted
3783 continue
3784 with self.subTest(builtin=name):
3785 self.assertIsNotNone(inspect.signature(obj))
3786 # Check callables that haven't been converted don't claim a signature
3787 # This ensures this test will start failing as more signatures are
3788 # added, so the affected items can be moved into the scope of the
3789 # regression test above
3790 for name in no_signature:
3791 with self.subTest(builtin=name):
3792 self.assertIsNone(obj.__text_signature__)
3793
Serhiy Storchakad53cf992019-05-06 22:40:27 +03003794 def test_python_function_override_signature(self):
3795 def func(*args, **kwargs):
3796 pass
3797 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
3798 sig = inspect.signature(func)
3799 self.assertIsNotNone(sig)
3800 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
3801 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
3802 sig = inspect.signature(func)
3803 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
3804
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003805
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003806class NTimesUnwrappable:
3807 def __init__(self, n):
3808 self.n = n
3809 self._next = None
3810
3811 @property
3812 def __wrapped__(self):
3813 if self.n <= 0:
3814 raise Exception("Unwrapped too many times")
3815 if self._next is None:
3816 self._next = NTimesUnwrappable(self.n - 1)
3817 return self._next
3818
Nick Coghlane8c45d62013-07-28 20:00:01 +10003819class TestUnwrap(unittest.TestCase):
3820
3821 def test_unwrap_one(self):
3822 def func(a, b):
3823 return a + b
3824 wrapper = functools.lru_cache(maxsize=20)(func)
3825 self.assertIs(inspect.unwrap(wrapper), func)
3826
3827 def test_unwrap_several(self):
3828 def func(a, b):
3829 return a + b
3830 wrapper = func
3831 for __ in range(10):
3832 @functools.wraps(wrapper)
3833 def wrapper():
3834 pass
3835 self.assertIsNot(wrapper.__wrapped__, func)
3836 self.assertIs(inspect.unwrap(wrapper), func)
3837
3838 def test_stop(self):
3839 def func1(a, b):
3840 return a + b
3841 @functools.wraps(func1)
3842 def func2():
3843 pass
3844 @functools.wraps(func2)
3845 def wrapper():
3846 pass
3847 func2.stop_here = 1
3848 unwrapped = inspect.unwrap(wrapper,
3849 stop=(lambda f: hasattr(f, "stop_here")))
3850 self.assertIs(unwrapped, func2)
3851
3852 def test_cycle(self):
3853 def func1(): pass
3854 func1.__wrapped__ = func1
3855 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3856 inspect.unwrap(func1)
3857
3858 def func2(): pass
3859 func2.__wrapped__ = func1
3860 func1.__wrapped__ = func2
3861 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3862 inspect.unwrap(func1)
3863 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3864 inspect.unwrap(func2)
3865
3866 def test_unhashable(self):
3867 def func(): pass
3868 func.__wrapped__ = None
3869 class C:
3870 __hash__ = None
3871 __wrapped__ = func
3872 self.assertIsNone(inspect.unwrap(C()))
3873
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003874 def test_recursion_limit(self):
3875 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3876 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3877 inspect.unwrap(obj)
3878
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003879class TestMain(unittest.TestCase):
3880 def test_only_source(self):
3881 module = importlib.import_module('unittest')
3882 rc, out, err = assert_python_ok('-m', 'inspect',
3883 'unittest')
3884 lines = out.decode().splitlines()
3885 # ignore the final newline
3886 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3887 self.assertEqual(err, b'')
3888
Yury Selivanov42407ab2014-06-23 10:23:50 -07003889 def test_custom_getattr(self):
3890 def foo():
3891 pass
3892 foo.__signature__ = 42
3893 with self.assertRaises(TypeError):
3894 inspect.signature(foo)
3895
Brett Cannon634a8fc2013-10-02 10:25:42 -04003896 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003897 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003898 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003899 rc, out, err = assert_python_ok('-m', 'inspect',
3900 'concurrent.futures:ThreadPoolExecutor')
3901 lines = out.decode().splitlines()
3902 # ignore the final newline
3903 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003904 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003905 self.assertEqual(err, b'')
3906
3907 def test_builtins(self):
3908 module = importlib.import_module('unittest')
3909 _, out, err = assert_python_failure('-m', 'inspect',
3910 'sys')
3911 lines = err.decode().splitlines()
3912 self.assertEqual(lines, ["Can't get info for builtin modules."])
3913
3914 def test_details(self):
3915 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003916 args = support.optim_args_from_interpreter_flags()
3917 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003918 'unittest', '--details')
3919 output = out.decode()
3920 # Just a quick sanity check on the output
3921 self.assertIn(module.__name__, output)
3922 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003923 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003924 self.assertEqual(err, b'')
3925
3926
Yury Selivanovef1e7502014-12-08 16:05:34 -05003927class TestReload(unittest.TestCase):
3928
3929 src_before = textwrap.dedent("""\
3930def foo():
3931 print("Bla")
3932 """)
3933
3934 src_after = textwrap.dedent("""\
3935def foo():
3936 print("Oh no!")
3937 """)
3938
3939 def assertInspectEqual(self, path, source):
3940 inspected_src = inspect.getsource(source)
3941 with open(path) as src:
3942 self.assertEqual(
3943 src.read().splitlines(True),
3944 inspected_src.splitlines(True)
3945 )
3946
3947 def test_getsource_reload(self):
3948 # see issue 1218234
3949 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3950 module = importlib.import_module(name)
3951 self.assertInspectEqual(path, module)
3952 with open(path, 'w') as src:
3953 src.write(self.src_after)
3954 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003955
Nick Coghlane8c45d62013-07-28 20:00:01 +10003956
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003957def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003958 run_unittest(
3959 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3960 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3961 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003962 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003963 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003964 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04003965 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003966 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07003967 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00003968 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003969
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003970if __name__ == "__main__":
3971 test_main()