blob: f193807e80473ad3c8c0089980df9d2ffc092717 [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()), '()')
Jens Reidel611836a2020-03-18 03:22:46 +01002080 self.assertEqual(repr(S().parameters), 'mappingproxy(OrderedDict())')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002081
Yury Selivanov07a9e452014-01-29 10:58:16 -05002082 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002083 pass
2084 sig = inspect.signature(test)
2085 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05002086 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002087 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05002088 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002089 args = sig.parameters['args']
2090 ko = sig.parameters['ko']
2091 kwargs = sig.parameters['kwargs']
2092
2093 S((po, pk, args, ko, kwargs))
2094
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002095 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002096 S((pk, po, args, ko, kwargs))
2097
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002098 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002099 S((po, args, pk, ko, kwargs))
2100
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002101 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002102 S((args, po, pk, ko, kwargs))
2103
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002104 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002105 S((po, pk, args, kwargs, ko))
2106
2107 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002108 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002109 S((po, pk, args, kwargs2, ko))
2110
Yury Selivanov07a9e452014-01-29 10:58:16 -05002111 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2112 S((pod, po))
2113
2114 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2115 S((po, pkd, pk))
2116
2117 with self.assertRaisesRegex(ValueError, 'follows default argument'):
2118 S((pkd, pk))
2119
Yury Selivanov374375d2014-03-27 12:41:53 -04002120 self.assertTrue(repr(sig).startswith('<Signature'))
Yury Selivanov0cd2bf42015-05-15 12:55:20 -04002121 self.assertTrue('(po, pk' in repr(sig))
Yury Selivanov374375d2014-03-27 12:41:53 -04002122
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002123 def test_signature_object_pickle(self):
2124 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
2125 foo_partial = functools.partial(foo, a=1)
2126
2127 sig = inspect.signature(foo_partial)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002128
2129 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2130 with self.subTest(pickle_ver=ver, subclass=False):
2131 sig_pickled = pickle.loads(pickle.dumps(sig, ver))
2132 self.assertEqual(sig, sig_pickled)
Yury Selivanova5d63dd2014-03-27 11:31:43 -04002133
2134 # Test that basic sub-classing works
2135 sig = inspect.signature(foo)
2136 myparam = MyParameter(name='z', kind=inspect.Parameter.POSITIONAL_ONLY)
2137 myparams = collections.OrderedDict(sig.parameters, a=myparam)
2138 mysig = MySignature().replace(parameters=myparams.values(),
2139 return_annotation=sig.return_annotation)
2140 self.assertTrue(isinstance(mysig, MySignature))
2141 self.assertTrue(isinstance(mysig.parameters['z'], MyParameter))
2142
2143 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
2144 with self.subTest(pickle_ver=ver, subclass=True):
2145 sig_pickled = pickle.loads(pickle.dumps(mysig, ver))
2146 self.assertEqual(mysig, sig_pickled)
2147 self.assertTrue(isinstance(sig_pickled, MySignature))
2148 self.assertTrue(isinstance(sig_pickled.parameters['z'],
2149 MyParameter))
2150
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002151 def test_signature_immutability(self):
2152 def test(a):
2153 pass
2154 sig = inspect.signature(test)
2155
2156 with self.assertRaises(AttributeError):
2157 sig.foo = 'bar'
2158
2159 with self.assertRaises(TypeError):
2160 sig.parameters['a'] = None
2161
2162 def test_signature_on_noarg(self):
2163 def test():
2164 pass
2165 self.assertEqual(self.signature(test), ((), ...))
2166
2167 def test_signature_on_wargs(self):
2168 def test(a, b:'foo') -> 123:
2169 pass
2170 self.assertEqual(self.signature(test),
2171 ((('a', ..., ..., "positional_or_keyword"),
2172 ('b', ..., 'foo', "positional_or_keyword")),
2173 123))
2174
2175 def test_signature_on_wkwonly(self):
2176 def test(*, a:float, b:str) -> int:
2177 pass
2178 self.assertEqual(self.signature(test),
2179 ((('a', ..., float, "keyword_only"),
2180 ('b', ..., str, "keyword_only")),
2181 int))
2182
2183 def test_signature_on_complex_args(self):
2184 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
2185 pass
2186 self.assertEqual(self.signature(test),
2187 ((('a', ..., ..., "positional_or_keyword"),
2188 ('b', 10, 'foo', "positional_or_keyword"),
2189 ('args', ..., 'bar', "var_positional"),
2190 ('spam', ..., 'baz', "keyword_only"),
2191 ('ham', 123, ..., "keyword_only"),
2192 ('kwargs', ..., int, "var_keyword")),
2193 ...))
2194
Dong-hee Na378d7062017-05-18 04:00:51 +09002195 def test_signature_without_self(self):
2196 def test_args_only(*args): # NOQA
2197 pass
2198
2199 def test_args_kwargs_only(*args, **kwargs): # NOQA
2200 pass
2201
2202 class A:
2203 @classmethod
2204 def test_classmethod(*args): # NOQA
2205 pass
2206
2207 @staticmethod
2208 def test_staticmethod(*args): # NOQA
2209 pass
2210
2211 f1 = functools.partialmethod((test_classmethod), 1)
2212 f2 = functools.partialmethod((test_args_only), 1)
2213 f3 = functools.partialmethod((test_staticmethod), 1)
2214 f4 = functools.partialmethod((test_args_kwargs_only),1)
2215
2216 self.assertEqual(self.signature(test_args_only),
2217 ((('args', ..., ..., 'var_positional'),), ...))
2218 self.assertEqual(self.signature(test_args_kwargs_only),
2219 ((('args', ..., ..., 'var_positional'),
2220 ('kwargs', ..., ..., 'var_keyword')), ...))
2221 self.assertEqual(self.signature(A.f1),
2222 ((('args', ..., ..., 'var_positional'),), ...))
2223 self.assertEqual(self.signature(A.f2),
2224 ((('args', ..., ..., 'var_positional'),), ...))
2225 self.assertEqual(self.signature(A.f3),
2226 ((('args', ..., ..., 'var_positional'),), ...))
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03002227 self.assertEqual(self.signature(A.f4),
Dong-hee Na378d7062017-05-18 04:00:51 +09002228 ((('args', ..., ..., 'var_positional'),
2229 ('kwargs', ..., ..., 'var_keyword')), ...))
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002230 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08002231 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2232 "Signature information for builtins requires docstrings")
2233 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002234 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08002235
Larry Hastings5c661892014-01-24 06:17:25 -08002236 def test_unbound_method(o):
2237 """Use this to test unbound methods (things that should have a self)"""
2238 signature = inspect.signature(o)
2239 self.assertTrue(isinstance(signature, inspect.Signature))
2240 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
2241 return signature
2242
2243 def test_callable(o):
2244 """Use this to test bound methods or normal callables (things that don't expect self)"""
2245 signature = inspect.signature(o)
2246 self.assertTrue(isinstance(signature, inspect.Signature))
2247 if signature.parameters:
2248 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
2249 return signature
2250
2251 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08002252 def p(name): return signature.parameters[name].default
2253 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08002254 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08002255 self.assertEqual(p('d'), 3.14)
2256 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08002257 self.assertEqual(p('n'), None)
2258 self.assertEqual(p('t'), True)
2259 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08002260 self.assertEqual(p('local'), 3)
2261 self.assertEqual(p('sys'), sys.maxsize)
Serhiy Storchakad8ac4d12018-01-04 11:15:39 +02002262 self.assertNotIn('exp', signature.parameters)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002263
Larry Hastings5c661892014-01-24 06:17:25 -08002264 test_callable(object)
2265
2266 # normal method
2267 # (PyMethodDescr_Type, "method_descriptor")
2268 test_unbound_method(_pickle.Pickler.dump)
2269 d = _pickle.Pickler(io.StringIO())
2270 test_callable(d.dump)
2271
2272 # static method
Serhiy Storchaka279f4462019-09-14 12:24:05 +03002273 test_callable(bytes.maketrans)
2274 test_callable(b'abc'.maketrans)
Larry Hastings5c661892014-01-24 06:17:25 -08002275
2276 # class method
2277 test_callable(dict.fromkeys)
2278 test_callable({}.fromkeys)
2279
2280 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
2281 test_unbound_method(type.__call__)
2282 test_unbound_method(int.__add__)
2283 test_callable((3).__add__)
2284
2285 # _PyMethodWrapper_Type
2286 # support for 'method-wrapper'
2287 test_callable(min.__call__)
2288
Larry Hastings2623c8c2014-02-08 22:15:29 -08002289 # This doesn't work now.
2290 # (We don't have a valid signature for "type" in 3.4)
2291 with self.assertRaisesRegex(ValueError, "no signature found"):
2292 class ThisWorksNow:
2293 __call__ = type
2294 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08002295
Yury Selivanov056e2652014-03-02 12:25:27 -05002296 # Regression test for issue #20786
2297 test_unbound_method(dict.__delitem__)
2298 test_unbound_method(property.__delete__)
2299
Zachary Ware8ef887c2015-04-13 18:22:35 -05002300 # Regression test for issue #20586
2301 test_callable(_testcapi.docstring_with_signature_but_no_doc)
2302
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002303 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05002304 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2305 "Signature information for builtins requires docstrings")
2306 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002307 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05002308 func = _testcapi.docstring_with_signature_with_defaults
2309
2310 def decorator(func):
2311 @functools.wraps(func)
2312 def wrapper(*args, **kwargs) -> int:
2313 return func(*args, **kwargs)
2314 return wrapper
2315
2316 decorated_func = decorator(func)
2317
2318 self.assertEqual(inspect.signature(func),
2319 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08002320
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002321 def wrapper_like(*args, **kwargs) -> int: pass
2322 self.assertEqual(inspect.signature(decorated_func,
2323 follow_wrapped=False),
2324 inspect.signature(wrapper_like))
2325
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002326 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08002327 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02002328 import _testcapi
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002329 with self.assertRaisesRegex(ValueError,
2330 'no signature found for builtin'):
Larry Hastings5c661892014-01-24 06:17:25 -08002331 inspect.signature(_testcapi.docstring_no_signature)
2332
Yury Selivanovbf304fc2015-05-30 17:08:36 -04002333 with self.assertRaisesRegex(ValueError,
2334 'no signature found for builtin'):
2335 inspect.signature(str)
2336
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002337 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002338 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002339 inspect.signature(42)
2340
Yury Selivanov63da7c72014-01-31 14:48:37 -05002341 def test_signature_from_functionlike_object(self):
2342 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2343 pass
2344
2345 class funclike:
2346 # Has to be callable, and have correct
2347 # __code__, __annotations__, __defaults__, __name__,
2348 # and __kwdefaults__ attributes
2349
2350 def __init__(self, func):
2351 self.__name__ = func.__name__
2352 self.__code__ = func.__code__
2353 self.__annotations__ = func.__annotations__
2354 self.__defaults__ = func.__defaults__
2355 self.__kwdefaults__ = func.__kwdefaults__
2356 self.func = func
2357
2358 def __call__(self, *args, **kwargs):
2359 return self.func(*args, **kwargs)
2360
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002361 sig_func = inspect.Signature.from_callable(func)
Yury Selivanov63da7c72014-01-31 14:48:37 -05002362
Yury Selivanov57c74fc2015-05-20 23:07:02 -04002363 sig_funclike = inspect.Signature.from_callable(funclike(func))
Yury Selivanov63da7c72014-01-31 14:48:37 -05002364 self.assertEqual(sig_funclike, sig_func)
2365
2366 sig_funclike = inspect.signature(funclike(func))
2367 self.assertEqual(sig_funclike, sig_func)
2368
2369 # If object is not a duck type of function, then
2370 # signature will try to get a signature for its '__call__'
2371 # method
2372 fl = funclike(func)
2373 del fl.__defaults__
2374 self.assertEqual(self.signature(fl),
2375 ((('args', ..., ..., "var_positional"),
2376 ('kwargs', ..., ..., "var_keyword")),
2377 ...))
2378
Yury Selivanova773de02014-02-21 18:30:53 -05002379 # Test with cython-like builtins:
2380 _orig_isdesc = inspect.ismethoddescriptor
2381 def _isdesc(obj):
2382 if hasattr(obj, '_builtinmock'):
2383 return True
2384 return _orig_isdesc(obj)
2385
2386 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
2387 builtin_func = funclike(func)
2388 # Make sure that our mock setup is working
2389 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
2390 builtin_func._builtinmock = True
2391 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
2392 self.assertEqual(inspect.signature(builtin_func), sig_func)
2393
Yury Selivanov63da7c72014-01-31 14:48:37 -05002394 def test_signature_functionlike_class(self):
2395 # We only want to duck type function-like objects,
2396 # not classes.
2397
2398 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
2399 pass
2400
2401 class funclike:
2402 def __init__(self, marker):
2403 pass
2404
2405 __name__ = func.__name__
2406 __code__ = func.__code__
2407 __annotations__ = func.__annotations__
2408 __defaults__ = func.__defaults__
2409 __kwdefaults__ = func.__kwdefaults__
2410
Yury Selivanov63da7c72014-01-31 14:48:37 -05002411 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
2412
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002413 def test_signature_on_method(self):
2414 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05002415 def __init__(*args):
2416 pass
2417 def m1(self, arg1, arg2=1) -> int:
2418 pass
2419 def m2(*args):
2420 pass
2421 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002422 pass
2423
Yury Selivanov62560fb2014-01-28 12:26:24 -05002424 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002425 ((('arg1', ..., ..., "positional_or_keyword"),
2426 ('arg2', 1, ..., "positional_or_keyword")),
2427 int))
2428
Yury Selivanov62560fb2014-01-28 12:26:24 -05002429 self.assertEqual(self.signature(Test().m2),
2430 ((('args', ..., ..., "var_positional"),),
2431 ...))
2432
2433 self.assertEqual(self.signature(Test),
2434 ((('args', ..., ..., "var_positional"),),
2435 ...))
2436
2437 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
2438 self.signature(Test())
2439
Yury Selivanov46c759d2015-05-27 21:56:53 -04002440 def test_signature_wrapped_bound_method(self):
2441 # Issue 24298
2442 class Test:
2443 def m1(self, arg1, arg2=1) -> int:
2444 pass
2445 @functools.wraps(Test().m1)
2446 def m1d(*args, **kwargs):
2447 pass
2448 self.assertEqual(self.signature(m1d),
2449 ((('arg1', ..., ..., "positional_or_keyword"),
2450 ('arg2', 1, ..., "positional_or_keyword")),
2451 int))
2452
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002453 def test_signature_on_classmethod(self):
2454 class Test:
2455 @classmethod
2456 def foo(cls, arg1, *, arg2=1):
2457 pass
2458
2459 meth = Test().foo
2460 self.assertEqual(self.signature(meth),
2461 ((('arg1', ..., ..., "positional_or_keyword"),
2462 ('arg2', 1, ..., "keyword_only")),
2463 ...))
2464
2465 meth = Test.foo
2466 self.assertEqual(self.signature(meth),
2467 ((('arg1', ..., ..., "positional_or_keyword"),
2468 ('arg2', 1, ..., "keyword_only")),
2469 ...))
2470
2471 def test_signature_on_staticmethod(self):
2472 class Test:
2473 @staticmethod
2474 def foo(cls, *, arg):
2475 pass
2476
2477 meth = Test().foo
2478 self.assertEqual(self.signature(meth),
2479 ((('cls', ..., ..., "positional_or_keyword"),
2480 ('arg', ..., ..., "keyword_only")),
2481 ...))
2482
2483 meth = Test.foo
2484 self.assertEqual(self.signature(meth),
2485 ((('cls', ..., ..., "positional_or_keyword"),
2486 ('arg', ..., ..., "keyword_only")),
2487 ...))
2488
2489 def test_signature_on_partial(self):
2490 from functools import partial
2491
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002492 Parameter = inspect.Parameter
2493
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002494 def test():
2495 pass
2496
2497 self.assertEqual(self.signature(partial(test)), ((), ...))
2498
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002499 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002500 inspect.signature(partial(test, 1))
2501
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002502 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002503 inspect.signature(partial(test, a=1))
2504
2505 def test(a, b, *, c, d):
2506 pass
2507
2508 self.assertEqual(self.signature(partial(test)),
2509 ((('a', ..., ..., "positional_or_keyword"),
2510 ('b', ..., ..., "positional_or_keyword"),
2511 ('c', ..., ..., "keyword_only"),
2512 ('d', ..., ..., "keyword_only")),
2513 ...))
2514
2515 self.assertEqual(self.signature(partial(test, 1)),
2516 ((('b', ..., ..., "positional_or_keyword"),
2517 ('c', ..., ..., "keyword_only"),
2518 ('d', ..., ..., "keyword_only")),
2519 ...))
2520
2521 self.assertEqual(self.signature(partial(test, 1, c=2)),
2522 ((('b', ..., ..., "positional_or_keyword"),
2523 ('c', 2, ..., "keyword_only"),
2524 ('d', ..., ..., "keyword_only")),
2525 ...))
2526
2527 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2528 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002529 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002530 ('c', 2, ..., "keyword_only"),
2531 ('d', ..., ..., "keyword_only")),
2532 ...))
2533
2534 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002535 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002536 ('c', 2, ..., "keyword_only"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002537 ('d', ..., ..., "keyword_only")),
2538 ...))
2539
2540 self.assertEqual(self.signature(partial(test, a=1)),
2541 ((('a', 1, ..., "keyword_only"),
2542 ('b', ..., ..., "keyword_only"),
2543 ('c', ..., ..., "keyword_only"),
2544 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002545 ...))
2546
2547 def test(a, *args, b, **kwargs):
2548 pass
2549
2550 self.assertEqual(self.signature(partial(test, 1)),
2551 ((('args', ..., ..., "var_positional"),
2552 ('b', ..., ..., "keyword_only"),
2553 ('kwargs', ..., ..., "var_keyword")),
2554 ...))
2555
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002556 self.assertEqual(self.signature(partial(test, a=1)),
2557 ((('a', 1, ..., "keyword_only"),
2558 ('b', ..., ..., "keyword_only"),
2559 ('kwargs', ..., ..., "var_keyword")),
2560 ...))
2561
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002562 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2563 ((('args', ..., ..., "var_positional"),
2564 ('b', ..., ..., "keyword_only"),
2565 ('kwargs', ..., ..., "var_keyword")),
2566 ...))
2567
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002568 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2569 ((('args', ..., ..., "var_positional"),
2570 ('b', ..., ..., "keyword_only"),
2571 ('kwargs', ..., ..., "var_keyword")),
2572 ...))
2573
2574 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2575 ((('args', ..., ..., "var_positional"),
2576 ('b', 0, ..., "keyword_only"),
2577 ('kwargs', ..., ..., "var_keyword")),
2578 ...))
2579
2580 self.assertEqual(self.signature(partial(test, b=0)),
2581 ((('a', ..., ..., "positional_or_keyword"),
2582 ('args', ..., ..., "var_positional"),
2583 ('b', 0, ..., "keyword_only"),
2584 ('kwargs', ..., ..., "var_keyword")),
2585 ...))
2586
2587 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2588 ((('a', ..., ..., "positional_or_keyword"),
2589 ('args', ..., ..., "var_positional"),
2590 ('b', 0, ..., "keyword_only"),
2591 ('kwargs', ..., ..., "var_keyword")),
2592 ...))
2593
2594 def test(a, b, c:int) -> 42:
2595 pass
2596
2597 sig = test.__signature__ = inspect.signature(test)
2598
2599 self.assertEqual(self.signature(partial(partial(test, 1))),
2600 ((('b', ..., ..., "positional_or_keyword"),
2601 ('c', ..., int, "positional_or_keyword")),
2602 42))
2603
2604 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2605 ((('c', ..., int, "positional_or_keyword"),),
2606 42))
2607
2608 psig = inspect.signature(partial(partial(test, 1), 2))
2609
2610 def foo(a):
2611 return a
2612 _foo = partial(partial(foo, a=10), a=20)
2613 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002614 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002615 ...))
2616 # check that we don't have any side-effects in signature(),
2617 # and the partial object is still functioning
2618 self.assertEqual(_foo(), 20)
2619
2620 def foo(a, b, c):
2621 return a, b, c
2622 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002623
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002624 self.assertEqual(self.signature(_foo),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002625 ((('b', 30, ..., "keyword_only"),
2626 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002627 ...))
2628 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002629
2630 def foo(a, b, c, *, d):
2631 return a, b, c, d
2632 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2633 self.assertEqual(self.signature(_foo),
2634 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002635 ('b', 10, ..., "keyword_only"),
2636 ('c', 20, ..., "keyword_only"),
2637 ('d', 30, ..., "keyword_only"),
2638 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002639 ...))
2640 ba = inspect.signature(_foo).bind(a=200, b=11)
2641 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2642
2643 def foo(a=1, b=2, c=3):
2644 return a, b, c
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002645 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2646
2647 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002648 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002649
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002650 ba = inspect.signature(_foo).bind(11, 12)
2651 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002652
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002653 ba = inspect.signature(_foo).bind(11, b=12)
2654 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002655
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002656 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov3f73ca22014-04-08 11:30:45 -04002657 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2658
2659 _foo = partial(_foo, b=10, c=20)
2660 ba = inspect.signature(_foo).bind(12)
2661 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2662
2663
2664 def foo(a, b, c, d, **kwargs):
2665 pass
2666 sig = inspect.signature(foo)
2667 params = sig.parameters.copy()
2668 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2669 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2670 foo.__signature__ = inspect.Signature(params.values())
2671 sig = inspect.signature(foo)
2672 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2673
2674 self.assertEqual(self.signature(partial(foo, 1)),
2675 ((('b', ..., ..., 'positional_only'),
2676 ('c', ..., ..., 'positional_or_keyword'),
2677 ('d', ..., ..., 'positional_or_keyword'),
2678 ('kwargs', ..., ..., 'var_keyword')),
2679 ...))
2680
2681 self.assertEqual(self.signature(partial(foo, 1, 2)),
2682 ((('c', ..., ..., 'positional_or_keyword'),
2683 ('d', ..., ..., 'positional_or_keyword'),
2684 ('kwargs', ..., ..., 'var_keyword')),
2685 ...))
2686
2687 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2688 ((('d', ..., ..., 'positional_or_keyword'),
2689 ('kwargs', ..., ..., 'var_keyword')),
2690 ...))
2691
2692 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2693 ((('c', 3, ..., 'keyword_only'),
2694 ('d', ..., ..., 'keyword_only'),
2695 ('kwargs', ..., ..., 'var_keyword')),
2696 ...))
2697
2698 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2699 ((('b', ..., ..., 'positional_only'),
2700 ('c', 3, ..., 'keyword_only'),
2701 ('d', ..., ..., 'keyword_only'),
2702 ('kwargs', ..., ..., 'var_keyword')),
2703 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002704
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002705 def test_signature_on_partialmethod(self):
2706 from functools import partialmethod
2707
2708 class Spam:
2709 def test():
2710 pass
2711 ham = partialmethod(test)
2712
2713 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2714 inspect.signature(Spam.ham)
2715
2716 class Spam:
2717 def test(it, a, *, c) -> 'spam':
2718 pass
2719 ham = partialmethod(test, c=1)
2720
2721 self.assertEqual(self.signature(Spam.ham),
2722 ((('it', ..., ..., 'positional_or_keyword'),
2723 ('a', ..., ..., 'positional_or_keyword'),
2724 ('c', 1, ..., 'keyword_only')),
2725 'spam'))
2726
2727 self.assertEqual(self.signature(Spam().ham),
2728 ((('a', ..., ..., 'positional_or_keyword'),
2729 ('c', 1, ..., 'keyword_only')),
2730 'spam'))
2731
Yury Selivanov8a387212018-03-06 12:59:45 -05002732 class Spam:
2733 def test(self: 'anno', x):
2734 pass
2735
2736 g = partialmethod(test, 1)
2737
2738 self.assertEqual(self.signature(Spam.g),
2739 ((('self', ..., 'anno', 'positional_or_keyword'),),
2740 ...))
2741
Yury Selivanov0486f812014-01-29 12:18:59 -05002742 def test_signature_on_fake_partialmethod(self):
2743 def foo(a): pass
2744 foo._partialmethod = 'spam'
2745 self.assertEqual(str(inspect.signature(foo)), '(a)')
2746
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002747 def test_signature_on_decorated(self):
2748 import functools
2749
2750 def decorator(func):
2751 @functools.wraps(func)
2752 def wrapper(*args, **kwargs) -> int:
2753 return func(*args, **kwargs)
2754 return wrapper
2755
2756 class Foo:
2757 @decorator
2758 def bar(self, a, b):
2759 pass
2760
2761 self.assertEqual(self.signature(Foo.bar),
2762 ((('self', ..., ..., "positional_or_keyword"),
2763 ('a', ..., ..., "positional_or_keyword"),
2764 ('b', ..., ..., "positional_or_keyword")),
2765 ...))
2766
2767 self.assertEqual(self.signature(Foo().bar),
2768 ((('a', ..., ..., "positional_or_keyword"),
2769 ('b', ..., ..., "positional_or_keyword")),
2770 ...))
2771
Yury Selivanovbcd4fc12015-05-20 14:30:08 -04002772 self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
2773 ((('args', ..., ..., "var_positional"),
2774 ('kwargs', ..., ..., "var_keyword")),
2775 ...)) # functools.wraps will copy __annotations__
2776 # from "func" to "wrapper", hence no
2777 # return_annotation
2778
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002779 # Test that we handle method wrappers correctly
2780 def decorator(func):
2781 @functools.wraps(func)
2782 def wrapper(*args, **kwargs) -> int:
2783 return func(42, *args, **kwargs)
2784 sig = inspect.signature(func)
2785 new_params = tuple(sig.parameters.values())[1:]
2786 wrapper.__signature__ = sig.replace(parameters=new_params)
2787 return wrapper
2788
2789 class Foo:
2790 @decorator
2791 def __call__(self, a, b):
2792 pass
2793
2794 self.assertEqual(self.signature(Foo.__call__),
2795 ((('a', ..., ..., "positional_or_keyword"),
2796 ('b', ..., ..., "positional_or_keyword")),
2797 ...))
2798
2799 self.assertEqual(self.signature(Foo().__call__),
2800 ((('b', ..., ..., "positional_or_keyword"),),
2801 ...))
2802
Nick Coghlane8c45d62013-07-28 20:00:01 +10002803 # Test we handle __signature__ partway down the wrapper stack
2804 def wrapped_foo_call():
2805 pass
2806 wrapped_foo_call.__wrapped__ = Foo.__call__
2807
2808 self.assertEqual(self.signature(wrapped_foo_call),
2809 ((('a', ..., ..., "positional_or_keyword"),
2810 ('b', ..., ..., "positional_or_keyword")),
2811 ...))
2812
2813
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002814 def test_signature_on_class(self):
2815 class C:
2816 def __init__(self, a):
2817 pass
2818
2819 self.assertEqual(self.signature(C),
2820 ((('a', ..., ..., "positional_or_keyword"),),
2821 ...))
2822
2823 class CM(type):
2824 def __call__(cls, a):
2825 pass
2826 class C(metaclass=CM):
2827 def __init__(self, b):
2828 pass
2829
2830 self.assertEqual(self.signature(C),
2831 ((('a', ..., ..., "positional_or_keyword"),),
2832 ...))
2833
2834 class CM(type):
2835 def __new__(mcls, name, bases, dct, *, foo=1):
2836 return super().__new__(mcls, name, bases, dct)
2837 class C(metaclass=CM):
2838 def __init__(self, b):
2839 pass
2840
2841 self.assertEqual(self.signature(C),
2842 ((('b', ..., ..., "positional_or_keyword"),),
2843 ...))
2844
2845 self.assertEqual(self.signature(CM),
2846 ((('name', ..., ..., "positional_or_keyword"),
2847 ('bases', ..., ..., "positional_or_keyword"),
2848 ('dct', ..., ..., "positional_or_keyword"),
2849 ('foo', 1, ..., "keyword_only")),
2850 ...))
2851
2852 class CMM(type):
2853 def __new__(mcls, name, bases, dct, *, foo=1):
2854 return super().__new__(mcls, name, bases, dct)
2855 def __call__(cls, nm, bs, dt):
2856 return type(nm, bs, dt)
2857 class CM(type, metaclass=CMM):
2858 def __new__(mcls, name, bases, dct, *, bar=2):
2859 return super().__new__(mcls, name, bases, dct)
2860 class C(metaclass=CM):
2861 def __init__(self, b):
2862 pass
2863
2864 self.assertEqual(self.signature(CMM),
2865 ((('name', ..., ..., "positional_or_keyword"),
2866 ('bases', ..., ..., "positional_or_keyword"),
2867 ('dct', ..., ..., "positional_or_keyword"),
2868 ('foo', 1, ..., "keyword_only")),
2869 ...))
2870
2871 self.assertEqual(self.signature(CM),
2872 ((('nm', ..., ..., "positional_or_keyword"),
2873 ('bs', ..., ..., "positional_or_keyword"),
2874 ('dt', ..., ..., "positional_or_keyword")),
2875 ...))
2876
2877 self.assertEqual(self.signature(C),
2878 ((('b', ..., ..., "positional_or_keyword"),),
2879 ...))
2880
2881 class CM(type):
2882 def __init__(cls, name, bases, dct, *, bar=2):
2883 return super().__init__(name, bases, dct)
2884 class C(metaclass=CM):
2885 def __init__(self, b):
2886 pass
2887
2888 self.assertEqual(self.signature(CM),
2889 ((('name', ..., ..., "positional_or_keyword"),
2890 ('bases', ..., ..., "positional_or_keyword"),
2891 ('dct', ..., ..., "positional_or_keyword"),
2892 ('bar', 2, ..., "keyword_only")),
2893 ...))
2894
Yury Selivanov145dff82014-02-01 13:49:29 -05002895 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2896 "Signature information for builtins requires docstrings")
2897 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002898 # Test classes without user-defined __init__ or __new__
2899 class C: pass
2900 self.assertEqual(str(inspect.signature(C)), '()')
2901 class D(C): pass
2902 self.assertEqual(str(inspect.signature(D)), '()')
2903
2904 # Test meta-classes without user-defined __init__ or __new__
2905 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002906 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002907 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2908 self.assertEqual(inspect.signature(C), None)
2909 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2910 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002911
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002912 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2913 "Signature information for builtins requires docstrings")
2914 def test_signature_on_builtin_class(self):
Antoine Pitrou91f43802019-05-26 17:10:09 +02002915 expected = ('(file, protocol=None, fix_imports=True, '
2916 'buffer_callback=None)')
2917 self.assertEqual(str(inspect.signature(_pickle.Pickler)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002918
2919 class P(_pickle.Pickler): pass
2920 class EmptyTrait: pass
2921 class P2(EmptyTrait, P): pass
Antoine Pitrou91f43802019-05-26 17:10:09 +02002922 self.assertEqual(str(inspect.signature(P)), expected)
2923 self.assertEqual(str(inspect.signature(P2)), expected)
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002924
2925 class P3(P2):
2926 def __init__(self, spam):
2927 pass
2928 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2929
2930 class MetaP(type):
2931 def __call__(cls, foo, bar):
2932 pass
2933 class P4(P2, metaclass=MetaP):
2934 pass
2935 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2936
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002937 def test_signature_on_callable_objects(self):
2938 class Foo:
2939 def __call__(self, a):
2940 pass
2941
2942 self.assertEqual(self.signature(Foo()),
2943 ((('a', ..., ..., "positional_or_keyword"),),
2944 ...))
2945
2946 class Spam:
2947 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002948 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002949 inspect.signature(Spam())
2950
2951 class Bar(Spam, Foo):
2952 pass
2953
2954 self.assertEqual(self.signature(Bar()),
2955 ((('a', ..., ..., "positional_or_keyword"),),
2956 ...))
2957
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002958 class Wrapped:
2959 pass
2960 Wrapped.__wrapped__ = lambda a: None
2961 self.assertEqual(self.signature(Wrapped),
2962 ((('a', ..., ..., "positional_or_keyword"),),
2963 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002964 # wrapper loop:
2965 Wrapped.__wrapped__ = Wrapped
2966 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2967 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002968
2969 def test_signature_on_lambdas(self):
2970 self.assertEqual(self.signature((lambda a=10: a)),
2971 ((('a', 10, ..., "positional_or_keyword"),),
2972 ...))
2973
2974 def test_signature_equality(self):
2975 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002976 self.assertFalse(inspect.signature(foo) == 42)
2977 self.assertTrue(inspect.signature(foo) != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03002978 self.assertTrue(inspect.signature(foo) == ALWAYS_EQ)
2979 self.assertFalse(inspect.signature(foo) != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002980
2981 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002982 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2983 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002984 self.assertEqual(
2985 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002986
2987 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002988 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2989 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002990 self.assertNotEqual(
2991 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002992
2993 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002994 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2995 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04002996 self.assertNotEqual(
2997 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002998
2999 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003000 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3001 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003002 self.assertNotEqual(
3003 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003004
3005 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003006 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3007 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003008 self.assertNotEqual(
3009 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003010
3011 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003012 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3013 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003014 self.assertNotEqual(
3015 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003016 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003017 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
3018 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003019 self.assertNotEqual(
3020 hash(inspect.signature(spam)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003021
3022 def foo(*, a, b, c): pass
3023 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003024 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3025 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003026 self.assertEqual(
3027 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003028
3029 def foo(*, a=1, b, c): pass
3030 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003031 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3032 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003033 self.assertEqual(
3034 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003035
3036 def foo(pos, *, a=1, b, c): pass
3037 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003038 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3039 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003040 self.assertEqual(
3041 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003042
3043 def foo(pos, *, a, b, c): pass
3044 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003045 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
3046 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003047 self.assertNotEqual(
3048 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003049
3050 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
3051 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003052 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
3053 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Yury Selivanov08d4a4f2014-09-12 15:48:02 -04003054 self.assertEqual(
3055 hash(inspect.signature(foo)), hash(inspect.signature(bar)))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003056
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003057 def test_signature_hashable(self):
3058 S = inspect.Signature
3059 P = inspect.Parameter
3060
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003061 def foo(a): pass
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003062 foo_sig = inspect.signature(foo)
3063
3064 manual_sig = S(parameters=[P('a', P.POSITIONAL_OR_KEYWORD)])
3065
3066 self.assertEqual(hash(foo_sig), hash(manual_sig))
3067 self.assertNotEqual(hash(foo_sig),
3068 hash(manual_sig.replace(return_annotation='spam')))
3069
3070 def bar(a) -> 1: pass
3071 self.assertNotEqual(hash(foo_sig), hash(inspect.signature(bar)))
3072
3073 def foo(a={}): pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003074 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003075 hash(inspect.signature(foo))
3076
3077 def foo(a) -> {}: pass
3078 with self.assertRaisesRegex(TypeError, 'unhashable type'):
3079 hash(inspect.signature(foo))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003080
3081 def test_signature_str(self):
3082 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
3083 pass
3084 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003085 '(a: int = 1, *, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003086
3087 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
3088 pass
3089 self.assertEqual(str(inspect.signature(foo)),
Dong-hee Na762b9572017-11-16 03:30:59 +09003090 '(a: int = 1, *args, b, c=None, **kwargs) -> 42')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003091
3092 def foo():
3093 pass
3094 self.assertEqual(str(inspect.signature(foo)), '()')
3095
3096 def test_signature_str_positional_only(self):
3097 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05003098 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003099
3100 def test(a_po, *, b, **kwargs):
3101 return a_po, kwargs
3102
3103 sig = inspect.signature(test)
3104 new_params = list(sig.parameters.values())
3105 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
3106 test.__signature__ = sig.replace(parameters=new_params)
3107
3108 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05003109 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003110
Yury Selivanov2393dca2014-01-27 15:07:58 -05003111 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
3112 '(foo, /)')
3113
3114 self.assertEqual(str(S(parameters=[
3115 P('foo', P.POSITIONAL_ONLY),
3116 P('bar', P.VAR_KEYWORD)])),
3117 '(foo, /, **bar)')
3118
3119 self.assertEqual(str(S(parameters=[
3120 P('foo', P.POSITIONAL_ONLY),
3121 P('bar', P.VAR_POSITIONAL)])),
3122 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003123
3124 def test_signature_replace_anno(self):
3125 def test() -> 42:
3126 pass
3127
3128 sig = inspect.signature(test)
3129 sig = sig.replace(return_annotation=None)
3130 self.assertIs(sig.return_annotation, None)
3131 sig = sig.replace(return_annotation=sig.empty)
3132 self.assertIs(sig.return_annotation, sig.empty)
3133 sig = sig.replace(return_annotation=42)
3134 self.assertEqual(sig.return_annotation, 42)
3135 self.assertEqual(sig, inspect.signature(test))
3136
Yury Selivanov34ce99f2014-02-18 12:49:41 -05003137 def test_signature_on_mangled_parameters(self):
3138 class Spam:
3139 def foo(self, __p1:1=2, *, __p2:2=3):
3140 pass
3141 class Ham(Spam):
3142 pass
3143
3144 self.assertEqual(self.signature(Spam.foo),
3145 ((('self', ..., ..., "positional_or_keyword"),
3146 ('_Spam__p1', 2, 1, "positional_or_keyword"),
3147 ('_Spam__p2', 3, 2, "keyword_only")),
3148 ...))
3149
3150 self.assertEqual(self.signature(Spam.foo),
3151 self.signature(Ham.foo))
3152
Yury Selivanovda396452014-03-27 12:09:24 -04003153 def test_signature_from_callable_python_obj(self):
3154 class MySignature(inspect.Signature): pass
3155 def foo(a, *, b:1): pass
3156 foo_sig = MySignature.from_callable(foo)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003157 self.assertIsInstance(foo_sig, MySignature)
3158
3159 def test_signature_from_callable_class(self):
3160 # A regression test for a class inheriting its signature from `object`.
3161 class MySignature(inspect.Signature): pass
3162 class foo: pass
3163 foo_sig = MySignature.from_callable(foo)
3164 self.assertIsInstance(foo_sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003165
3166 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3167 "Signature information for builtins requires docstrings")
3168 def test_signature_from_callable_builtin_obj(self):
3169 class MySignature(inspect.Signature): pass
3170 sig = MySignature.from_callable(_pickle.Pickler)
Gregory P. Smith5b9ff7a2019-09-13 17:13:51 +01003171 self.assertIsInstance(sig, MySignature)
Yury Selivanovda396452014-03-27 12:09:24 -04003172
larryhastingsf36ba122018-01-28 11:13:09 -08003173 def test_signature_definition_order_preserved_on_kwonly(self):
3174 for fn in signatures_with_lexicographic_keyword_only_parameters():
3175 signature = inspect.signature(fn)
3176 l = list(signature.parameters)
3177 sorted_l = sorted(l)
3178 self.assertTrue(l)
3179 self.assertEqual(l, sorted_l)
3180 signature = inspect.signature(unsorted_keyword_only_parameters_fn)
3181 l = list(signature.parameters)
3182 self.assertEqual(l, unsorted_keyword_only_parameters)
3183
Jens Reidel611836a2020-03-18 03:22:46 +01003184 def test_signater_parameters_is_ordered(self):
3185 p1 = inspect.signature(lambda x, y: None).parameters
3186 p2 = inspect.signature(lambda y, x: None).parameters
3187 self.assertNotEqual(p1, p2)
3188
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003189
3190class TestParameterObject(unittest.TestCase):
3191 def test_signature_parameter_kinds(self):
3192 P = inspect.Parameter
3193 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
3194 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
3195
3196 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
3197 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
3198
3199 def test_signature_parameter_object(self):
3200 p = inspect.Parameter('foo', default=10,
3201 kind=inspect.Parameter.POSITIONAL_ONLY)
3202 self.assertEqual(p.name, 'foo')
3203 self.assertEqual(p.default, 10)
3204 self.assertIs(p.annotation, p.empty)
3205 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
3206
Dong-hee Naa9cab432018-05-30 00:04:08 +09003207 with self.assertRaisesRegex(ValueError, "value '123' is "
3208 "not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003209 inspect.Parameter('foo', default=10, kind='123')
3210
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003211 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003212 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
3213
Yury Selivanov2393dca2014-01-27 15:07:58 -05003214 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003215 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
3216
Yury Selivanov2393dca2014-01-27 15:07:58 -05003217 with self.assertRaisesRegex(ValueError,
3218 'is not a valid parameter name'):
3219 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
3220
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003221 with self.assertRaisesRegex(ValueError,
3222 'is not a valid parameter name'):
3223 inspect.Parameter('.a', kind=inspect.Parameter.VAR_KEYWORD)
3224
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003225 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003226 inspect.Parameter('a', default=42,
3227 kind=inspect.Parameter.VAR_KEYWORD)
3228
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003229 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003230 inspect.Parameter('a', default=42,
3231 kind=inspect.Parameter.VAR_POSITIONAL)
3232
3233 p = inspect.Parameter('a', default=42,
3234 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003235 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003236 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
3237
3238 self.assertTrue(repr(p).startswith('<Parameter'))
Yury Selivanov374375d2014-03-27 12:41:53 -04003239 self.assertTrue('"a=42"' in repr(p))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003240
Yury Selivanov67ae50e2014-04-08 11:46:50 -04003241 def test_signature_parameter_hashable(self):
3242 P = inspect.Parameter
3243 foo = P('foo', kind=P.POSITIONAL_ONLY)
3244 self.assertEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY)))
3245 self.assertNotEqual(hash(foo), hash(P('foo', kind=P.POSITIONAL_ONLY,
3246 default=42)))
3247 self.assertNotEqual(hash(foo),
3248 hash(foo.replace(kind=P.VAR_POSITIONAL)))
3249
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003250 def test_signature_parameter_equality(self):
3251 P = inspect.Parameter
3252 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
3253
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003254 self.assertTrue(p == p)
3255 self.assertFalse(p != p)
3256 self.assertFalse(p == 42)
3257 self.assertTrue(p != 42)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003258 self.assertTrue(p == ALWAYS_EQ)
3259 self.assertFalse(p != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003260
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003261 self.assertTrue(p == P('foo', default=42,
3262 kind=inspect.Parameter.KEYWORD_ONLY))
3263 self.assertFalse(p != P('foo', default=42,
3264 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003265
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003266 def test_signature_parameter_replace(self):
3267 p = inspect.Parameter('foo', default=42,
3268 kind=inspect.Parameter.KEYWORD_ONLY)
3269
3270 self.assertIsNot(p, p.replace())
3271 self.assertEqual(p, p.replace())
3272
3273 p2 = p.replace(annotation=1)
3274 self.assertEqual(p2.annotation, 1)
3275 p2 = p2.replace(annotation=p2.empty)
3276 self.assertEqual(p, p2)
3277
3278 p2 = p2.replace(name='bar')
3279 self.assertEqual(p2.name, 'bar')
3280 self.assertNotEqual(p2, p)
3281
Yury Selivanov2393dca2014-01-27 15:07:58 -05003282 with self.assertRaisesRegex(ValueError,
3283 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003284 p2 = p2.replace(name=p2.empty)
3285
3286 p2 = p2.replace(name='foo', default=None)
3287 self.assertIs(p2.default, None)
3288 self.assertNotEqual(p2, p)
3289
3290 p2 = p2.replace(name='foo', default=p2.empty)
3291 self.assertIs(p2.default, p2.empty)
3292
3293
3294 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
3295 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
3296 self.assertNotEqual(p2, p)
3297
Dong-hee Naa9cab432018-05-30 00:04:08 +09003298 with self.assertRaisesRegex(ValueError,
3299 "value <class 'inspect._empty'> "
3300 "is not a valid Parameter.kind"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003301 p2 = p2.replace(kind=p2.empty)
3302
3303 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
3304 self.assertEqual(p2, p)
3305
3306 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003307 with self.assertRaisesRegex(TypeError, 'name must be a str'):
3308 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003309
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003310 @cpython_only
3311 def test_signature_parameter_implicit(self):
3312 with self.assertRaisesRegex(ValueError,
Dong-hee Naa9cab432018-05-30 00:04:08 +09003313 'implicit arguments must be passed as '
3314 'positional or keyword arguments, '
3315 'not positional-only'):
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003316 inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY)
3317
3318 param = inspect.Parameter(
3319 '.0', kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
3320 self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_ONLY)
3321 self.assertEqual(param.name, 'implicit0')
3322
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003323 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05003324 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003325
3326 with self.assertRaises(AttributeError):
3327 p.foo = 'bar'
3328
3329 with self.assertRaises(AttributeError):
3330 p.kind = 123
3331
3332
3333class TestSignatureBind(unittest.TestCase):
3334 @staticmethod
3335 def call(func, *args, **kwargs):
3336 sig = inspect.signature(func)
3337 ba = sig.bind(*args, **kwargs)
3338 return func(*ba.args, **ba.kwargs)
3339
3340 def test_signature_bind_empty(self):
3341 def test():
3342 return 42
3343
3344 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003345 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003346 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003347 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003348 self.call(test, 1, spam=10)
Yury Selivanov86872752015-05-19 00:27:49 -04003349 with self.assertRaisesRegex(
3350 TypeError, "got an unexpected keyword argument 'spam'"):
3351
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003352 self.call(test, spam=1)
3353
3354 def test_signature_bind_var(self):
3355 def test(*args, **kwargs):
3356 return args, kwargs
3357
3358 self.assertEqual(self.call(test), ((), {}))
3359 self.assertEqual(self.call(test, 1), ((1,), {}))
3360 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
3361 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
3362 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
3363 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
3364 self.assertEqual(self.call(test, 1, 2, foo='bar'),
3365 ((1, 2), {'foo': 'bar'}))
3366
3367 def test_signature_bind_just_args(self):
3368 def test(a, b, c):
3369 return a, b, c
3370
3371 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3372
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003373 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003374 self.call(test, 1, 2, 3, 4)
3375
Yury Selivanov86872752015-05-19 00:27:49 -04003376 with self.assertRaisesRegex(TypeError,
3377 "missing a required argument: 'b'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003378 self.call(test, 1)
3379
Yury Selivanov86872752015-05-19 00:27:49 -04003380 with self.assertRaisesRegex(TypeError,
3381 "missing a required argument: 'a'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003382 self.call(test)
3383
3384 def test(a, b, c=10):
3385 return a, b, c
3386 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3387 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
3388
3389 def test(a=1, b=2, c=3):
3390 return a, b, c
3391 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
3392 self.assertEqual(self.call(test, a=10), (10, 2, 3))
3393 self.assertEqual(self.call(test, b=10), (1, 10, 3))
3394
3395 def test_signature_bind_varargs_order(self):
3396 def test(*args):
3397 return args
3398
3399 self.assertEqual(self.call(test), ())
3400 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
3401
3402 def test_signature_bind_args_and_varargs(self):
3403 def test(a, b, c=3, *args):
3404 return a, b, c, args
3405
3406 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
3407 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
3408 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
3409 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
3410
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003411 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003412 "multiple values for argument 'c'"):
3413 self.call(test, 1, 2, 3, c=4)
3414
3415 def test_signature_bind_just_kwargs(self):
3416 def test(**kwargs):
3417 return kwargs
3418
3419 self.assertEqual(self.call(test), {})
3420 self.assertEqual(self.call(test, foo='bar', spam='ham'),
3421 {'foo': 'bar', 'spam': 'ham'})
3422
3423 def test_signature_bind_args_and_kwargs(self):
3424 def test(a, b, c=3, **kwargs):
3425 return a, b, c, kwargs
3426
3427 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
3428 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
3429 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3430 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
3431 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3432 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
3433 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3434 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
3435 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
3436 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
3437 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
3438 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
3439 (1, 2, 4, {'foo': 'bar'}))
3440 self.assertEqual(self.call(test, c=5, a=4, b=3),
3441 (4, 3, 5, {}))
3442
3443 def test_signature_bind_kwonly(self):
3444 def test(*, foo):
3445 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003446 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003447 'too many positional arguments'):
3448 self.call(test, 1)
3449 self.assertEqual(self.call(test, foo=1), 1)
3450
3451 def test(a, *, foo=1, bar):
3452 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003453 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003454 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003455 self.call(test, 1)
3456
3457 def test(foo, *, bar):
3458 return foo, bar
3459 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
3460 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
3461
Yury Selivanov86872752015-05-19 00:27:49 -04003462 with self.assertRaisesRegex(
3463 TypeError, "got an unexpected keyword argument 'spam'"):
3464
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003465 self.call(test, bar=2, foo=1, spam=10)
3466
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003467 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003468 'too many positional arguments'):
3469 self.call(test, 1, 2)
3470
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003471 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003472 'too many positional arguments'):
3473 self.call(test, 1, 2, bar=2)
3474
Yury Selivanov86872752015-05-19 00:27:49 -04003475 with self.assertRaisesRegex(
3476 TypeError, "got an unexpected keyword argument 'spam'"):
3477
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003478 self.call(test, 1, bar=2, spam='ham')
3479
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003480 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003481 "missing a required argument: 'bar'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003482 self.call(test, 1)
3483
3484 def test(foo, *, bar, **bin):
3485 return foo, bar, bin
3486 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
3487 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
3488 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
3489 (1, 2, {'spam': 'ham'}))
3490 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
3491 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003492 with self.assertRaisesRegex(TypeError,
Yury Selivanov86872752015-05-19 00:27:49 -04003493 "missing a required argument: 'foo'"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003494 self.call(test, spam='ham', bar=2)
3495 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
3496 (1, 2, {'bin': 1, 'spam': 10}))
3497
3498 def test_signature_bind_arguments(self):
3499 def test(a, *args, b, z=100, **kwargs):
3500 pass
3501 sig = inspect.signature(test)
3502 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
3503 # we won't have 'z' argument in the bound arguments object, as we didn't
3504 # pass it to the 'bind'
3505 self.assertEqual(tuple(ba.arguments.items()),
3506 (('a', 10), ('args', (20,)), ('b', 30),
3507 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
3508 self.assertEqual(ba.kwargs,
3509 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
3510 self.assertEqual(ba.args, (10, 20))
3511
3512 def test_signature_bind_positional_only(self):
3513 P = inspect.Parameter
3514
3515 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
3516 return a_po, b_po, c_po, foo, bar, kwargs
3517
3518 sig = inspect.signature(test)
3519 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
3520 for name in ('a_po', 'b_po', 'c_po'):
3521 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
3522 new_sig = sig.replace(parameters=new_params.values())
3523 test.__signature__ = new_sig
3524
3525 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
3526 (1, 2, 4, 5, 6, {}))
3527
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003528 self.assertEqual(self.call(test, 1, 2),
3529 (1, 2, 3, 42, 50, {}))
3530
3531 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
3532 (1, 2, 3, 4, 5, {}))
3533
3534 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
3535 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
3536
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003537 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003538 self.call(test, 1, 2, c_po=4)
3539
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003540 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003541 self.call(test, a_po=1, b_po=2)
3542
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01003543 def test_signature_bind_with_self_arg(self):
3544 # Issue #17071: one of the parameters is named "self
3545 def test(a, self, b):
3546 pass
3547 sig = inspect.signature(test)
3548 ba = sig.bind(1, 2, 3)
3549 self.assertEqual(ba.args, (1, 2, 3))
3550 ba = sig.bind(1, self=2, b=3)
3551 self.assertEqual(ba.args, (1, 2, 3))
3552
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003553 def test_signature_bind_vararg_name(self):
3554 def test(a, *args):
3555 return a, args
3556 sig = inspect.signature(test)
3557
Yury Selivanov86872752015-05-19 00:27:49 -04003558 with self.assertRaisesRegex(
3559 TypeError, "got an unexpected keyword argument 'args'"):
3560
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05003561 sig.bind(a=0, args=1)
3562
3563 def test(*args, **kwargs):
3564 return args, kwargs
3565 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
3566
3567 sig = inspect.signature(test)
3568 ba = sig.bind(args=1)
3569 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
3570
Nick Coghlanb4b966e2016-06-04 14:40:03 -07003571 @cpython_only
3572 def test_signature_bind_implicit_arg(self):
3573 # Issue #19611: getcallargs should work with set comprehensions
3574 def make_set():
3575 return {z * z for z in range(5)}
3576 setcomp_code = make_set.__code__.co_consts[1]
3577 setcomp_func = types.FunctionType(setcomp_code, {})
3578
3579 iterator = iter(range(5))
3580 self.assertEqual(self.call(setcomp_func, iterator), {0, 1, 4, 9, 16})
3581
Pablo Galindof3ef06a2019-10-15 12:40:02 +01003582 def test_signature_bind_posonly_kwargs(self):
3583 def foo(bar, /, **kwargs):
3584 return bar, kwargs.get(bar)
3585
3586 sig = inspect.signature(foo)
3587 result = sig.bind("pos-only", bar="keyword")
3588
3589 self.assertEqual(result.kwargs, {"bar": "keyword"})
3590 self.assertIn(("bar", "pos-only"), result.arguments.items())
3591
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003592
3593class TestBoundArguments(unittest.TestCase):
3594 def test_signature_bound_arguments_unhashable(self):
3595 def foo(a): pass
3596 ba = inspect.signature(foo).bind(1)
3597
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02003598 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003599 hash(ba)
3600
3601 def test_signature_bound_arguments_equality(self):
3602 def foo(a): pass
3603 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003604 self.assertTrue(ba == ba)
3605 self.assertFalse(ba != ba)
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03003606 self.assertTrue(ba == ALWAYS_EQ)
3607 self.assertFalse(ba != ALWAYS_EQ)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003608
3609 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003610 self.assertTrue(ba == ba2)
3611 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003612
3613 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003614 self.assertFalse(ba == ba3)
3615 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003616 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003617 self.assertTrue(ba == ba3)
3618 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003619
3620 def bar(b): pass
3621 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03003622 self.assertFalse(ba == ba4)
3623 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003624
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003625 def foo(*, a, b): pass
3626 sig = inspect.signature(foo)
3627 ba1 = sig.bind(a=1, b=2)
3628 ba2 = sig.bind(b=2, a=1)
Serhiy Storchaka2489bd52015-07-18 23:20:50 +03003629 self.assertTrue(ba1 == ba2)
3630 self.assertFalse(ba1 != ba2)
Yury Selivanov4cfd4ea2015-05-14 18:30:27 -04003631
Yury Selivanova5d63dd2014-03-27 11:31:43 -04003632 def test_signature_bound_arguments_pickle(self):
3633 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3634 sig = inspect.signature(foo)
3635 ba = sig.bind(20, 30, z={})
3636
3637 for ver in range(pickle.HIGHEST_PROTOCOL + 1):
3638 with self.subTest(pickle_ver=ver):
3639 ba_pickled = pickle.loads(pickle.dumps(ba, ver))
3640 self.assertEqual(ba, ba_pickled)
3641
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003642 def test_signature_bound_arguments_repr(self):
3643 def foo(a, b, *, c:1={}, **kw) -> {42:'ham'}: pass
3644 sig = inspect.signature(foo)
3645 ba = sig.bind(20, 30, z={})
Yury Selivanovf229bc52015-05-15 12:53:56 -04003646 self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
Yury Selivanov3f6538f2015-05-14 18:47:17 -04003647
Yury Selivanovb907a512015-05-16 13:45:09 -04003648 def test_signature_bound_arguments_apply_defaults(self):
3649 def foo(a, b=1, *args, c:1={}, **kw): pass
3650 sig = inspect.signature(foo)
3651
3652 ba = sig.bind(20)
3653 ba.apply_defaults()
3654 self.assertEqual(
3655 list(ba.arguments.items()),
3656 [('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
3657
3658 # Make sure that we preserve the order:
3659 # i.e. 'c' should be *before* 'kw'.
3660 ba = sig.bind(10, 20, 30, d=1)
3661 ba.apply_defaults()
3662 self.assertEqual(
3663 list(ba.arguments.items()),
3664 [('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
3665
3666 # Make sure that BoundArguments produced by bind_partial()
3667 # are supported.
3668 def foo(a, b): pass
3669 sig = inspect.signature(foo)
3670 ba = sig.bind_partial(20)
3671 ba.apply_defaults()
3672 self.assertEqual(
3673 list(ba.arguments.items()),
3674 [('a', 20)])
3675
3676 # Test no args
3677 def foo(): pass
3678 sig = inspect.signature(foo)
3679 ba = sig.bind()
3680 ba.apply_defaults()
3681 self.assertEqual(list(ba.arguments.items()), [])
3682
Yury Selivanovf9e1f2b2016-03-02 11:07:47 -05003683 # Make sure a no-args binding still acquires proper defaults.
3684 def foo(a='spam'): pass
3685 sig = inspect.signature(foo)
3686 ba = sig.bind()
3687 ba.apply_defaults()
3688 self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
3689
Rémi Lapeyre2cca8ef2020-01-28 13:47:03 +01003690 def test_signature_bound_arguments_arguments_type(self):
3691 def foo(a): pass
3692 ba = inspect.signature(foo).bind(1)
3693 self.assertIs(type(ba.arguments), dict)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003694
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003695class TestSignaturePrivateHelpers(unittest.TestCase):
3696 def test_signature_get_bound_param(self):
3697 getter = inspect._signature_get_bound_param
3698
3699 self.assertEqual(getter('($self)'), 'self')
3700 self.assertEqual(getter('($self, obj)'), 'self')
3701 self.assertEqual(getter('($cls, /, obj)'), 'cls')
3702
Larry Hastings2623c8c2014-02-08 22:15:29 -08003703 def _strip_non_python_syntax(self, input,
3704 clean_signature, self_parameter, last_positional_only):
3705 computed_clean_signature, \
3706 computed_self_parameter, \
3707 computed_last_positional_only = \
3708 inspect._signature_strip_non_python_syntax(input)
3709 self.assertEqual(computed_clean_signature, clean_signature)
3710 self.assertEqual(computed_self_parameter, self_parameter)
3711 self.assertEqual(computed_last_positional_only, last_positional_only)
3712
3713 def test_signature_strip_non_python_syntax(self):
3714 self._strip_non_python_syntax(
3715 "($module, /, path, mode, *, dir_fd=None, " +
3716 "effective_ids=False,\n follow_symlinks=True)",
3717 "(module, path, mode, *, dir_fd=None, " +
3718 "effective_ids=False, follow_symlinks=True)",
3719 0,
3720 0)
3721
3722 self._strip_non_python_syntax(
3723 "($module, word, salt, /)",
3724 "(module, word, salt)",
3725 0,
3726 2)
3727
3728 self._strip_non_python_syntax(
3729 "(x, y=None, z=None, /)",
3730 "(x, y=None, z=None)",
3731 None,
3732 2)
3733
3734 self._strip_non_python_syntax(
3735 "(x, y=None, z=None)",
3736 "(x, y=None, z=None)",
3737 None,
3738 None)
3739
3740 self._strip_non_python_syntax(
3741 "(x,\n y=None,\n z = None )",
3742 "(x, y=None, z=None)",
3743 None,
3744 None)
3745
3746 self._strip_non_python_syntax(
3747 "",
3748 "",
3749 None,
3750 None)
3751
3752 self._strip_non_python_syntax(
3753 None,
3754 None,
3755 None,
3756 None)
3757
Nick Coghlan9c680b02015-04-13 12:54:54 -04003758class TestSignatureDefinitions(unittest.TestCase):
3759 # This test case provides a home for checking that particular APIs
3760 # have signatures available for introspection
3761
3762 @cpython_only
3763 @unittest.skipIf(MISSING_C_DOCSTRINGS,
3764 "Signature information for builtins requires docstrings")
3765 def test_builtins_have_signatures(self):
3766 # This checks all builtin callables in CPython have signatures
3767 # A few have signatures Signature can't yet handle, so we skip those
3768 # since they will have to wait until PEP 457 adds the required
3769 # introspection support to the inspect module
3770 # Some others also haven't been converted yet for various other
3771 # reasons, so we also skip those for the time being, but design
3772 # the test to fail in order to indicate when it needs to be
3773 # updated.
3774 no_signature = set()
3775 # These need PEP 457 groups
3776 needs_groups = {"range", "slice", "dir", "getattr",
3777 "next", "iter", "vars"}
3778 no_signature |= needs_groups
3779 # These need PEP 457 groups or a signature change to accept None
3780 needs_semantic_update = {"round"}
3781 no_signature |= needs_semantic_update
3782 # These need *args support in Argument Clinic
Barry Warsaw36c1d1f2017-10-05 12:11:18 -04003783 needs_varargs = {"breakpoint", "min", "max", "print",
3784 "__build_class__"}
Nick Coghlan9c680b02015-04-13 12:54:54 -04003785 no_signature |= needs_varargs
3786 # These simply weren't covered in the initial AC conversion
3787 # for builtin callables
3788 not_converted_yet = {"open", "__import__"}
3789 no_signature |= not_converted_yet
3790 # These builtin types are expected to provide introspection info
3791 types_with_signatures = set()
3792 # Check the signatures we expect to be there
3793 ns = vars(builtins)
3794 for name, obj in sorted(ns.items()):
3795 if not callable(obj):
3796 continue
3797 # The builtin types haven't been converted to AC yet
3798 if isinstance(obj, type) and (name not in types_with_signatures):
3799 # Note that this also skips all the exception types
3800 no_signature.add(name)
3801 if (name in no_signature):
3802 # Not yet converted
3803 continue
3804 with self.subTest(builtin=name):
3805 self.assertIsNotNone(inspect.signature(obj))
3806 # Check callables that haven't been converted don't claim a signature
3807 # This ensures this test will start failing as more signatures are
3808 # added, so the affected items can be moved into the scope of the
3809 # regression test above
3810 for name in no_signature:
3811 with self.subTest(builtin=name):
3812 self.assertIsNone(obj.__text_signature__)
3813
Serhiy Storchakad53cf992019-05-06 22:40:27 +03003814 def test_python_function_override_signature(self):
3815 def func(*args, **kwargs):
3816 pass
3817 func.__text_signature__ = '($self, a, b=1, *args, c, d=2, **kwargs)'
3818 sig = inspect.signature(func)
3819 self.assertIsNotNone(sig)
3820 self.assertEqual(str(sig), '(self, /, a, b=1, *args, c, d=2, **kwargs)')
3821 func.__text_signature__ = '($self, a, b=1, /, *args, c, d=2, **kwargs)'
3822 sig = inspect.signature(func)
3823 self.assertEqual(str(sig), '(self, a, b=1, /, *args, c, d=2, **kwargs)')
3824
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003825
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003826class NTimesUnwrappable:
3827 def __init__(self, n):
3828 self.n = n
3829 self._next = None
3830
3831 @property
3832 def __wrapped__(self):
3833 if self.n <= 0:
3834 raise Exception("Unwrapped too many times")
3835 if self._next is None:
3836 self._next = NTimesUnwrappable(self.n - 1)
3837 return self._next
3838
Nick Coghlane8c45d62013-07-28 20:00:01 +10003839class TestUnwrap(unittest.TestCase):
3840
3841 def test_unwrap_one(self):
3842 def func(a, b):
3843 return a + b
3844 wrapper = functools.lru_cache(maxsize=20)(func)
3845 self.assertIs(inspect.unwrap(wrapper), func)
3846
3847 def test_unwrap_several(self):
3848 def func(a, b):
3849 return a + b
3850 wrapper = func
3851 for __ in range(10):
3852 @functools.wraps(wrapper)
3853 def wrapper():
3854 pass
3855 self.assertIsNot(wrapper.__wrapped__, func)
3856 self.assertIs(inspect.unwrap(wrapper), func)
3857
3858 def test_stop(self):
3859 def func1(a, b):
3860 return a + b
3861 @functools.wraps(func1)
3862 def func2():
3863 pass
3864 @functools.wraps(func2)
3865 def wrapper():
3866 pass
3867 func2.stop_here = 1
3868 unwrapped = inspect.unwrap(wrapper,
3869 stop=(lambda f: hasattr(f, "stop_here")))
3870 self.assertIs(unwrapped, func2)
3871
3872 def test_cycle(self):
3873 def func1(): pass
3874 func1.__wrapped__ = func1
3875 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3876 inspect.unwrap(func1)
3877
3878 def func2(): pass
3879 func2.__wrapped__ = func1
3880 func1.__wrapped__ = func2
3881 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3882 inspect.unwrap(func1)
3883 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3884 inspect.unwrap(func2)
3885
3886 def test_unhashable(self):
3887 def func(): pass
3888 func.__wrapped__ = None
3889 class C:
3890 __hash__ = None
3891 __wrapped__ = func
3892 self.assertIsNone(inspect.unwrap(C()))
3893
Thomas Kluyverf9169ce2017-05-23 04:27:52 +01003894 def test_recursion_limit(self):
3895 obj = NTimesUnwrappable(sys.getrecursionlimit() + 1)
3896 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3897 inspect.unwrap(obj)
3898
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003899class TestMain(unittest.TestCase):
3900 def test_only_source(self):
3901 module = importlib.import_module('unittest')
3902 rc, out, err = assert_python_ok('-m', 'inspect',
3903 'unittest')
3904 lines = out.decode().splitlines()
3905 # ignore the final newline
3906 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3907 self.assertEqual(err, b'')
3908
Yury Selivanov42407ab2014-06-23 10:23:50 -07003909 def test_custom_getattr(self):
3910 def foo():
3911 pass
3912 foo.__signature__ = 42
3913 with self.assertRaises(TypeError):
3914 inspect.signature(foo)
3915
Brett Cannon634a8fc2013-10-02 10:25:42 -04003916 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003917 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003918 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003919 rc, out, err = assert_python_ok('-m', 'inspect',
3920 'concurrent.futures:ThreadPoolExecutor')
3921 lines = out.decode().splitlines()
3922 # ignore the final newline
3923 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003924 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003925 self.assertEqual(err, b'')
3926
3927 def test_builtins(self):
3928 module = importlib.import_module('unittest')
3929 _, out, err = assert_python_failure('-m', 'inspect',
3930 'sys')
3931 lines = err.decode().splitlines()
3932 self.assertEqual(lines, ["Can't get info for builtin modules."])
3933
3934 def test_details(self):
3935 module = importlib.import_module('unittest')
Victor Stinner9def2842016-01-18 12:15:08 +01003936 args = support.optim_args_from_interpreter_flags()
3937 rc, out, err = assert_python_ok(*args, '-m', 'inspect',
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003938 'unittest', '--details')
3939 output = out.decode()
3940 # Just a quick sanity check on the output
3941 self.assertIn(module.__name__, output)
3942 self.assertIn(module.__file__, output)
Victor Stinner9def2842016-01-18 12:15:08 +01003943 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003944 self.assertEqual(err, b'')
3945
3946
Yury Selivanovef1e7502014-12-08 16:05:34 -05003947class TestReload(unittest.TestCase):
3948
3949 src_before = textwrap.dedent("""\
3950def foo():
3951 print("Bla")
3952 """)
3953
3954 src_after = textwrap.dedent("""\
3955def foo():
3956 print("Oh no!")
3957 """)
3958
3959 def assertInspectEqual(self, path, source):
3960 inspected_src = inspect.getsource(source)
3961 with open(path) as src:
3962 self.assertEqual(
3963 src.read().splitlines(True),
3964 inspected_src.splitlines(True)
3965 )
3966
3967 def test_getsource_reload(self):
3968 # see issue 1218234
3969 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3970 module = importlib.import_module(name)
3971 self.assertInspectEqual(path, module)
3972 with open(path, 'w') as src:
3973 src.write(self.src_after)
3974 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003975
Nick Coghlane8c45d62013-07-28 20:00:01 +10003976
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003977def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003978 run_unittest(
3979 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3980 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3981 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003982 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003983 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan9c680b02015-04-13 12:54:54 -04003984 TestBoundArguments, TestSignaturePrivateHelpers,
Aaron Hall, MBA4054b172018-05-20 19:46:42 -04003985 TestSignatureDefinitions, TestIsDataDescriptor,
Yury Selivanov5376ba92015-06-22 12:19:30 -04003986 TestGetClosureVars, TestUnwrap, TestMain, TestReload,
Vladimir Matveev91cb2982018-08-24 07:18:00 -07003987 TestGetCoroutineState, TestGettingSourceOfToplevelFrames
Michael Foord95fc51d2010-11-20 15:07:30 +00003988 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003989
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003990if __name__ == "__main__":
3991 test_main()