blob: 1a124b5db2360ad44812d5be63f5921740668390 [file] [log] [blame]
Guido van Rossum813b0e52007-05-21 18:11:34 +00001import collections
Larry Hastings5c661892014-01-24 06:17:25 -08002import datetime
Nick Coghlane8c45d62013-07-28 20:00:01 +10003import functools
Nick Coghlanf94a16b2013-09-22 22:46:49 +10004import importlib
Larry Hastings5c661892014-01-24 06:17:25 -08005import inspect
6import io
7import linecache
8import os
Christian Heimesa3538eb2007-11-06 11:44:48 +00009from os.path import normcase
Larry Hastings5c661892014-01-24 06:17:25 -080010import _pickle
11import re
12import shutil
13import sys
14import types
Yury Selivanov7de29682014-12-08 18:00:25 -050015import textwrap
Larry Hastings5c661892014-01-24 06:17:25 -080016import unicodedata
17import unittest
Yury Selivanov8dfb4572014-02-21 18:30:53 -050018import unittest.mock
Larry Hastings5c661892014-01-24 06:17:25 -080019
Brett Cannon634a8fc2013-10-02 10:25:42 -040020try:
21 from concurrent.futures import ThreadPoolExecutor
22except ImportError:
23 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000024
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020025from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -080026from test.support import MISSING_C_DOCSTRINGS
Nick Coghlanf94a16b2013-09-22 22:46:49 +100027from test.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000028from test import inspect_fodder as mod
29from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000030
Yury Selivanov7de29682014-12-08 18:00:25 -050031from test.test_import import _ready_to_import
32
R. David Murray74b89242009-05-13 17:33:03 +000033
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000034# Functions tested in this suite:
35# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000036# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
37# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
38# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
39# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000040
Nick Coghlanf088e5e2008-12-14 11:50:48 +000041# NOTE: There are some additional tests relating to interaction with
42# zipimport in the test_zipimport_support test module.
43
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000044modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000045if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000046 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000047
Christian Heimesa3538eb2007-11-06 11:44:48 +000048# Normalize file names: on Windows, the case of file names of compiled
49# modules depends on the path used to start the python executable.
50modfile = normcase(modfile)
51
52def revise(filename, *args):
53 return (normcase(filename),) + args
54
Georg Brandl1a3284e2007-12-02 09:40:06 +000055import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000056
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000057git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000058
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000059class IsTestBase(unittest.TestCase):
60 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
61 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000062 inspect.ismodule, inspect.istraceback,
63 inspect.isgenerator, inspect.isgeneratorfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000064
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000065 def istest(self, predicate, exp):
66 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000067 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000068
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000069 for other in self.predicates - set([predicate]):
Christian Heimes7131fd92008-02-19 14:21:46 +000070 if predicate == inspect.isgeneratorfunction and\
71 other == inspect.isfunction:
72 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000073 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000074
Christian Heimes7131fd92008-02-19 14:21:46 +000075def generator_function_example(self):
76 for i in range(2):
77 yield i
78
Serhiy Storchaka3018cc42015-07-18 23:19:05 +030079class EqualsToAll:
80 def __eq__(self, other):
81 return True
82
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000083class TestPredicates(IsTestBase):
Christian Heimes227c8002008-03-03 20:34:40 +000084 def test_sixteen(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +000085 count = len([x for x in dir(inspect) if x.startswith('is')])
Christian Heimes7131fd92008-02-19 14:21:46 +000086 # This test is here for remember you to update Doc/library/inspect.rst
Christian Heimes78644762008-03-04 23:39:23 +000087 # which claims there are 16 such functions
Christian Heimes227c8002008-03-03 20:34:40 +000088 expected = 16
Thomas Wouters0e3f5912006-08-11 14:57:12 +000089 err_msg = "There are %d (not %d) is* functions" % (count, expected)
90 self.assertEqual(count, expected, err_msg)
Tim Peters5a9fb3c2005-01-07 16:01:32 +000091
Christian Heimes7131fd92008-02-19 14:21:46 +000092
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000093 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020094 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000095 self.istest(inspect.isbuiltin, 'sys.exit')
96 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +000097 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +020098 try:
99 1/0
100 except:
101 tb = sys.exc_info()[2]
102 self.istest(inspect.isframe, 'tb.tb_frame')
103 self.istest(inspect.istraceback, 'tb')
104 if hasattr(types, 'GetSetDescriptorType'):
105 self.istest(inspect.isgetsetdescriptor,
106 'type(tb.tb_frame).f_locals')
107 else:
108 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
109 finally:
110 # Clear traceback and all the frames and local variables hanging to it.
111 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000112 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000113 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000114 self.istest(inspect.ismethod, 'git.argue')
115 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000116 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000117 self.istest(inspect.isgenerator, '(x for x in range(2))')
118 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000119 if hasattr(types, 'MemberDescriptorType'):
120 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
121 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000122 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000123
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000124 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000125 self.assertTrue(inspect.isroutine(mod.spam))
126 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000127
Benjamin Petersonc4656002009-01-17 22:41:18 +0000128 def test_isclass(self):
129 self.istest(inspect.isclass, 'mod.StupidGit')
130 self.assertTrue(inspect.isclass(list))
131
132 class CustomGetattr(object):
133 def __getattr__(self, attr):
134 return None
135 self.assertFalse(inspect.isclass(CustomGetattr()))
136
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000137 def test_get_slot_members(self):
138 class C(object):
139 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000140 x = C()
141 x.a = 42
142 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000143 self.assertIn('a', members)
144 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000145
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000146 def test_isabstract(self):
147 from abc import ABCMeta, abstractmethod
148
149 class AbstractClassExample(metaclass=ABCMeta):
150
151 @abstractmethod
152 def foo(self):
153 pass
154
155 class ClassExample(AbstractClassExample):
156 def foo(self):
157 pass
158
159 a = ClassExample()
160
161 # Test general behaviour.
162 self.assertTrue(inspect.isabstract(AbstractClassExample))
163 self.assertFalse(inspect.isabstract(ClassExample))
164 self.assertFalse(inspect.isabstract(a))
165 self.assertFalse(inspect.isabstract(int))
166 self.assertFalse(inspect.isabstract(5))
167
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000168
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000169class TestInterpreterStack(IsTestBase):
170 def __init__(self, *args, **kwargs):
171 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000172
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000173 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000174
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000175 def test_abuse_done(self):
176 self.istest(inspect.istraceback, 'git.ex[2]')
177 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000178
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000179 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000180 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000181 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000182 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000183 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000184 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000185 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000186 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000187 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000188 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000189
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000190 def test_trace(self):
191 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000192 self.assertEqual(revise(*git.tr[0][1:]),
193 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
194 self.assertEqual(revise(*git.tr[1][1:]),
195 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
196 self.assertEqual(revise(*git.tr[2][1:]),
197 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000198
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000199 def test_frame(self):
200 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
201 self.assertEqual(args, ['x', 'y'])
202 self.assertEqual(varargs, None)
203 self.assertEqual(varkw, None)
204 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
205 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
206 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000207
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000208 def test_previous_frame(self):
209 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000210 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000211 self.assertEqual(varargs, 'g')
212 self.assertEqual(varkw, 'h')
213 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000214 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000215
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000216class GetSourceBase(unittest.TestCase):
217 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000218 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000219
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000220 def __init__(self, *args, **kwargs):
221 unittest.TestCase.__init__(self, *args, **kwargs)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000222
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000223 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000224 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000225
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000226 def sourcerange(self, top, bottom):
227 lines = self.source.split("\n")
228 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000229
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000230 def assertSourceEqual(self, obj, top, bottom):
231 self.assertEqual(inspect.getsource(obj),
232 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000233
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000234class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000235 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000236
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000237 def test_getclasses(self):
238 classes = inspect.getmembers(mod, inspect.isclass)
239 self.assertEqual(classes,
240 [('FesteringGob', mod.FesteringGob),
241 ('MalodorousPervert', mod.MalodorousPervert),
242 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300243 ('StupidGit', mod.StupidGit),
244 ('Tit', mod.MalodorousPervert),
245 ])
246 tree = inspect.getclasstree([cls[1] for cls in classes])
247 self.assertEqual(tree,
248 [(object, ()),
249 [(mod.ParrotDroppings, (object,)),
250 [(mod.FesteringGob, (mod.MalodorousPervert,
251 mod.ParrotDroppings))
252 ],
253 (mod.StupidGit, (object,)),
254 [(mod.MalodorousPervert, (mod.StupidGit,)),
255 [(mod.FesteringGob, (mod.MalodorousPervert,
256 mod.ParrotDroppings))
257 ]
258 ]
259 ]
260 ])
261 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000262 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000263 [(object, ()),
264 [(mod.ParrotDroppings, (object,)),
265 (mod.StupidGit, (object,)),
266 [(mod.MalodorousPervert, (mod.StupidGit,)),
267 [(mod.FesteringGob, (mod.MalodorousPervert,
268 mod.ParrotDroppings))
269 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000270 ]
271 ]
272 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000273
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000274 def test_getfunctions(self):
275 functions = inspect.getmembers(mod, inspect.isfunction)
276 self.assertEqual(functions, [('eggs', mod.eggs),
277 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000278
R. David Murray378c0cf2010-02-24 01:46:21 +0000279 @unittest.skipIf(sys.flags.optimize >= 2,
280 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000281 def test_getdoc(self):
282 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
283 self.assertEqual(inspect.getdoc(mod.StupidGit),
284 'A longer,\n\nindented\n\ndocstring.')
285 self.assertEqual(inspect.getdoc(git.abuse),
286 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000287
Georg Brandl0c77a822008-06-10 16:37:50 +0000288 def test_cleandoc(self):
289 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
290 'An\nindented\ndocstring.')
291
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000292 def test_getcomments(self):
293 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
294 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000295
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000296 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000297 # Check actual module
298 self.assertEqual(inspect.getmodule(mod), mod)
299 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000300 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000301 # Check a method (no __module__ attribute, falls back to filename)
302 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
303 # Do it again (check the caching isn't broken)
304 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
305 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000306 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000307 # Check filename override
308 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000309
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000310 def test_getsource(self):
311 self.assertSourceEqual(git.abuse, 29, 39)
312 self.assertSourceEqual(mod.StupidGit, 21, 46)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000313
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000314 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000315 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
316 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000317 fn = "_non_existing_filename_used_for_sourcefile_test.py"
318 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000319 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000320 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200321 try:
322 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
323 finally:
324 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000325
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000326 def test_getfile(self):
327 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000328
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500329 def test_getfile_class_without_module(self):
330 class CM(type):
331 @property
332 def __module__(cls):
333 raise AttributeError
334 class C(metaclass=CM):
335 pass
336 with self.assertRaises(TypeError):
337 inspect.getfile(C)
338
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000339 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000340 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000341 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000342 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000343 m.__file__ = "<string>" # hopefully not a real filename...
344 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000345 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000346 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000347 del sys.modules[name]
348 inspect.getmodule(compile('a=10','','single'))
349
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500350 def test_proceed_with_fake_filename(self):
351 '''doctest monkeypatches linecache to enable inspection'''
352 fn, source = '<test>', 'def x(): pass\n'
353 getlines = linecache.getlines
354 def monkey(filename, module_globals=None):
355 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300356 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500357 else:
358 return getlines(filename, module_globals)
359 linecache.getlines = monkey
360 try:
361 ns = {}
362 exec(compile(source, fn, 'single'), ns)
363 inspect.getsource(ns["x"])
364 finally:
365 linecache.getlines = getlines
366
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000367class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000368 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000369
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000370 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000371 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000372
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000373 def test_replacing_decorator(self):
374 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000375
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000376class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000377 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000378 def test_oneline_lambda(self):
379 # Test inspect.getsource with a one-line lambda function.
380 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000381
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000382 def test_threeline_lambda(self):
383 # Test inspect.getsource with a three-line lambda function,
384 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000385 self.assertSourceEqual(mod2.tll, 28, 30)
386
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000387 def test_twoline_indented_lambda(self):
388 # Test inspect.getsource with a two-line lambda function,
389 # where the second line _is_ indented.
390 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000391
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000392 def test_onelinefunc(self):
393 # Test inspect.getsource with a regular one-line function.
394 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000395
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000396 def test_manyargs(self):
397 # Test inspect.getsource with a regular function where
398 # the arguments are on two lines and _not_ indented and
399 # the body on the second line with the last arguments.
400 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000401
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000402 def test_twolinefunc(self):
403 # Test inspect.getsource with a regular function where
404 # the body is on two lines, following the argument list and
405 # continued on the next line by a \\.
406 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000407
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000408 def test_lambda_in_list(self):
409 # Test inspect.getsource with a one-line lambda function
410 # defined in a list, indented.
411 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000412
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000413 def test_anonymous(self):
414 # Test inspect.getsource with a lambda function defined
415 # as argument to another function.
416 self.assertSourceEqual(mod2.anonymous, 55, 55)
417
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000418class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000419 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000420
421 def test_with_comment(self):
422 self.assertSourceEqual(mod2.with_comment, 58, 59)
423
424 def test_multiline_sig(self):
425 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
426
Armin Rigodd5c0232005-09-25 11:45:45 +0000427 def test_nested_class(self):
428 self.assertSourceEqual(mod2.func69().func71, 71, 72)
429
430 def test_one_liner_followed_by_non_name(self):
431 self.assertSourceEqual(mod2.func77, 77, 77)
432
433 def test_one_liner_dedent_non_name(self):
434 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
435
436 def test_with_comment_instead_of_docstring(self):
437 self.assertSourceEqual(mod2.func88, 88, 90)
438
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000439 def test_method_in_dynamic_class(self):
440 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
441
R David Murray32562d72014-10-03 11:15:38 -0400442 # This should not skip for CPython, but might on a repackaged python where
443 # unicodedata is not an external module, or on pypy.
444 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
445 unicodedata.__file__.endswith('.py'),
446 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000447 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200448 self.assertRaises(OSError, inspect.getsource, unicodedata)
449 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000450
R. David Murraya1b37402010-06-17 02:04:29 +0000451 def test_findsource_code_in_linecache(self):
452 lines = ["x=1"]
453 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200454 self.assertRaises(OSError, inspect.findsource, co)
455 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000456 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200457 try:
458 self.assertEqual(inspect.findsource(co), (lines,0))
459 self.assertEqual(inspect.getsource(co), lines[0])
460 finally:
461 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000462
Ezio Melotti1b145922013-03-30 05:17:24 +0200463 def test_findsource_without_filename(self):
464 for fname in ['', '<string>']:
465 co = compile('x=1', fname, "exec")
466 self.assertRaises(IOError, inspect.findsource, co)
467 self.assertRaises(IOError, inspect.getsource, co)
468
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000469class TestNoEOL(GetSourceBase):
470 def __init__(self, *args, **kwargs):
471 self.tempdir = TESTFN + '_dir'
472 os.mkdir(self.tempdir)
473 with open(os.path.join(self.tempdir,
474 'inspect_fodder3%spy' % os.extsep), 'w') as f:
475 f.write("class X:\n pass # No EOL")
476 with DirsOnSysPath(self.tempdir):
477 import inspect_fodder3 as mod3
478 self.fodderModule = mod3
479 GetSourceBase.__init__(self, *args, **kwargs)
480
481 def tearDown(self):
482 shutil.rmtree(self.tempdir)
483
484 def test_class(self):
485 self.assertSourceEqual(self.fodderModule.X, 1, 2)
486
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100487
488class _BrokenDataDescriptor(object):
489 """
490 A broken data descriptor. See bug #1785.
491 """
492 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700493 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100494
495 def __set__(*args):
496 raise RuntimeError
497
498 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700499 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100500
501
502class _BrokenMethodDescriptor(object):
503 """
504 A broken method descriptor. See bug #1785.
505 """
506 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700507 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100508
509 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700510 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100511
512
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000513# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000514def attrs_wo_objs(cls):
515 return [t[:3] for t in inspect.classify_class_attrs(cls)]
516
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100517
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000518class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000519 def test_newstyle_mro(self):
520 # The same w/ new-class MRO.
521 class A(object): pass
522 class B(A): pass
523 class C(A): pass
524 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000525
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000526 expected = (D, B, C, A, object)
527 got = inspect.getmro(D)
528 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000529
Christian Heimes3795b532007-11-08 13:48:53 +0000530 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
531 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000532 args, varargs, varkw, defaults = inspect.getargspec(routine)
533 self.assertEqual(args, args_e)
534 self.assertEqual(varargs, varargs_e)
535 self.assertEqual(varkw, varkw_e)
536 self.assertEqual(defaults, defaults_e)
537 if formatted is not None:
538 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
539 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000540
Christian Heimes3795b532007-11-08 13:48:53 +0000541 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
542 varkw_e=None, defaults_e=None,
543 kwonlyargs_e=[], kwonlydefaults_e=None,
544 ann_e={}, formatted=None):
545 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
546 inspect.getfullargspec(routine)
547 self.assertEqual(args, args_e)
548 self.assertEqual(varargs, varargs_e)
549 self.assertEqual(varkw, varkw_e)
550 self.assertEqual(defaults, defaults_e)
551 self.assertEqual(kwonlyargs, kwonlyargs_e)
552 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
553 self.assertEqual(ann, ann_e)
554 if formatted is not None:
555 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
556 kwonlyargs, kwonlydefaults, ann),
557 formatted)
558
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000559 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000560 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000561
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000562 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000563 ['a', 'b', 'c', 'd', 'e', 'f'],
564 'g', 'h', (3, 4, 5),
565 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000566
Christian Heimes3795b532007-11-08 13:48:53 +0000567 self.assertRaises(ValueError, self.assertArgSpecEquals,
568 mod2.keyworded, [])
569
570 self.assertRaises(ValueError, self.assertArgSpecEquals,
571 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000572 self.assertRaises(ValueError, self.assertArgSpecEquals,
573 mod2.keyword_only_arg, [])
574
Christian Heimes3795b532007-11-08 13:48:53 +0000575
576 def test_getfullargspec(self):
577 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
578 kwonlyargs_e=['arg2'],
579 kwonlydefaults_e={'arg2':1},
580 formatted='(*arg1, arg2=1)')
581
582 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000583 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000584 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000585 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
586 kwonlyargs_e=['arg'],
587 formatted='(*, arg)')
588
Yury Selivanovff385b82014-02-19 16:27:23 -0500589 def test_argspec_api_ignores_wrapped(self):
590 # Issue 20684: low level introspection API must ignore __wrapped__
591 @functools.wraps(mod.spam)
592 def ham(x, y):
593 pass
594 # Basic check
595 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
596 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
597 self.assertFullArgSpecEquals(functools.partial(ham),
598 ['x', 'y'], formatted='(x, y)')
599 # Other variants
600 def check_method(f):
601 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
602 formatted='(self, x, y)')
603 class C:
604 @functools.wraps(mod.spam)
605 def ham(self, x, y):
606 pass
607 pham = functools.partialmethod(ham)
608 @functools.wraps(mod.spam)
609 def __call__(self, x, y):
610 pass
611 check_method(C())
612 check_method(C.ham)
613 check_method(C().ham)
614 check_method(C.pham)
615 check_method(C().pham)
616
617 class C_new:
618 @functools.wraps(mod.spam)
619 def __new__(self, x, y):
620 pass
621 check_method(C_new)
622
623 class C_init:
624 @functools.wraps(mod.spam)
625 def __init__(self, x, y):
626 pass
627 check_method(C_init)
628
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500629 def test_getfullargspec_signature_attr(self):
630 def test():
631 pass
632 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
633 test.__signature__ = inspect.Signature(parameters=(spam_param,))
634
635 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
636
Yury Selivanov4cb93912014-01-29 11:54:12 -0500637 def test_getfullargspec_signature_annos(self):
638 def test(a:'spam') -> 'ham': pass
639 spec = inspect.getfullargspec(test)
640 self.assertEqual(test.__annotations__, spec.annotations)
641
642 def test(): pass
643 spec = inspect.getfullargspec(test)
644 self.assertEqual(test.__annotations__, spec.annotations)
645
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500646 @unittest.skipIf(MISSING_C_DOCSTRINGS,
647 "Signature information for builtins requires docstrings")
648 def test_getfullargspec_builtin_methods(self):
649 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
650 args_e=['self', 'obj'], formatted='(self, obj)')
651
652 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
653 args_e=['self', 'obj'], formatted='(self, obj)')
654
Yury Selivanovd224b6a2014-02-21 01:32:42 -0500655 self.assertFullArgSpecEquals(
656 os.stat,
657 args_e=['path'],
658 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
659 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
660 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
661
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200662 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500663 @unittest.skipIf(MISSING_C_DOCSTRINGS,
664 "Signature information for builtins requires docstrings")
665 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200666 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500667 builtin = _testcapi.docstring_with_signature_with_defaults
668 spec = inspect.getfullargspec(builtin)
669 self.assertEqual(spec.defaults[0], 'avocado')
670
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200671 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500672 @unittest.skipIf(MISSING_C_DOCSTRINGS,
673 "Signature information for builtins requires docstrings")
674 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200675 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500676 builtin = _testcapi.docstring_no_signature
677 with self.assertRaises(TypeError):
678 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000679
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000680 def test_getargspec_method(self):
681 class A(object):
682 def m(self):
683 pass
684 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000685
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000686 def test_classify_newstyle(self):
687 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000688
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000689 def s(): pass
690 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000691
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000692 def c(cls): pass
693 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000694
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000695 def getp(self): pass
696 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000697
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000698 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000699
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000700 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000701
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000702 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000703
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100704 dd = _BrokenDataDescriptor()
705 md = _BrokenMethodDescriptor()
706
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000707 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500708
709 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
710 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
711
Benjamin Peterson577473f2010-01-19 00:09:57 +0000712 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
713 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
714 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000715 self.assertIn(('m', 'method', A), attrs,
716 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000717 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
718 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100719 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
720 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000721
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000722 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000723
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000724 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000725
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000726 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000727 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
728 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
729 self.assertIn(('p', 'property', A), attrs, 'missing property')
730 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
731 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
732 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100733 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
734 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000735
736
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000737 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000738
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000739 def m(self): pass
740 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000741
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000742 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000743 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
744 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
745 self.assertIn(('p', 'property', A), attrs, 'missing property')
746 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
747 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
748 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100749 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
750 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000751
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000752 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000753
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000754 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000755
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000756 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000757 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
758 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
759 self.assertIn(('p', 'property', A), attrs, 'missing property')
760 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
761 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
762 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100763 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
764 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
765
766 def test_classify_builtin_types(self):
767 # Simple sanity check that all built-in types can have their
768 # attributes classified.
769 for name in dir(__builtins__):
770 builtin = getattr(__builtins__, name)
771 if isinstance(builtin, type):
772 inspect.classify_class_attrs(builtin)
773
Ethan Furman63c141c2013-10-18 00:27:39 -0700774 def test_classify_DynamicClassAttribute(self):
775 class Meta(type):
776 def __getattr__(self, name):
777 if name == 'ham':
778 return 'spam'
779 return super().__getattr__(name)
780 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700781 @types.DynamicClassAttribute
782 def ham(self):
783 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700784 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
785 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700786 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700787 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
788
Yury Selivanovbf341fb2015-05-21 15:41:57 -0400789 def test_classify_overrides_bool(self):
790 class NoBool(object):
791 def __eq__(self, other):
792 return NoBool()
793
794 def __bool__(self):
795 raise NotImplementedError(
796 "This object does not specify a boolean value")
797
798 class HasNB(object):
799 dd = NoBool()
800
801 should_find_attr = inspect.Attribute('dd', 'data', HasNB, HasNB.dd)
802 self.assertIn(should_find_attr, inspect.classify_class_attrs(HasNB))
803
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700804 def test_classify_metaclass_class_attribute(self):
805 class Meta(type):
806 fish = 'slap'
807 def __dir__(self):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200808 return ['__class__', '__module__', '__name__', 'fish']
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700809 class Class(metaclass=Meta):
810 pass
811 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
812 self.assertIn(should_find, inspect.classify_class_attrs(Class))
813
Ethan Furman63c141c2013-10-18 00:27:39 -0700814 def test_classify_VirtualAttribute(self):
815 class Meta(type):
816 def __dir__(cls):
817 return ['__class__', '__module__', '__name__', 'BOOM']
818 def __getattr__(self, name):
819 if name =='BOOM':
820 return 42
821 return super().__getattr(name)
822 class Class(metaclass=Meta):
823 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700824 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700825 self.assertIn(should_find, inspect.classify_class_attrs(Class))
826
827 def test_classify_VirtualAttribute_multi_classes(self):
828 class Meta1(type):
829 def __dir__(cls):
830 return ['__class__', '__module__', '__name__', 'one']
831 def __getattr__(self, name):
832 if name =='one':
833 return 1
834 return super().__getattr__(name)
835 class Meta2(type):
836 def __dir__(cls):
837 return ['__class__', '__module__', '__name__', 'two']
838 def __getattr__(self, name):
839 if name =='two':
840 return 2
841 return super().__getattr__(name)
842 class Meta3(Meta1, Meta2):
843 def __dir__(cls):
844 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
845 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
846 def __getattr__(self, name):
847 if name =='three':
848 return 3
849 return super().__getattr__(name)
850 class Class1(metaclass=Meta1):
851 pass
852 class Class2(Class1, metaclass=Meta3):
853 pass
854
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700855 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
856 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
857 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700858 cca = inspect.classify_class_attrs(Class2)
859 for sf in (should_find1, should_find2, should_find3):
860 self.assertIn(sf, cca)
861
862 def test_classify_class_attrs_with_buggy_dir(self):
863 class M(type):
864 def __dir__(cls):
865 return ['__class__', '__name__', 'missing']
866 class C(metaclass=M):
867 pass
868 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
869 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700870
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100871 def test_getmembers_descriptors(self):
872 class A(object):
873 dd = _BrokenDataDescriptor()
874 md = _BrokenMethodDescriptor()
875
876 def pred_wrapper(pred):
877 # A quick'n'dirty way to discard standard attributes of new-style
878 # classes.
879 class Empty(object):
880 pass
881 def wrapped(x):
882 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
883 return False
884 return pred(x)
885 return wrapped
886
887 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
888 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
889
890 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
891 [('md', A.__dict__['md'])])
892 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
893 [('dd', A.__dict__['dd'])])
894
895 class B(A):
896 pass
897
898 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
899 [('md', A.__dict__['md'])])
900 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
901 [('dd', A.__dict__['dd'])])
902
Antoine Pitrou0c603812012-01-18 17:40:18 +0100903 def test_getmembers_method(self):
904 class B:
905 def f(self):
906 pass
907
908 self.assertIn(('f', B.f), inspect.getmembers(B))
909 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
910 b = B()
911 self.assertIn(('f', b.f), inspect.getmembers(b))
912 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
913
Ethan Furmane03ea372013-09-25 07:14:41 -0700914 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700915 class M(type):
916 def __getattr__(cls, name):
917 if name == 'eggs':
918 return 'scrambled'
919 return super().__getattr__(name)
920 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700921 @types.DynamicClassAttribute
922 def eggs(self):
923 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700924 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
925 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
926
927 def test_getmembers_with_buggy_dir(self):
928 class M(type):
929 def __dir__(cls):
930 return ['__class__', '__name__', 'missing']
931 class C(metaclass=M):
932 pass
933 attrs = [a[0] for a in inspect.getmembers(C)]
934 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700935
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000936
Nick Coghlan2f92e542012-06-23 19:39:55 +1000937_global_ref = object()
938class TestGetClosureVars(unittest.TestCase):
939
940 def test_name_resolution(self):
941 # Basic test of the 4 different resolution mechanisms
942 def f(nonlocal_ref):
943 def g(local_ref):
944 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
945 return g
946 _arg = object()
947 nonlocal_vars = {"nonlocal_ref": _arg}
948 global_vars = {"_global_ref": _global_ref}
949 builtin_vars = {"print": print}
950 unbound_names = {"unbound_ref"}
951 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
952 builtin_vars, unbound_names)
953 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
954
955 def test_generator_closure(self):
956 def f(nonlocal_ref):
957 def g(local_ref):
958 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
959 yield
960 return g
961 _arg = object()
962 nonlocal_vars = {"nonlocal_ref": _arg}
963 global_vars = {"_global_ref": _global_ref}
964 builtin_vars = {"print": print}
965 unbound_names = {"unbound_ref"}
966 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
967 builtin_vars, unbound_names)
968 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
969
970 def test_method_closure(self):
971 class C:
972 def f(self, nonlocal_ref):
973 def g(local_ref):
974 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
975 return g
976 _arg = object()
977 nonlocal_vars = {"nonlocal_ref": _arg}
978 global_vars = {"_global_ref": _global_ref}
979 builtin_vars = {"print": print}
980 unbound_names = {"unbound_ref"}
981 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
982 builtin_vars, unbound_names)
983 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
984
985 def test_nonlocal_vars(self):
986 # More complex tests of nonlocal resolution
987 def _nonlocal_vars(f):
988 return inspect.getclosurevars(f).nonlocals
989
990 def make_adder(x):
991 def add(y):
992 return x + y
993 return add
994
995 def curry(func, arg1):
996 return lambda arg2: func(arg1, arg2)
997
998 def less_than(a, b):
999 return a < b
1000
1001 # The infamous Y combinator.
1002 def Y(le):
1003 def g(f):
1004 return le(lambda x: f(f)(x))
1005 Y.g_ref = g
1006 return g(g)
1007
1008 def check_y_combinator(func):
1009 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
1010
1011 inc = make_adder(1)
1012 add_two = make_adder(2)
1013 greater_than_five = curry(less_than, 5)
1014
1015 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
1016 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
1017 self.assertEqual(_nonlocal_vars(greater_than_five),
1018 {'arg1': 5, 'func': less_than})
1019 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
1020 {'x': 3})
1021 Y(check_y_combinator)
1022
1023 def test_getclosurevars_empty(self):
1024 def foo(): pass
1025 _empty = inspect.ClosureVars({}, {}, {}, set())
1026 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1027 self.assertEqual(inspect.getclosurevars(foo), _empty)
1028
1029 def test_getclosurevars_error(self):
1030 class T: pass
1031 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1032 self.assertRaises(TypeError, inspect.getclosurevars, list)
1033 self.assertRaises(TypeError, inspect.getclosurevars, {})
1034
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001035 def _private_globals(self):
1036 code = """def f(): print(path)"""
1037 ns = {}
1038 exec(code, ns)
1039 return ns["f"], ns
1040
1041 def test_builtins_fallback(self):
1042 f, ns = self._private_globals()
1043 ns.pop("__builtins__", None)
1044 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1045 self.assertEqual(inspect.getclosurevars(f), expected)
1046
1047 def test_builtins_as_dict(self):
1048 f, ns = self._private_globals()
1049 ns["__builtins__"] = {"path":1}
1050 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1051 self.assertEqual(inspect.getclosurevars(f), expected)
1052
1053 def test_builtins_as_module(self):
1054 f, ns = self._private_globals()
1055 ns["__builtins__"] = os
1056 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1057 self.assertEqual(inspect.getclosurevars(f), expected)
1058
Nick Coghlan2f92e542012-06-23 19:39:55 +10001059
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001060class TestGetcallargsFunctions(unittest.TestCase):
1061
1062 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1063 locs = dict(locs or {}, func=func)
1064 r1 = eval('func(%s)' % call_params_string, None, locs)
1065 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1066 locs)
1067 self.assertEqual(r1, r2)
1068
1069 def assertEqualException(self, func, call_param_string, locs=None):
1070 locs = dict(locs or {}, func=func)
1071 try:
1072 eval('func(%s)' % call_param_string, None, locs)
1073 except Exception as e:
1074 ex1 = e
1075 else:
1076 self.fail('Exception not raised')
1077 try:
1078 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1079 locs)
1080 except Exception as e:
1081 ex2 = e
1082 else:
1083 self.fail('Exception not raised')
1084 self.assertIs(type(ex1), type(ex2))
1085 self.assertEqual(str(ex1), str(ex2))
1086 del ex1, ex2
1087
1088 def makeCallable(self, signature):
1089 """Create a function that returns its locals()"""
1090 code = "lambda %s: locals()"
1091 return eval(code % signature)
1092
1093 def test_plain(self):
1094 f = self.makeCallable('a, b=1')
1095 self.assertEqualCallArgs(f, '2')
1096 self.assertEqualCallArgs(f, '2, 3')
1097 self.assertEqualCallArgs(f, 'a=2')
1098 self.assertEqualCallArgs(f, 'b=3, a=2')
1099 self.assertEqualCallArgs(f, '2, b=3')
1100 # expand *iterable / **mapping
1101 self.assertEqualCallArgs(f, '*(2,)')
1102 self.assertEqualCallArgs(f, '*[2]')
1103 self.assertEqualCallArgs(f, '*(2, 3)')
1104 self.assertEqualCallArgs(f, '*[2, 3]')
1105 self.assertEqualCallArgs(f, '**{"a":2}')
1106 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1107 self.assertEqualCallArgs(f, '2, **{"b":3}')
1108 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1109 # expand UserList / UserDict
1110 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1111 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1112 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1113 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1114 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1115
1116 def test_varargs(self):
1117 f = self.makeCallable('a, b=1, *c')
1118 self.assertEqualCallArgs(f, '2')
1119 self.assertEqualCallArgs(f, '2, 3')
1120 self.assertEqualCallArgs(f, '2, 3, 4')
1121 self.assertEqualCallArgs(f, '*(2,3,4)')
1122 self.assertEqualCallArgs(f, '2, *[3,4]')
1123 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1124
1125 def test_varkw(self):
1126 f = self.makeCallable('a, b=1, **c')
1127 self.assertEqualCallArgs(f, 'a=2')
1128 self.assertEqualCallArgs(f, '2, b=3, c=4')
1129 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1130 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1131 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1132 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1133 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1134 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1135 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1136
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001137 def test_varkw_only(self):
1138 # issue11256:
1139 f = self.makeCallable('**c')
1140 self.assertEqualCallArgs(f, '')
1141 self.assertEqualCallArgs(f, 'a=1')
1142 self.assertEqualCallArgs(f, 'a=1, b=2')
1143 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1144 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1145 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1146
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001147 def test_keyword_only(self):
1148 f = self.makeCallable('a=3, *, c, d=2')
1149 self.assertEqualCallArgs(f, 'c=3')
1150 self.assertEqualCallArgs(f, 'c=3, a=3')
1151 self.assertEqualCallArgs(f, 'a=2, c=4')
1152 self.assertEqualCallArgs(f, '4, c=4')
1153 self.assertEqualException(f, '')
1154 self.assertEqualException(f, '3')
1155 self.assertEqualException(f, 'a=3')
1156 self.assertEqualException(f, 'd=4')
1157
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001158 f = self.makeCallable('*, c, d=2')
1159 self.assertEqualCallArgs(f, 'c=3')
1160 self.assertEqualCallArgs(f, 'c=3, d=4')
1161 self.assertEqualCallArgs(f, 'd=4, c=3')
1162
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001163 def test_multiple_features(self):
1164 f = self.makeCallable('a, b=2, *f, **g')
1165 self.assertEqualCallArgs(f, '2, 3, 7')
1166 self.assertEqualCallArgs(f, '2, 3, x=8')
1167 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1168 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1169 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1170 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1171 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1172 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1173 '(4,[5,6])]), **collections.UserDict('
1174 'y=9, z=10)')
1175
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001176 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1177 self.assertEqualCallArgs(f, '2, 3, x=8')
1178 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1179 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1180 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1181 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1182 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1183 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1184 '(4,[5,6])]), q=0, **collections.UserDict('
1185 'y=9, z=10)')
1186
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001187 def test_errors(self):
1188 f0 = self.makeCallable('')
1189 f1 = self.makeCallable('a, b')
1190 f2 = self.makeCallable('a, b=1')
1191 # f0 takes no arguments
1192 self.assertEqualException(f0, '1')
1193 self.assertEqualException(f0, 'x=1')
1194 self.assertEqualException(f0, '1,x=1')
1195 # f1 takes exactly 2 arguments
1196 self.assertEqualException(f1, '')
1197 self.assertEqualException(f1, '1')
1198 self.assertEqualException(f1, 'a=2')
1199 self.assertEqualException(f1, 'b=3')
1200 # f2 takes at least 1 argument
1201 self.assertEqualException(f2, '')
1202 self.assertEqualException(f2, 'b=3')
1203 for f in f1, f2:
1204 # f1/f2 takes exactly/at most 2 arguments
1205 self.assertEqualException(f, '2, 3, 4')
1206 self.assertEqualException(f, '1, 2, 3, a=1')
1207 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001208 # XXX: success of this one depends on dict order
1209 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001210 # f got an unexpected keyword argument
1211 self.assertEqualException(f, 'c=2')
1212 self.assertEqualException(f, '2, c=3')
1213 self.assertEqualException(f, '2, 3, c=4')
1214 self.assertEqualException(f, '2, c=4, b=3')
1215 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1216 # f got multiple values for keyword argument
1217 self.assertEqualException(f, '1, a=2')
1218 self.assertEqualException(f, '1, **{"a":2}')
1219 self.assertEqualException(f, '1, 2, b=3')
1220 # XXX: Python inconsistency
1221 # - for functions and bound methods: unexpected keyword 'c'
1222 # - for unbound methods: multiple values for keyword 'a'
1223 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001224 # issue11256:
1225 f3 = self.makeCallable('**c')
1226 self.assertEqualException(f3, '1, 2')
1227 self.assertEqualException(f3, '1, 2, a=1, b=2')
1228 f4 = self.makeCallable('*, a, b=0')
1229 self.assertEqualException(f3, '1, 2')
1230 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001231
Yury Selivanovb1d060b2014-03-27 18:23:03 -04001232 # issue #20816: getcallargs() fails to iterate over non-existent
1233 # kwonlydefaults and raises a wrong TypeError
1234 def f5(*, a): pass
1235 with self.assertRaisesRegex(TypeError,
1236 'missing 1 required keyword-only'):
1237 inspect.getcallargs(f5)
1238
1239
Yury Selivanov2542b662014-03-27 18:42:52 -04001240 # issue20817:
1241 def f6(a, b, c):
1242 pass
1243 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1244 inspect.getcallargs(f6)
1245
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001246class TestGetcallargsMethods(TestGetcallargsFunctions):
1247
1248 def setUp(self):
1249 class Foo(object):
1250 pass
1251 self.cls = Foo
1252 self.inst = Foo()
1253
1254 def makeCallable(self, signature):
1255 assert 'self' not in signature
1256 mk = super(TestGetcallargsMethods, self).makeCallable
1257 self.cls.method = mk('self, ' + signature)
1258 return self.inst.method
1259
1260class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1261
1262 def makeCallable(self, signature):
1263 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1264 return self.cls.method
1265
1266 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1267 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1268 *self._getAssertEqualParams(func, call_params_string, locs))
1269
1270 def assertEqualException(self, func, call_params_string, locs=None):
1271 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1272 *self._getAssertEqualParams(func, call_params_string, locs))
1273
1274 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1275 assert 'inst' not in call_params_string
1276 locs = dict(locs or {}, inst=self.inst)
1277 return (func, 'inst,' + call_params_string, locs)
1278
Michael Foord95fc51d2010-11-20 15:07:30 +00001279
1280class TestGetattrStatic(unittest.TestCase):
1281
1282 def test_basic(self):
1283 class Thing(object):
1284 x = object()
1285
1286 thing = Thing()
1287 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1288 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1289 with self.assertRaises(AttributeError):
1290 inspect.getattr_static(thing, 'y')
1291
1292 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1293
1294 def test_inherited(self):
1295 class Thing(object):
1296 x = object()
1297 class OtherThing(Thing):
1298 pass
1299
1300 something = OtherThing()
1301 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1302
1303 def test_instance_attr(self):
1304 class Thing(object):
1305 x = 2
1306 def __init__(self, x):
1307 self.x = x
1308 thing = Thing(3)
1309 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1310 del thing.x
1311 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1312
1313 def test_property(self):
1314 class Thing(object):
1315 @property
1316 def x(self):
1317 raise AttributeError("I'm pretending not to exist")
1318 thing = Thing()
1319 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1320
Ezio Melotti75cbd732011-04-28 00:59:29 +03001321 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001322 class descriptor(object):
1323 def __get__(*_):
1324 raise AttributeError("I'm pretending not to exist")
1325 desc = descriptor()
1326 class Thing(object):
1327 x = desc
1328 thing = Thing()
1329 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1330
1331 def test_classAttribute(self):
1332 class Thing(object):
1333 x = object()
1334
1335 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1336
Ethan Furmane03ea372013-09-25 07:14:41 -07001337 def test_classVirtualAttribute(self):
1338 class Thing(object):
1339 @types.DynamicClassAttribute
1340 def x(self):
1341 return self._x
1342 _x = object()
1343
1344 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1345
Michael Foord95fc51d2010-11-20 15:07:30 +00001346 def test_inherited_classattribute(self):
1347 class Thing(object):
1348 x = object()
1349 class OtherThing(Thing):
1350 pass
1351
1352 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1353
1354 def test_slots(self):
1355 class Thing(object):
1356 y = 'bar'
1357 __slots__ = ['x']
1358 def __init__(self):
1359 self.x = 'foo'
1360 thing = Thing()
1361 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1362 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1363
1364 del thing.x
1365 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1366
1367 def test_metaclass(self):
1368 class meta(type):
1369 attr = 'foo'
1370 class Thing(object, metaclass=meta):
1371 pass
1372 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1373
1374 class sub(meta):
1375 pass
1376 class OtherThing(object, metaclass=sub):
1377 x = 3
1378 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1379
1380 class OtherOtherThing(OtherThing):
1381 pass
1382 # this test is odd, but it was added as it exposed a bug
1383 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1384
1385 def test_no_dict_no_slots(self):
1386 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1387 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1388
1389 def test_no_dict_no_slots_instance_member(self):
1390 # returns descriptor
1391 with open(__file__) as handle:
1392 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1393
1394 def test_inherited_slots(self):
1395 # returns descriptor
1396 class Thing(object):
1397 __slots__ = ['x']
1398 def __init__(self):
1399 self.x = 'foo'
1400
1401 class OtherThing(Thing):
1402 pass
1403 # it would be nice if this worked...
1404 # we get the descriptor instead of the instance attribute
1405 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1406
1407 def test_descriptor(self):
1408 class descriptor(object):
1409 def __get__(self, instance, owner):
1410 return 3
1411 class Foo(object):
1412 d = descriptor()
1413
1414 foo = Foo()
1415
1416 # for a non data descriptor we return the instance attribute
1417 foo.__dict__['d'] = 1
1418 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1419
1420 # if the descriptor is a data-desciptor we should return the
1421 # descriptor
1422 descriptor.__set__ = lambda s, i, v: None
1423 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1424
1425
1426 def test_metaclass_with_descriptor(self):
1427 class descriptor(object):
1428 def __get__(self, instance, owner):
1429 return 3
1430 class meta(type):
1431 d = descriptor()
1432 class Thing(object, metaclass=meta):
1433 pass
1434 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1435
1436
Michael Foordcc7ebb82010-11-20 16:20:16 +00001437 def test_class_as_property(self):
1438 class Base(object):
1439 foo = 3
1440
1441 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001442 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001443 @property
1444 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001445 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001446 return object
1447
Michael Foord35184ed2010-11-20 16:58:30 +00001448 instance = Something()
1449 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1450 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001451 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1452
Michael Foorde5162652010-11-20 16:40:44 +00001453 def test_mro_as_property(self):
1454 class Meta(type):
1455 @property
1456 def __mro__(self):
1457 return (object,)
1458
1459 class Base(object):
1460 foo = 3
1461
1462 class Something(Base, metaclass=Meta):
1463 pass
1464
1465 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1466 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1467
Michael Foorddcebe0f2011-03-15 19:20:44 -04001468 def test_dict_as_property(self):
1469 test = self
1470 test.called = False
1471
1472 class Foo(dict):
1473 a = 3
1474 @property
1475 def __dict__(self):
1476 test.called = True
1477 return {}
1478
1479 foo = Foo()
1480 foo.a = 4
1481 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1482 self.assertFalse(test.called)
1483
1484 def test_custom_object_dict(self):
1485 test = self
1486 test.called = False
1487
1488 class Custom(dict):
1489 def get(self, key, default=None):
1490 test.called = True
1491 super().get(key, default)
1492
1493 class Foo(object):
1494 a = 3
1495 foo = Foo()
1496 foo.__dict__ = Custom()
1497 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1498 self.assertFalse(test.called)
1499
1500 def test_metaclass_dict_as_property(self):
1501 class Meta(type):
1502 @property
1503 def __dict__(self):
1504 self.executed = True
1505
1506 class Thing(metaclass=Meta):
1507 executed = False
1508
1509 def __init__(self):
1510 self.spam = 42
1511
1512 instance = Thing()
1513 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1514 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001515
Michael Foorda51623b2011-12-18 22:01:40 +00001516 def test_module(self):
1517 sentinel = object()
1518 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1519 sentinel)
1520
Michael Foord3ba95f82011-12-22 01:13:37 +00001521 def test_metaclass_with_metaclass_with_dict_as_property(self):
1522 class MetaMeta(type):
1523 @property
1524 def __dict__(self):
1525 self.executed = True
1526 return dict(spam=42)
1527
1528 class Meta(type, metaclass=MetaMeta):
1529 executed = False
1530
1531 class Thing(metaclass=Meta):
1532 pass
1533
1534 with self.assertRaises(AttributeError):
1535 inspect.getattr_static(Thing, "spam")
1536 self.assertFalse(Thing.executed)
1537
Nick Coghlane0f04652010-11-21 03:44:04 +00001538class TestGetGeneratorState(unittest.TestCase):
1539
1540 def setUp(self):
1541 def number_generator():
1542 for number in range(5):
1543 yield number
1544 self.generator = number_generator()
1545
1546 def _generatorstate(self):
1547 return inspect.getgeneratorstate(self.generator)
1548
1549 def test_created(self):
1550 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1551
1552 def test_suspended(self):
1553 next(self.generator)
1554 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1555
1556 def test_closed_after_exhaustion(self):
1557 for i in self.generator:
1558 pass
1559 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1560
1561 def test_closed_after_immediate_exception(self):
1562 with self.assertRaises(RuntimeError):
1563 self.generator.throw(RuntimeError)
1564 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1565
1566 def test_running(self):
1567 # As mentioned on issue #10220, checking for the RUNNING state only
1568 # makes sense inside the generator itself.
1569 # The following generator checks for this by using the closure's
1570 # reference to self and the generator state checking helper method
1571 def running_check_generator():
1572 for number in range(5):
1573 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1574 yield number
1575 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1576 self.generator = running_check_generator()
1577 # Running up to the first yield
1578 next(self.generator)
1579 # Running after the first yield
1580 next(self.generator)
1581
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001582 def test_easy_debugging(self):
1583 # repr() and str() of a generator state should contain the state name
1584 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1585 for name in names:
1586 state = getattr(inspect, name)
1587 self.assertIn(name, repr(state))
1588 self.assertIn(name, str(state))
1589
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001590 def test_getgeneratorlocals(self):
1591 def each(lst, a=None):
1592 b=(1, 2, 3)
1593 for v in lst:
1594 if v == 3:
1595 c = 12
1596 yield v
1597
1598 numbers = each([1, 2, 3])
1599 self.assertEqual(inspect.getgeneratorlocals(numbers),
1600 {'a': None, 'lst': [1, 2, 3]})
1601 next(numbers)
1602 self.assertEqual(inspect.getgeneratorlocals(numbers),
1603 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1604 'b': (1, 2, 3)})
1605 next(numbers)
1606 self.assertEqual(inspect.getgeneratorlocals(numbers),
1607 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1608 'b': (1, 2, 3)})
1609 next(numbers)
1610 self.assertEqual(inspect.getgeneratorlocals(numbers),
1611 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1612 'b': (1, 2, 3), 'c': 12})
1613 try:
1614 next(numbers)
1615 except StopIteration:
1616 pass
1617 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1618
1619 def test_getgeneratorlocals_empty(self):
1620 def yield_one():
1621 yield 1
1622 one = yield_one()
1623 self.assertEqual(inspect.getgeneratorlocals(one), {})
1624 try:
1625 next(one)
1626 except StopIteration:
1627 pass
1628 self.assertEqual(inspect.getgeneratorlocals(one), {})
1629
1630 def test_getgeneratorlocals_error(self):
1631 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1632 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1633 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1634 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1635
Nick Coghlane0f04652010-11-21 03:44:04 +00001636
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001637class TestSignatureObject(unittest.TestCase):
1638 @staticmethod
1639 def signature(func):
1640 sig = inspect.signature(func)
1641 return (tuple((param.name,
1642 (... if param.default is param.empty else param.default),
1643 (... if param.annotation is param.empty
1644 else param.annotation),
1645 str(param.kind).lower())
1646 for param in sig.parameters.values()),
1647 (... if sig.return_annotation is sig.empty
1648 else sig.return_annotation))
1649
1650 def test_signature_object(self):
1651 S = inspect.Signature
1652 P = inspect.Parameter
1653
1654 self.assertEqual(str(S()), '()')
1655
Yury Selivanov07a9e452014-01-29 10:58:16 -05001656 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001657 pass
1658 sig = inspect.signature(test)
1659 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001660 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001661 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001662 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001663 args = sig.parameters['args']
1664 ko = sig.parameters['ko']
1665 kwargs = sig.parameters['kwargs']
1666
1667 S((po, pk, args, ko, kwargs))
1668
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001669 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001670 S((pk, po, args, ko, kwargs))
1671
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001672 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001673 S((po, args, pk, ko, kwargs))
1674
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001675 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001676 S((args, po, pk, ko, kwargs))
1677
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001678 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001679 S((po, pk, args, kwargs, ko))
1680
1681 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001682 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001683 S((po, pk, args, kwargs2, ko))
1684
Yury Selivanov07a9e452014-01-29 10:58:16 -05001685 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1686 S((pod, po))
1687
1688 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1689 S((po, pkd, pk))
1690
1691 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1692 S((pkd, pk))
1693
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001694 def test_signature_immutability(self):
1695 def test(a):
1696 pass
1697 sig = inspect.signature(test)
1698
1699 with self.assertRaises(AttributeError):
1700 sig.foo = 'bar'
1701
1702 with self.assertRaises(TypeError):
1703 sig.parameters['a'] = None
1704
1705 def test_signature_on_noarg(self):
1706 def test():
1707 pass
1708 self.assertEqual(self.signature(test), ((), ...))
1709
1710 def test_signature_on_wargs(self):
1711 def test(a, b:'foo') -> 123:
1712 pass
1713 self.assertEqual(self.signature(test),
1714 ((('a', ..., ..., "positional_or_keyword"),
1715 ('b', ..., 'foo', "positional_or_keyword")),
1716 123))
1717
1718 def test_signature_on_wkwonly(self):
1719 def test(*, a:float, b:str) -> int:
1720 pass
1721 self.assertEqual(self.signature(test),
1722 ((('a', ..., float, "keyword_only"),
1723 ('b', ..., str, "keyword_only")),
1724 int))
1725
1726 def test_signature_on_complex_args(self):
1727 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1728 pass
1729 self.assertEqual(self.signature(test),
1730 ((('a', ..., ..., "positional_or_keyword"),
1731 ('b', 10, 'foo', "positional_or_keyword"),
1732 ('args', ..., 'bar', "var_positional"),
1733 ('spam', ..., 'baz', "keyword_only"),
1734 ('ham', 123, ..., "keyword_only"),
1735 ('kwargs', ..., int, "var_keyword")),
1736 ...))
1737
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001738 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001739 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1740 "Signature information for builtins requires docstrings")
1741 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001742 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001743
Larry Hastings5c661892014-01-24 06:17:25 -08001744 def test_unbound_method(o):
1745 """Use this to test unbound methods (things that should have a self)"""
1746 signature = inspect.signature(o)
1747 self.assertTrue(isinstance(signature, inspect.Signature))
1748 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1749 return signature
1750
1751 def test_callable(o):
1752 """Use this to test bound methods or normal callables (things that don't expect self)"""
1753 signature = inspect.signature(o)
1754 self.assertTrue(isinstance(signature, inspect.Signature))
1755 if signature.parameters:
1756 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1757 return signature
1758
1759 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001760 def p(name): return signature.parameters[name].default
1761 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001762 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001763 self.assertEqual(p('d'), 3.14)
1764 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001765 self.assertEqual(p('n'), None)
1766 self.assertEqual(p('t'), True)
1767 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001768 self.assertEqual(p('local'), 3)
1769 self.assertEqual(p('sys'), sys.maxsize)
1770 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001771
Larry Hastings5c661892014-01-24 06:17:25 -08001772 test_callable(object)
1773
1774 # normal method
1775 # (PyMethodDescr_Type, "method_descriptor")
1776 test_unbound_method(_pickle.Pickler.dump)
1777 d = _pickle.Pickler(io.StringIO())
1778 test_callable(d.dump)
1779
1780 # static method
1781 test_callable(str.maketrans)
1782 test_callable('abc'.maketrans)
1783
1784 # class method
1785 test_callable(dict.fromkeys)
1786 test_callable({}.fromkeys)
1787
1788 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1789 test_unbound_method(type.__call__)
1790 test_unbound_method(int.__add__)
1791 test_callable((3).__add__)
1792
1793 # _PyMethodWrapper_Type
1794 # support for 'method-wrapper'
1795 test_callable(min.__call__)
1796
Larry Hastings2623c8c2014-02-08 22:15:29 -08001797 # This doesn't work now.
1798 # (We don't have a valid signature for "type" in 3.4)
1799 with self.assertRaisesRegex(ValueError, "no signature found"):
1800 class ThisWorksNow:
1801 __call__ = type
1802 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001803
Yury Selivanovd930d852014-03-02 12:25:27 -05001804 # Regression test for issue #20786
1805 test_unbound_method(dict.__delitem__)
1806 test_unbound_method(property.__delete__)
1807
1808
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001809 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001810 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1811 "Signature information for builtins requires docstrings")
1812 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001813 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001814 func = _testcapi.docstring_with_signature_with_defaults
1815
1816 def decorator(func):
1817 @functools.wraps(func)
1818 def wrapper(*args, **kwargs) -> int:
1819 return func(*args, **kwargs)
1820 return wrapper
1821
1822 decorated_func = decorator(func)
1823
1824 self.assertEqual(inspect.signature(func),
1825 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08001826
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001827 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08001828 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001829 import _testcapi
Larry Hastings5c661892014-01-24 06:17:25 -08001830 with self.assertRaisesRegex(ValueError, 'no signature found for builtin'):
1831 inspect.signature(_testcapi.docstring_no_signature)
1832
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001833 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001834 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001835 inspect.signature(42)
1836
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001837 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001838 inspect.Signature.from_function(42)
1839
Yury Selivanovb77511d2014-01-29 10:46:14 -05001840 def test_signature_from_builtin_errors(self):
1841 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1842 inspect.Signature.from_builtin(42)
1843
Yury Selivanov63da7c72014-01-31 14:48:37 -05001844 def test_signature_from_functionlike_object(self):
1845 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1846 pass
1847
1848 class funclike:
1849 # Has to be callable, and have correct
1850 # __code__, __annotations__, __defaults__, __name__,
1851 # and __kwdefaults__ attributes
1852
1853 def __init__(self, func):
1854 self.__name__ = func.__name__
1855 self.__code__ = func.__code__
1856 self.__annotations__ = func.__annotations__
1857 self.__defaults__ = func.__defaults__
1858 self.__kwdefaults__ = func.__kwdefaults__
1859 self.func = func
1860
1861 def __call__(self, *args, **kwargs):
1862 return self.func(*args, **kwargs)
1863
1864 sig_func = inspect.Signature.from_function(func)
1865
1866 sig_funclike = inspect.Signature.from_function(funclike(func))
1867 self.assertEqual(sig_funclike, sig_func)
1868
1869 sig_funclike = inspect.signature(funclike(func))
1870 self.assertEqual(sig_funclike, sig_func)
1871
1872 # If object is not a duck type of function, then
1873 # signature will try to get a signature for its '__call__'
1874 # method
1875 fl = funclike(func)
1876 del fl.__defaults__
1877 self.assertEqual(self.signature(fl),
1878 ((('args', ..., ..., "var_positional"),
1879 ('kwargs', ..., ..., "var_keyword")),
1880 ...))
1881
Yury Selivanov8dfb4572014-02-21 18:30:53 -05001882 # Test with cython-like builtins:
1883 _orig_isdesc = inspect.ismethoddescriptor
1884 def _isdesc(obj):
1885 if hasattr(obj, '_builtinmock'):
1886 return True
1887 return _orig_isdesc(obj)
1888
1889 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
1890 builtin_func = funclike(func)
1891 # Make sure that our mock setup is working
1892 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
1893 builtin_func._builtinmock = True
1894 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
1895 self.assertEqual(inspect.signature(builtin_func), sig_func)
1896
Yury Selivanov63da7c72014-01-31 14:48:37 -05001897 def test_signature_functionlike_class(self):
1898 # We only want to duck type function-like objects,
1899 # not classes.
1900
1901 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1902 pass
1903
1904 class funclike:
1905 def __init__(self, marker):
1906 pass
1907
1908 __name__ = func.__name__
1909 __code__ = func.__code__
1910 __annotations__ = func.__annotations__
1911 __defaults__ = func.__defaults__
1912 __kwdefaults__ = func.__kwdefaults__
1913
1914 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1915 inspect.Signature.from_function(funclike)
1916
1917 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1918
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001919 def test_signature_on_method(self):
1920 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05001921 def __init__(*args):
1922 pass
1923 def m1(self, arg1, arg2=1) -> int:
1924 pass
1925 def m2(*args):
1926 pass
1927 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001928 pass
1929
Yury Selivanov62560fb2014-01-28 12:26:24 -05001930 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001931 ((('arg1', ..., ..., "positional_or_keyword"),
1932 ('arg2', 1, ..., "positional_or_keyword")),
1933 int))
1934
Yury Selivanov62560fb2014-01-28 12:26:24 -05001935 self.assertEqual(self.signature(Test().m2),
1936 ((('args', ..., ..., "var_positional"),),
1937 ...))
1938
1939 self.assertEqual(self.signature(Test),
1940 ((('args', ..., ..., "var_positional"),),
1941 ...))
1942
1943 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
1944 self.signature(Test())
1945
Yury Selivanov46c759d2015-05-27 21:56:53 -04001946 def test_signature_wrapped_bound_method(self):
1947 # Issue 24298
1948 class Test:
1949 def m1(self, arg1, arg2=1) -> int:
1950 pass
1951 @functools.wraps(Test().m1)
1952 def m1d(*args, **kwargs):
1953 pass
1954 self.assertEqual(self.signature(m1d),
1955 ((('arg1', ..., ..., "positional_or_keyword"),
1956 ('arg2', 1, ..., "positional_or_keyword")),
1957 int))
1958
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001959 def test_signature_on_classmethod(self):
1960 class Test:
1961 @classmethod
1962 def foo(cls, arg1, *, arg2=1):
1963 pass
1964
1965 meth = Test().foo
1966 self.assertEqual(self.signature(meth),
1967 ((('arg1', ..., ..., "positional_or_keyword"),
1968 ('arg2', 1, ..., "keyword_only")),
1969 ...))
1970
1971 meth = Test.foo
1972 self.assertEqual(self.signature(meth),
1973 ((('arg1', ..., ..., "positional_or_keyword"),
1974 ('arg2', 1, ..., "keyword_only")),
1975 ...))
1976
1977 def test_signature_on_staticmethod(self):
1978 class Test:
1979 @staticmethod
1980 def foo(cls, *, arg):
1981 pass
1982
1983 meth = Test().foo
1984 self.assertEqual(self.signature(meth),
1985 ((('cls', ..., ..., "positional_or_keyword"),
1986 ('arg', ..., ..., "keyword_only")),
1987 ...))
1988
1989 meth = Test.foo
1990 self.assertEqual(self.signature(meth),
1991 ((('cls', ..., ..., "positional_or_keyword"),
1992 ('arg', ..., ..., "keyword_only")),
1993 ...))
1994
1995 def test_signature_on_partial(self):
1996 from functools import partial
1997
Yury Selivanov0fceaf42014-04-08 11:28:02 -04001998 Parameter = inspect.Parameter
1999
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002000 def test():
2001 pass
2002
2003 self.assertEqual(self.signature(partial(test)), ((), ...))
2004
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002005 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002006 inspect.signature(partial(test, 1))
2007
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002008 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002009 inspect.signature(partial(test, a=1))
2010
2011 def test(a, b, *, c, d):
2012 pass
2013
2014 self.assertEqual(self.signature(partial(test)),
2015 ((('a', ..., ..., "positional_or_keyword"),
2016 ('b', ..., ..., "positional_or_keyword"),
2017 ('c', ..., ..., "keyword_only"),
2018 ('d', ..., ..., "keyword_only")),
2019 ...))
2020
2021 self.assertEqual(self.signature(partial(test, 1)),
2022 ((('b', ..., ..., "positional_or_keyword"),
2023 ('c', ..., ..., "keyword_only"),
2024 ('d', ..., ..., "keyword_only")),
2025 ...))
2026
2027 self.assertEqual(self.signature(partial(test, 1, c=2)),
2028 ((('b', ..., ..., "positional_or_keyword"),
2029 ('c', 2, ..., "keyword_only"),
2030 ('d', ..., ..., "keyword_only")),
2031 ...))
2032
2033 self.assertEqual(self.signature(partial(test, b=1, c=2)),
2034 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002035 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002036 ('c', 2, ..., "keyword_only"),
2037 ('d', ..., ..., "keyword_only")),
2038 ...))
2039
2040 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002041 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002042 ('c', 2, ..., "keyword_only"),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002043 ('d', ..., ..., "keyword_only")),
2044 ...))
2045
2046 self.assertEqual(self.signature(partial(test, a=1)),
2047 ((('a', 1, ..., "keyword_only"),
2048 ('b', ..., ..., "keyword_only"),
2049 ('c', ..., ..., "keyword_only"),
2050 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002051 ...))
2052
2053 def test(a, *args, b, **kwargs):
2054 pass
2055
2056 self.assertEqual(self.signature(partial(test, 1)),
2057 ((('args', ..., ..., "var_positional"),
2058 ('b', ..., ..., "keyword_only"),
2059 ('kwargs', ..., ..., "var_keyword")),
2060 ...))
2061
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002062 self.assertEqual(self.signature(partial(test, a=1)),
2063 ((('a', 1, ..., "keyword_only"),
2064 ('b', ..., ..., "keyword_only"),
2065 ('kwargs', ..., ..., "var_keyword")),
2066 ...))
2067
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002068 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2069 ((('args', ..., ..., "var_positional"),
2070 ('b', ..., ..., "keyword_only"),
2071 ('kwargs', ..., ..., "var_keyword")),
2072 ...))
2073
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002074 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2075 ((('args', ..., ..., "var_positional"),
2076 ('b', ..., ..., "keyword_only"),
2077 ('kwargs', ..., ..., "var_keyword")),
2078 ...))
2079
2080 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2081 ((('args', ..., ..., "var_positional"),
2082 ('b', 0, ..., "keyword_only"),
2083 ('kwargs', ..., ..., "var_keyword")),
2084 ...))
2085
2086 self.assertEqual(self.signature(partial(test, b=0)),
2087 ((('a', ..., ..., "positional_or_keyword"),
2088 ('args', ..., ..., "var_positional"),
2089 ('b', 0, ..., "keyword_only"),
2090 ('kwargs', ..., ..., "var_keyword")),
2091 ...))
2092
2093 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2094 ((('a', ..., ..., "positional_or_keyword"),
2095 ('args', ..., ..., "var_positional"),
2096 ('b', 0, ..., "keyword_only"),
2097 ('kwargs', ..., ..., "var_keyword")),
2098 ...))
2099
2100 def test(a, b, c:int) -> 42:
2101 pass
2102
2103 sig = test.__signature__ = inspect.signature(test)
2104
2105 self.assertEqual(self.signature(partial(partial(test, 1))),
2106 ((('b', ..., ..., "positional_or_keyword"),
2107 ('c', ..., int, "positional_or_keyword")),
2108 42))
2109
2110 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2111 ((('c', ..., int, "positional_or_keyword"),),
2112 42))
2113
2114 psig = inspect.signature(partial(partial(test, 1), 2))
2115
2116 def foo(a):
2117 return a
2118 _foo = partial(partial(foo, a=10), a=20)
2119 self.assertEqual(self.signature(_foo),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002120 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002121 ...))
2122 # check that we don't have any side-effects in signature(),
2123 # and the partial object is still functioning
2124 self.assertEqual(_foo(), 20)
2125
2126 def foo(a, b, c):
2127 return a, b, c
2128 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002129
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002130 self.assertEqual(self.signature(_foo),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002131 ((('b', 30, ..., "keyword_only"),
2132 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002133 ...))
2134 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002135
2136 def foo(a, b, c, *, d):
2137 return a, b, c, d
2138 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2139 self.assertEqual(self.signature(_foo),
2140 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002141 ('b', 10, ..., "keyword_only"),
2142 ('c', 20, ..., "keyword_only"),
2143 ('d', 30, ..., "keyword_only"),
2144 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002145 ...))
2146 ba = inspect.signature(_foo).bind(a=200, b=11)
2147 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2148
2149 def foo(a=1, b=2, c=3):
2150 return a, b, c
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002151 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2152
2153 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002154 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002155
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002156 ba = inspect.signature(_foo).bind(11, 12)
2157 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002158
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002159 ba = inspect.signature(_foo).bind(11, b=12)
2160 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002161
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002162 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002163 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2164
2165 _foo = partial(_foo, b=10, c=20)
2166 ba = inspect.signature(_foo).bind(12)
2167 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2168
2169
2170 def foo(a, b, c, d, **kwargs):
2171 pass
2172 sig = inspect.signature(foo)
2173 params = sig.parameters.copy()
2174 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2175 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2176 foo.__signature__ = inspect.Signature(params.values())
2177 sig = inspect.signature(foo)
2178 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2179
2180 self.assertEqual(self.signature(partial(foo, 1)),
2181 ((('b', ..., ..., 'positional_only'),
2182 ('c', ..., ..., 'positional_or_keyword'),
2183 ('d', ..., ..., 'positional_or_keyword'),
2184 ('kwargs', ..., ..., 'var_keyword')),
2185 ...))
2186
2187 self.assertEqual(self.signature(partial(foo, 1, 2)),
2188 ((('c', ..., ..., 'positional_or_keyword'),
2189 ('d', ..., ..., 'positional_or_keyword'),
2190 ('kwargs', ..., ..., 'var_keyword')),
2191 ...))
2192
2193 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2194 ((('d', ..., ..., 'positional_or_keyword'),
2195 ('kwargs', ..., ..., 'var_keyword')),
2196 ...))
2197
2198 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2199 ((('c', 3, ..., 'keyword_only'),
2200 ('d', ..., ..., 'keyword_only'),
2201 ('kwargs', ..., ..., 'var_keyword')),
2202 ...))
2203
2204 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2205 ((('b', ..., ..., 'positional_only'),
2206 ('c', 3, ..., 'keyword_only'),
2207 ('d', ..., ..., 'keyword_only'),
2208 ('kwargs', ..., ..., 'var_keyword')),
2209 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002210
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002211 def test_signature_on_partialmethod(self):
2212 from functools import partialmethod
2213
2214 class Spam:
2215 def test():
2216 pass
2217 ham = partialmethod(test)
2218
2219 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2220 inspect.signature(Spam.ham)
2221
2222 class Spam:
2223 def test(it, a, *, c) -> 'spam':
2224 pass
2225 ham = partialmethod(test, c=1)
2226
2227 self.assertEqual(self.signature(Spam.ham),
2228 ((('it', ..., ..., 'positional_or_keyword'),
2229 ('a', ..., ..., 'positional_or_keyword'),
2230 ('c', 1, ..., 'keyword_only')),
2231 'spam'))
2232
2233 self.assertEqual(self.signature(Spam().ham),
2234 ((('a', ..., ..., 'positional_or_keyword'),
2235 ('c', 1, ..., 'keyword_only')),
2236 'spam'))
2237
Yury Selivanov0486f812014-01-29 12:18:59 -05002238 def test_signature_on_fake_partialmethod(self):
2239 def foo(a): pass
2240 foo._partialmethod = 'spam'
2241 self.assertEqual(str(inspect.signature(foo)), '(a)')
2242
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002243 def test_signature_on_decorated(self):
2244 import functools
2245
2246 def decorator(func):
2247 @functools.wraps(func)
2248 def wrapper(*args, **kwargs) -> int:
2249 return func(*args, **kwargs)
2250 return wrapper
2251
2252 class Foo:
2253 @decorator
2254 def bar(self, a, b):
2255 pass
2256
2257 self.assertEqual(self.signature(Foo.bar),
2258 ((('self', ..., ..., "positional_or_keyword"),
2259 ('a', ..., ..., "positional_or_keyword"),
2260 ('b', ..., ..., "positional_or_keyword")),
2261 ...))
2262
2263 self.assertEqual(self.signature(Foo().bar),
2264 ((('a', ..., ..., "positional_or_keyword"),
2265 ('b', ..., ..., "positional_or_keyword")),
2266 ...))
2267
2268 # Test that we handle method wrappers correctly
2269 def decorator(func):
2270 @functools.wraps(func)
2271 def wrapper(*args, **kwargs) -> int:
2272 return func(42, *args, **kwargs)
2273 sig = inspect.signature(func)
2274 new_params = tuple(sig.parameters.values())[1:]
2275 wrapper.__signature__ = sig.replace(parameters=new_params)
2276 return wrapper
2277
2278 class Foo:
2279 @decorator
2280 def __call__(self, a, b):
2281 pass
2282
2283 self.assertEqual(self.signature(Foo.__call__),
2284 ((('a', ..., ..., "positional_or_keyword"),
2285 ('b', ..., ..., "positional_or_keyword")),
2286 ...))
2287
2288 self.assertEqual(self.signature(Foo().__call__),
2289 ((('b', ..., ..., "positional_or_keyword"),),
2290 ...))
2291
Nick Coghlane8c45d62013-07-28 20:00:01 +10002292 # Test we handle __signature__ partway down the wrapper stack
2293 def wrapped_foo_call():
2294 pass
2295 wrapped_foo_call.__wrapped__ = Foo.__call__
2296
2297 self.assertEqual(self.signature(wrapped_foo_call),
2298 ((('a', ..., ..., "positional_or_keyword"),
2299 ('b', ..., ..., "positional_or_keyword")),
2300 ...))
2301
2302
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002303 def test_signature_on_class(self):
2304 class C:
2305 def __init__(self, a):
2306 pass
2307
2308 self.assertEqual(self.signature(C),
2309 ((('a', ..., ..., "positional_or_keyword"),),
2310 ...))
2311
2312 class CM(type):
2313 def __call__(cls, a):
2314 pass
2315 class C(metaclass=CM):
2316 def __init__(self, b):
2317 pass
2318
2319 self.assertEqual(self.signature(C),
2320 ((('a', ..., ..., "positional_or_keyword"),),
2321 ...))
2322
2323 class CM(type):
2324 def __new__(mcls, name, bases, dct, *, foo=1):
2325 return super().__new__(mcls, name, bases, dct)
2326 class C(metaclass=CM):
2327 def __init__(self, b):
2328 pass
2329
2330 self.assertEqual(self.signature(C),
2331 ((('b', ..., ..., "positional_or_keyword"),),
2332 ...))
2333
2334 self.assertEqual(self.signature(CM),
2335 ((('name', ..., ..., "positional_or_keyword"),
2336 ('bases', ..., ..., "positional_or_keyword"),
2337 ('dct', ..., ..., "positional_or_keyword"),
2338 ('foo', 1, ..., "keyword_only")),
2339 ...))
2340
2341 class CMM(type):
2342 def __new__(mcls, name, bases, dct, *, foo=1):
2343 return super().__new__(mcls, name, bases, dct)
2344 def __call__(cls, nm, bs, dt):
2345 return type(nm, bs, dt)
2346 class CM(type, metaclass=CMM):
2347 def __new__(mcls, name, bases, dct, *, bar=2):
2348 return super().__new__(mcls, name, bases, dct)
2349 class C(metaclass=CM):
2350 def __init__(self, b):
2351 pass
2352
2353 self.assertEqual(self.signature(CMM),
2354 ((('name', ..., ..., "positional_or_keyword"),
2355 ('bases', ..., ..., "positional_or_keyword"),
2356 ('dct', ..., ..., "positional_or_keyword"),
2357 ('foo', 1, ..., "keyword_only")),
2358 ...))
2359
2360 self.assertEqual(self.signature(CM),
2361 ((('nm', ..., ..., "positional_or_keyword"),
2362 ('bs', ..., ..., "positional_or_keyword"),
2363 ('dt', ..., ..., "positional_or_keyword")),
2364 ...))
2365
2366 self.assertEqual(self.signature(C),
2367 ((('b', ..., ..., "positional_or_keyword"),),
2368 ...))
2369
2370 class CM(type):
2371 def __init__(cls, name, bases, dct, *, bar=2):
2372 return super().__init__(name, bases, dct)
2373 class C(metaclass=CM):
2374 def __init__(self, b):
2375 pass
2376
2377 self.assertEqual(self.signature(CM),
2378 ((('name', ..., ..., "positional_or_keyword"),
2379 ('bases', ..., ..., "positional_or_keyword"),
2380 ('dct', ..., ..., "positional_or_keyword"),
2381 ('bar', 2, ..., "keyword_only")),
2382 ...))
2383
Yury Selivanov145dff82014-02-01 13:49:29 -05002384 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2385 "Signature information for builtins requires docstrings")
2386 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002387 # Test classes without user-defined __init__ or __new__
2388 class C: pass
2389 self.assertEqual(str(inspect.signature(C)), '()')
2390 class D(C): pass
2391 self.assertEqual(str(inspect.signature(D)), '()')
2392
2393 # Test meta-classes without user-defined __init__ or __new__
2394 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002395 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002396 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2397 self.assertEqual(inspect.signature(C), None)
2398 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2399 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002400
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002401 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2402 "Signature information for builtins requires docstrings")
2403 def test_signature_on_builtin_class(self):
2404 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2405 '(file, protocol=None, fix_imports=True)')
2406
2407 class P(_pickle.Pickler): pass
2408 class EmptyTrait: pass
2409 class P2(EmptyTrait, P): pass
2410 self.assertEqual(str(inspect.signature(P)),
2411 '(file, protocol=None, fix_imports=True)')
2412 self.assertEqual(str(inspect.signature(P2)),
2413 '(file, protocol=None, fix_imports=True)')
2414
2415 class P3(P2):
2416 def __init__(self, spam):
2417 pass
2418 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2419
2420 class MetaP(type):
2421 def __call__(cls, foo, bar):
2422 pass
2423 class P4(P2, metaclass=MetaP):
2424 pass
2425 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2426
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002427 def test_signature_on_callable_objects(self):
2428 class Foo:
2429 def __call__(self, a):
2430 pass
2431
2432 self.assertEqual(self.signature(Foo()),
2433 ((('a', ..., ..., "positional_or_keyword"),),
2434 ...))
2435
2436 class Spam:
2437 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002438 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002439 inspect.signature(Spam())
2440
2441 class Bar(Spam, Foo):
2442 pass
2443
2444 self.assertEqual(self.signature(Bar()),
2445 ((('a', ..., ..., "positional_or_keyword"),),
2446 ...))
2447
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002448 class Wrapped:
2449 pass
2450 Wrapped.__wrapped__ = lambda a: None
2451 self.assertEqual(self.signature(Wrapped),
2452 ((('a', ..., ..., "positional_or_keyword"),),
2453 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002454 # wrapper loop:
2455 Wrapped.__wrapped__ = Wrapped
2456 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2457 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002458
2459 def test_signature_on_lambdas(self):
2460 self.assertEqual(self.signature((lambda a=10: a)),
2461 ((('a', 10, ..., "positional_or_keyword"),),
2462 ...))
2463
2464 def test_signature_equality(self):
2465 def foo(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002466 self.assertFalse(inspect.signature(foo) == 42)
2467 self.assertTrue(inspect.signature(foo) != 42)
2468 self.assertTrue(inspect.signature(foo) == EqualsToAll())
2469 self.assertFalse(inspect.signature(foo) != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002470
2471 def bar(a, *, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002472 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2473 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002474
2475 def bar(a, *, b:int) -> int: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002476 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2477 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002478
2479 def bar(a, *, b:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002480 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2481 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002482
2483 def bar(a, *, b:int=42) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002484 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2485 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002486
2487 def bar(a, *, c) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002488 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2489 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002490
2491 def bar(a, b:int) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002492 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2493 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002494 def spam(b:int, a) -> float: pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002495 self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
2496 self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002497
2498 def foo(*, a, b, c): pass
2499 def bar(*, c, b, a): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002500 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2501 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002502
2503 def foo(*, a=1, b, c): pass
2504 def bar(*, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002505 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2506 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002507
2508 def foo(pos, *, a=1, b, c): pass
2509 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002510 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2511 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002512
2513 def foo(pos, *, a, b, c): pass
2514 def bar(pos, *, c, b, a=1): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002515 self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
2516 self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002517
2518 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2519 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002520 self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
2521 self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002522
2523 def test_signature_unhashable(self):
2524 def foo(a): pass
2525 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002526 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002527 hash(sig)
2528
2529 def test_signature_str(self):
2530 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2531 pass
2532 self.assertEqual(str(inspect.signature(foo)),
2533 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2534
2535 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2536 pass
2537 self.assertEqual(str(inspect.signature(foo)),
2538 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2539
2540 def foo():
2541 pass
2542 self.assertEqual(str(inspect.signature(foo)), '()')
2543
2544 def test_signature_str_positional_only(self):
2545 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002546 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002547
2548 def test(a_po, *, b, **kwargs):
2549 return a_po, kwargs
2550
2551 sig = inspect.signature(test)
2552 new_params = list(sig.parameters.values())
2553 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2554 test.__signature__ = sig.replace(parameters=new_params)
2555
2556 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002557 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002558
Yury Selivanov2393dca2014-01-27 15:07:58 -05002559 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2560 '(foo, /)')
2561
2562 self.assertEqual(str(S(parameters=[
2563 P('foo', P.POSITIONAL_ONLY),
2564 P('bar', P.VAR_KEYWORD)])),
2565 '(foo, /, **bar)')
2566
2567 self.assertEqual(str(S(parameters=[
2568 P('foo', P.POSITIONAL_ONLY),
2569 P('bar', P.VAR_POSITIONAL)])),
2570 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002571
2572 def test_signature_replace_anno(self):
2573 def test() -> 42:
2574 pass
2575
2576 sig = inspect.signature(test)
2577 sig = sig.replace(return_annotation=None)
2578 self.assertIs(sig.return_annotation, None)
2579 sig = sig.replace(return_annotation=sig.empty)
2580 self.assertIs(sig.return_annotation, sig.empty)
2581 sig = sig.replace(return_annotation=42)
2582 self.assertEqual(sig.return_annotation, 42)
2583 self.assertEqual(sig, inspect.signature(test))
2584
Yury Selivanov026019f2014-02-18 12:49:41 -05002585 def test_signature_on_mangled_parameters(self):
2586 class Spam:
2587 def foo(self, __p1:1=2, *, __p2:2=3):
2588 pass
2589 class Ham(Spam):
2590 pass
2591
2592 self.assertEqual(self.signature(Spam.foo),
2593 ((('self', ..., ..., "positional_or_keyword"),
2594 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2595 ('_Spam__p2', 3, 2, "keyword_only")),
2596 ...))
2597
2598 self.assertEqual(self.signature(Spam.foo),
2599 self.signature(Ham.foo))
2600
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002601
2602class TestParameterObject(unittest.TestCase):
2603 def test_signature_parameter_kinds(self):
2604 P = inspect.Parameter
2605 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2606 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2607
2608 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2609 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2610
2611 def test_signature_parameter_object(self):
2612 p = inspect.Parameter('foo', default=10,
2613 kind=inspect.Parameter.POSITIONAL_ONLY)
2614 self.assertEqual(p.name, 'foo')
2615 self.assertEqual(p.default, 10)
2616 self.assertIs(p.annotation, p.empty)
2617 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2618
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002619 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002620 inspect.Parameter('foo', default=10, kind='123')
2621
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002622 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002623 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2624
Yury Selivanov2393dca2014-01-27 15:07:58 -05002625 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002626 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2627
Yury Selivanov2393dca2014-01-27 15:07:58 -05002628 with self.assertRaisesRegex(ValueError,
2629 'is not a valid parameter name'):
2630 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2631
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002632 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002633 inspect.Parameter('a', default=42,
2634 kind=inspect.Parameter.VAR_KEYWORD)
2635
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002636 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002637 inspect.Parameter('a', default=42,
2638 kind=inspect.Parameter.VAR_POSITIONAL)
2639
2640 p = inspect.Parameter('a', default=42,
2641 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002642 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002643 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2644
2645 self.assertTrue(repr(p).startswith('<Parameter'))
2646
2647 def test_signature_parameter_equality(self):
2648 P = inspect.Parameter
2649 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2650
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002651 self.assertTrue(p == p)
2652 self.assertFalse(p != p)
2653 self.assertFalse(p == 42)
2654 self.assertTrue(p != 42)
2655 self.assertTrue(p == EqualsToAll())
2656 self.assertFalse(p != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002657
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002658 self.assertTrue(p == P('foo', default=42,
2659 kind=inspect.Parameter.KEYWORD_ONLY))
2660 self.assertFalse(p != P('foo', default=42,
2661 kind=inspect.Parameter.KEYWORD_ONLY))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002662
2663 def test_signature_parameter_unhashable(self):
2664 p = inspect.Parameter('foo', default=42,
2665 kind=inspect.Parameter.KEYWORD_ONLY)
2666
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002667 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002668 hash(p)
2669
2670 def test_signature_parameter_replace(self):
2671 p = inspect.Parameter('foo', default=42,
2672 kind=inspect.Parameter.KEYWORD_ONLY)
2673
2674 self.assertIsNot(p, p.replace())
2675 self.assertEqual(p, p.replace())
2676
2677 p2 = p.replace(annotation=1)
2678 self.assertEqual(p2.annotation, 1)
2679 p2 = p2.replace(annotation=p2.empty)
2680 self.assertEqual(p, p2)
2681
2682 p2 = p2.replace(name='bar')
2683 self.assertEqual(p2.name, 'bar')
2684 self.assertNotEqual(p2, p)
2685
Yury Selivanov2393dca2014-01-27 15:07:58 -05002686 with self.assertRaisesRegex(ValueError,
2687 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002688 p2 = p2.replace(name=p2.empty)
2689
2690 p2 = p2.replace(name='foo', default=None)
2691 self.assertIs(p2.default, None)
2692 self.assertNotEqual(p2, p)
2693
2694 p2 = p2.replace(name='foo', default=p2.empty)
2695 self.assertIs(p2.default, p2.empty)
2696
2697
2698 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2699 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2700 self.assertNotEqual(p2, p)
2701
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002702 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002703 p2 = p2.replace(kind=p2.empty)
2704
2705 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2706 self.assertEqual(p2, p)
2707
2708 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002709 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2710 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002711
2712 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002713 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002714
2715 with self.assertRaises(AttributeError):
2716 p.foo = 'bar'
2717
2718 with self.assertRaises(AttributeError):
2719 p.kind = 123
2720
2721
2722class TestSignatureBind(unittest.TestCase):
2723 @staticmethod
2724 def call(func, *args, **kwargs):
2725 sig = inspect.signature(func)
2726 ba = sig.bind(*args, **kwargs)
2727 return func(*ba.args, **ba.kwargs)
2728
2729 def test_signature_bind_empty(self):
2730 def test():
2731 return 42
2732
2733 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002734 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002735 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002736 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002737 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002738 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002739 self.call(test, spam=1)
2740
2741 def test_signature_bind_var(self):
2742 def test(*args, **kwargs):
2743 return args, kwargs
2744
2745 self.assertEqual(self.call(test), ((), {}))
2746 self.assertEqual(self.call(test, 1), ((1,), {}))
2747 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2748 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2749 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2750 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2751 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2752 ((1, 2), {'foo': 'bar'}))
2753
2754 def test_signature_bind_just_args(self):
2755 def test(a, b, c):
2756 return a, b, c
2757
2758 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2759
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002760 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002761 self.call(test, 1, 2, 3, 4)
2762
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002763 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002764 self.call(test, 1)
2765
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002766 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002767 self.call(test)
2768
2769 def test(a, b, c=10):
2770 return a, b, c
2771 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2772 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2773
2774 def test(a=1, b=2, c=3):
2775 return a, b, c
2776 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2777 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2778 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2779
2780 def test_signature_bind_varargs_order(self):
2781 def test(*args):
2782 return args
2783
2784 self.assertEqual(self.call(test), ())
2785 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2786
2787 def test_signature_bind_args_and_varargs(self):
2788 def test(a, b, c=3, *args):
2789 return a, b, c, args
2790
2791 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2792 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2793 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2794 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2795
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002796 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002797 "multiple values for argument 'c'"):
2798 self.call(test, 1, 2, 3, c=4)
2799
2800 def test_signature_bind_just_kwargs(self):
2801 def test(**kwargs):
2802 return kwargs
2803
2804 self.assertEqual(self.call(test), {})
2805 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2806 {'foo': 'bar', 'spam': 'ham'})
2807
2808 def test_signature_bind_args_and_kwargs(self):
2809 def test(a, b, c=3, **kwargs):
2810 return a, b, c, kwargs
2811
2812 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2813 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2814 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2815 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2816 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2817 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2818 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2819 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2820 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2821 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2822 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2823 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2824 (1, 2, 4, {'foo': 'bar'}))
2825 self.assertEqual(self.call(test, c=5, a=4, b=3),
2826 (4, 3, 5, {}))
2827
2828 def test_signature_bind_kwonly(self):
2829 def test(*, foo):
2830 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002831 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002832 'too many positional arguments'):
2833 self.call(test, 1)
2834 self.assertEqual(self.call(test, foo=1), 1)
2835
2836 def test(a, *, foo=1, bar):
2837 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002838 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002839 "'bar' parameter lacking default value"):
2840 self.call(test, 1)
2841
2842 def test(foo, *, bar):
2843 return foo, bar
2844 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2845 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2846
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002847 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002848 'too many keyword arguments'):
2849 self.call(test, bar=2, foo=1, spam=10)
2850
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002851 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002852 'too many positional arguments'):
2853 self.call(test, 1, 2)
2854
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002855 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002856 'too many positional arguments'):
2857 self.call(test, 1, 2, bar=2)
2858
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002859 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002860 'too many keyword arguments'):
2861 self.call(test, 1, bar=2, spam='ham')
2862
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002863 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002864 "'bar' parameter lacking default value"):
2865 self.call(test, 1)
2866
2867 def test(foo, *, bar, **bin):
2868 return foo, bar, bin
2869 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2870 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2871 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2872 (1, 2, {'spam': 'ham'}))
2873 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2874 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002875 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002876 "'foo' parameter lacking default value"):
2877 self.call(test, spam='ham', bar=2)
2878 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2879 (1, 2, {'bin': 1, 'spam': 10}))
2880
2881 def test_signature_bind_arguments(self):
2882 def test(a, *args, b, z=100, **kwargs):
2883 pass
2884 sig = inspect.signature(test)
2885 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2886 # we won't have 'z' argument in the bound arguments object, as we didn't
2887 # pass it to the 'bind'
2888 self.assertEqual(tuple(ba.arguments.items()),
2889 (('a', 10), ('args', (20,)), ('b', 30),
2890 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2891 self.assertEqual(ba.kwargs,
2892 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2893 self.assertEqual(ba.args, (10, 20))
2894
2895 def test_signature_bind_positional_only(self):
2896 P = inspect.Parameter
2897
2898 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2899 return a_po, b_po, c_po, foo, bar, kwargs
2900
2901 sig = inspect.signature(test)
2902 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2903 for name in ('a_po', 'b_po', 'c_po'):
2904 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2905 new_sig = sig.replace(parameters=new_params.values())
2906 test.__signature__ = new_sig
2907
2908 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2909 (1, 2, 4, 5, 6, {}))
2910
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002911 self.assertEqual(self.call(test, 1, 2),
2912 (1, 2, 3, 42, 50, {}))
2913
2914 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
2915 (1, 2, 3, 4, 5, {}))
2916
2917 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
2918 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
2919
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002920 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002921 self.call(test, 1, 2, c_po=4)
2922
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002923 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002924 self.call(test, a_po=1, b_po=2)
2925
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002926 def test_signature_bind_with_self_arg(self):
2927 # Issue #17071: one of the parameters is named "self
2928 def test(a, self, b):
2929 pass
2930 sig = inspect.signature(test)
2931 ba = sig.bind(1, 2, 3)
2932 self.assertEqual(ba.args, (1, 2, 3))
2933 ba = sig.bind(1, self=2, b=3)
2934 self.assertEqual(ba.args, (1, 2, 3))
2935
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002936 def test_signature_bind_vararg_name(self):
2937 def test(a, *args):
2938 return a, args
2939 sig = inspect.signature(test)
2940
2941 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
2942 sig.bind(a=0, args=1)
2943
2944 def test(*args, **kwargs):
2945 return args, kwargs
2946 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
2947
2948 sig = inspect.signature(test)
2949 ba = sig.bind(args=1)
2950 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
2951
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002952
2953class TestBoundArguments(unittest.TestCase):
2954 def test_signature_bound_arguments_unhashable(self):
2955 def foo(a): pass
2956 ba = inspect.signature(foo).bind(1)
2957
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002958 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002959 hash(ba)
2960
2961 def test_signature_bound_arguments_equality(self):
2962 def foo(a): pass
2963 ba = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002964 self.assertTrue(ba == ba)
2965 self.assertFalse(ba != ba)
2966 self.assertTrue(ba == EqualsToAll())
2967 self.assertFalse(ba != EqualsToAll())
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002968
2969 ba2 = inspect.signature(foo).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002970 self.assertTrue(ba == ba2)
2971 self.assertFalse(ba != ba2)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002972
2973 ba3 = inspect.signature(foo).bind(2)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002974 self.assertFalse(ba == ba3)
2975 self.assertTrue(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002976 ba3.arguments['a'] = 1
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002977 self.assertTrue(ba == ba3)
2978 self.assertFalse(ba != ba3)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002979
2980 def bar(b): pass
2981 ba4 = inspect.signature(bar).bind(1)
Serhiy Storchaka3018cc42015-07-18 23:19:05 +03002982 self.assertFalse(ba == ba4)
2983 self.assertTrue(ba != ba4)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002984
2985
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002986class TestSignaturePrivateHelpers(unittest.TestCase):
2987 def test_signature_get_bound_param(self):
2988 getter = inspect._signature_get_bound_param
2989
2990 self.assertEqual(getter('($self)'), 'self')
2991 self.assertEqual(getter('($self, obj)'), 'self')
2992 self.assertEqual(getter('($cls, /, obj)'), 'cls')
2993
Larry Hastings2623c8c2014-02-08 22:15:29 -08002994 def _strip_non_python_syntax(self, input,
2995 clean_signature, self_parameter, last_positional_only):
2996 computed_clean_signature, \
2997 computed_self_parameter, \
2998 computed_last_positional_only = \
2999 inspect._signature_strip_non_python_syntax(input)
3000 self.assertEqual(computed_clean_signature, clean_signature)
3001 self.assertEqual(computed_self_parameter, self_parameter)
3002 self.assertEqual(computed_last_positional_only, last_positional_only)
3003
3004 def test_signature_strip_non_python_syntax(self):
3005 self._strip_non_python_syntax(
3006 "($module, /, path, mode, *, dir_fd=None, " +
3007 "effective_ids=False,\n follow_symlinks=True)",
3008 "(module, path, mode, *, dir_fd=None, " +
3009 "effective_ids=False, follow_symlinks=True)",
3010 0,
3011 0)
3012
3013 self._strip_non_python_syntax(
3014 "($module, word, salt, /)",
3015 "(module, word, salt)",
3016 0,
3017 2)
3018
3019 self._strip_non_python_syntax(
3020 "(x, y=None, z=None, /)",
3021 "(x, y=None, z=None)",
3022 None,
3023 2)
3024
3025 self._strip_non_python_syntax(
3026 "(x, y=None, z=None)",
3027 "(x, y=None, z=None)",
3028 None,
3029 None)
3030
3031 self._strip_non_python_syntax(
3032 "(x,\n y=None,\n z = None )",
3033 "(x, y=None, z=None)",
3034 None,
3035 None)
3036
3037 self._strip_non_python_syntax(
3038 "",
3039 "",
3040 None,
3041 None)
3042
3043 self._strip_non_python_syntax(
3044 None,
3045 None,
3046 None,
3047 None)
3048
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003049
Nick Coghlane8c45d62013-07-28 20:00:01 +10003050class TestUnwrap(unittest.TestCase):
3051
3052 def test_unwrap_one(self):
3053 def func(a, b):
3054 return a + b
3055 wrapper = functools.lru_cache(maxsize=20)(func)
3056 self.assertIs(inspect.unwrap(wrapper), func)
3057
3058 def test_unwrap_several(self):
3059 def func(a, b):
3060 return a + b
3061 wrapper = func
3062 for __ in range(10):
3063 @functools.wraps(wrapper)
3064 def wrapper():
3065 pass
3066 self.assertIsNot(wrapper.__wrapped__, func)
3067 self.assertIs(inspect.unwrap(wrapper), func)
3068
3069 def test_stop(self):
3070 def func1(a, b):
3071 return a + b
3072 @functools.wraps(func1)
3073 def func2():
3074 pass
3075 @functools.wraps(func2)
3076 def wrapper():
3077 pass
3078 func2.stop_here = 1
3079 unwrapped = inspect.unwrap(wrapper,
3080 stop=(lambda f: hasattr(f, "stop_here")))
3081 self.assertIs(unwrapped, func2)
3082
3083 def test_cycle(self):
3084 def func1(): pass
3085 func1.__wrapped__ = func1
3086 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3087 inspect.unwrap(func1)
3088
3089 def func2(): pass
3090 func2.__wrapped__ = func1
3091 func1.__wrapped__ = func2
3092 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3093 inspect.unwrap(func1)
3094 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3095 inspect.unwrap(func2)
3096
3097 def test_unhashable(self):
3098 def func(): pass
3099 func.__wrapped__ = None
3100 class C:
3101 __hash__ = None
3102 __wrapped__ = func
3103 self.assertIsNone(inspect.unwrap(C()))
3104
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003105class TestMain(unittest.TestCase):
3106 def test_only_source(self):
3107 module = importlib.import_module('unittest')
3108 rc, out, err = assert_python_ok('-m', 'inspect',
3109 'unittest')
3110 lines = out.decode().splitlines()
3111 # ignore the final newline
3112 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3113 self.assertEqual(err, b'')
3114
Yury Selivanovc0f964f2014-06-23 10:21:04 -07003115 def test_custom_getattr(self):
3116 def foo():
3117 pass
3118 foo.__signature__ = 42
3119 with self.assertRaises(TypeError):
3120 inspect.signature(foo)
3121
Brett Cannon634a8fc2013-10-02 10:25:42 -04003122 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003123 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003124 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003125 rc, out, err = assert_python_ok('-m', 'inspect',
3126 'concurrent.futures:ThreadPoolExecutor')
3127 lines = out.decode().splitlines()
3128 # ignore the final newline
3129 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003130 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003131 self.assertEqual(err, b'')
3132
3133 def test_builtins(self):
3134 module = importlib.import_module('unittest')
3135 _, out, err = assert_python_failure('-m', 'inspect',
3136 'sys')
3137 lines = err.decode().splitlines()
3138 self.assertEqual(lines, ["Can't get info for builtin modules."])
3139
3140 def test_details(self):
3141 module = importlib.import_module('unittest')
3142 rc, out, err = assert_python_ok('-m', 'inspect',
3143 'unittest', '--details')
3144 output = out.decode()
3145 # Just a quick sanity check on the output
3146 self.assertIn(module.__name__, output)
3147 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003148 if not sys.flags.optimize:
3149 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003150 self.assertEqual(err, b'')
3151
3152
Yury Selivanov7de29682014-12-08 18:00:25 -05003153class TestReload(unittest.TestCase):
3154
3155 src_before = textwrap.dedent("""\
3156def foo():
3157 print("Bla")
3158 """)
3159
3160 src_after = textwrap.dedent("""\
3161def foo():
3162 print("Oh no!")
3163 """)
3164
3165 def assertInspectEqual(self, path, source):
3166 inspected_src = inspect.getsource(source)
3167 with open(path) as src:
3168 self.assertEqual(
3169 src.read().splitlines(True),
3170 inspected_src.splitlines(True)
3171 )
3172
3173 def test_getsource_reload(self):
3174 # see issue 1218234
3175 with _ready_to_import('reload_bug', self.src_before) as (name, path):
3176 module = importlib.import_module(name)
3177 self.assertInspectEqual(path, module)
3178 with open(path, 'w') as src:
3179 src.write(self.src_after)
3180 self.assertInspectEqual(path, module)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003181
Nick Coghlane8c45d62013-07-28 20:00:01 +10003182
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003183def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003184 run_unittest(
3185 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3186 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3187 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003188 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003189 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003190 TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars,
Yury Selivanov7de29682014-12-08 18:00:25 -05003191 TestUnwrap, TestMain, TestReload
Michael Foord95fc51d2010-11-20 15:07:30 +00003192 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003193
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003194if __name__ == "__main__":
3195 test_main()