blob: 66d3fab429c268eb4305ef8af7ad7e65fbea9e99 [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
15import unicodedata
16import unittest
Yury Selivanov8dfb4572014-02-21 18:30:53 -050017import unittest.mock
Larry Hastings5c661892014-01-24 06:17:25 -080018
Brett Cannon634a8fc2013-10-02 10:25:42 -040019try:
20 from concurrent.futures import ThreadPoolExecutor
21except ImportError:
22 ThreadPoolExecutor = None
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000023
Serhiy Storchakaf28ba362014-02-07 10:10:55 +020024from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -080025from test.support import MISSING_C_DOCSTRINGS
Nick Coghlanf94a16b2013-09-22 22:46:49 +100026from test.script_helper import assert_python_ok, assert_python_failure
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000027from test import inspect_fodder as mod
28from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000029
R. David Murray74b89242009-05-13 17:33:03 +000030
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000031# Functions tested in this suite:
32# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000033# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
34# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
35# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
36# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000037
Nick Coghlanf088e5e2008-12-14 11:50:48 +000038# NOTE: There are some additional tests relating to interaction with
39# zipimport in the test_zipimport_support test module.
40
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000041modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000042if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000043 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000044
Christian Heimesa3538eb2007-11-06 11:44:48 +000045# Normalize file names: on Windows, the case of file names of compiled
46# modules depends on the path used to start the python executable.
47modfile = normcase(modfile)
48
49def revise(filename, *args):
50 return (normcase(filename),) + args
51
Georg Brandl1a3284e2007-12-02 09:40:06 +000052import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000053
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000054git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000055
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000056class IsTestBase(unittest.TestCase):
57 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
58 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000059 inspect.ismodule, inspect.istraceback,
60 inspect.isgenerator, inspect.isgeneratorfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000061
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000062 def istest(self, predicate, exp):
63 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000064 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000065
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000066 for other in self.predicates - set([predicate]):
Christian Heimes7131fd92008-02-19 14:21:46 +000067 if predicate == inspect.isgeneratorfunction and\
68 other == inspect.isfunction:
69 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000070 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000071
Christian Heimes7131fd92008-02-19 14:21:46 +000072def generator_function_example(self):
73 for i in range(2):
74 yield i
75
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000076class TestPredicates(IsTestBase):
Christian Heimes227c8002008-03-03 20:34:40 +000077 def test_sixteen(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +000078 count = len([x for x in dir(inspect) if x.startswith('is')])
Christian Heimes7131fd92008-02-19 14:21:46 +000079 # This test is here for remember you to update Doc/library/inspect.rst
Christian Heimes78644762008-03-04 23:39:23 +000080 # which claims there are 16 such functions
Christian Heimes227c8002008-03-03 20:34:40 +000081 expected = 16
Thomas Wouters0e3f5912006-08-11 14:57:12 +000082 err_msg = "There are %d (not %d) is* functions" % (count, expected)
83 self.assertEqual(count, expected, err_msg)
Tim Peters5a9fb3c2005-01-07 16:01:32 +000084
Christian Heimes7131fd92008-02-19 14:21:46 +000085
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000086 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020087 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000088 self.istest(inspect.isbuiltin, 'sys.exit')
89 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +000090 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +020091 try:
92 1/0
93 except:
94 tb = sys.exc_info()[2]
95 self.istest(inspect.isframe, 'tb.tb_frame')
96 self.istest(inspect.istraceback, 'tb')
97 if hasattr(types, 'GetSetDescriptorType'):
98 self.istest(inspect.isgetsetdescriptor,
99 'type(tb.tb_frame).f_locals')
100 else:
101 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
102 finally:
103 # Clear traceback and all the frames and local variables hanging to it.
104 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000105 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000106 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000107 self.istest(inspect.ismethod, 'git.argue')
108 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +0000109 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000110 self.istest(inspect.isgenerator, '(x for x in range(2))')
111 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000112 if hasattr(types, 'MemberDescriptorType'):
113 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
114 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000115 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000116
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000117 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000118 self.assertTrue(inspect.isroutine(mod.spam))
119 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000120
Benjamin Petersonc4656002009-01-17 22:41:18 +0000121 def test_isclass(self):
122 self.istest(inspect.isclass, 'mod.StupidGit')
123 self.assertTrue(inspect.isclass(list))
124
125 class CustomGetattr(object):
126 def __getattr__(self, attr):
127 return None
128 self.assertFalse(inspect.isclass(CustomGetattr()))
129
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000130 def test_get_slot_members(self):
131 class C(object):
132 __slots__ = ("a", "b")
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000133 x = C()
134 x.a = 42
135 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000136 self.assertIn('a', members)
137 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000138
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000139 def test_isabstract(self):
140 from abc import ABCMeta, abstractmethod
141
142 class AbstractClassExample(metaclass=ABCMeta):
143
144 @abstractmethod
145 def foo(self):
146 pass
147
148 class ClassExample(AbstractClassExample):
149 def foo(self):
150 pass
151
152 a = ClassExample()
153
154 # Test general behaviour.
155 self.assertTrue(inspect.isabstract(AbstractClassExample))
156 self.assertFalse(inspect.isabstract(ClassExample))
157 self.assertFalse(inspect.isabstract(a))
158 self.assertFalse(inspect.isabstract(int))
159 self.assertFalse(inspect.isabstract(5))
160
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000161
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000162class TestInterpreterStack(IsTestBase):
163 def __init__(self, *args, **kwargs):
164 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000165
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000166 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000167
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000168 def test_abuse_done(self):
169 self.istest(inspect.istraceback, 'git.ex[2]')
170 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000171
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000172 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000173 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000174 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000175 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000176 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000177 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000178 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000179 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000180 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000181 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000182
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000183 def test_trace(self):
184 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000185 self.assertEqual(revise(*git.tr[0][1:]),
186 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
187 self.assertEqual(revise(*git.tr[1][1:]),
188 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
189 self.assertEqual(revise(*git.tr[2][1:]),
190 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000191
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000192 def test_frame(self):
193 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
194 self.assertEqual(args, ['x', 'y'])
195 self.assertEqual(varargs, None)
196 self.assertEqual(varkw, None)
197 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
198 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
199 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000200
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000201 def test_previous_frame(self):
202 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000203 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000204 self.assertEqual(varargs, 'g')
205 self.assertEqual(varkw, 'h')
206 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000207 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000208
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000209class GetSourceBase(unittest.TestCase):
210 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000211 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000212
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000213 def __init__(self, *args, **kwargs):
214 unittest.TestCase.__init__(self, *args, **kwargs)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000215
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000216 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000217 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000218
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000219 def sourcerange(self, top, bottom):
220 lines = self.source.split("\n")
221 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000222
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000223 def assertSourceEqual(self, obj, top, bottom):
224 self.assertEqual(inspect.getsource(obj),
225 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000226
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000227class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000228 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000229
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000230 def test_getclasses(self):
231 classes = inspect.getmembers(mod, inspect.isclass)
232 self.assertEqual(classes,
233 [('FesteringGob', mod.FesteringGob),
234 ('MalodorousPervert', mod.MalodorousPervert),
235 ('ParrotDroppings', mod.ParrotDroppings),
Serhiy Storchaka362c1b52013-09-05 17:14:32 +0300236 ('StupidGit', mod.StupidGit),
237 ('Tit', mod.MalodorousPervert),
238 ])
239 tree = inspect.getclasstree([cls[1] for cls in classes])
240 self.assertEqual(tree,
241 [(object, ()),
242 [(mod.ParrotDroppings, (object,)),
243 [(mod.FesteringGob, (mod.MalodorousPervert,
244 mod.ParrotDroppings))
245 ],
246 (mod.StupidGit, (object,)),
247 [(mod.MalodorousPervert, (mod.StupidGit,)),
248 [(mod.FesteringGob, (mod.MalodorousPervert,
249 mod.ParrotDroppings))
250 ]
251 ]
252 ]
253 ])
254 tree = inspect.getclasstree([cls[1] for cls in classes], True)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000255 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000256 [(object, ()),
257 [(mod.ParrotDroppings, (object,)),
258 (mod.StupidGit, (object,)),
259 [(mod.MalodorousPervert, (mod.StupidGit,)),
260 [(mod.FesteringGob, (mod.MalodorousPervert,
261 mod.ParrotDroppings))
262 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000263 ]
264 ]
265 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000266
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000267 def test_getfunctions(self):
268 functions = inspect.getmembers(mod, inspect.isfunction)
269 self.assertEqual(functions, [('eggs', mod.eggs),
270 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000271
R. David Murray378c0cf2010-02-24 01:46:21 +0000272 @unittest.skipIf(sys.flags.optimize >= 2,
273 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000274 def test_getdoc(self):
275 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
276 self.assertEqual(inspect.getdoc(mod.StupidGit),
277 'A longer,\n\nindented\n\ndocstring.')
278 self.assertEqual(inspect.getdoc(git.abuse),
279 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000280
Georg Brandl0c77a822008-06-10 16:37:50 +0000281 def test_cleandoc(self):
282 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
283 'An\nindented\ndocstring.')
284
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000285 def test_getcomments(self):
286 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
287 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000288
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000289 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000290 # Check actual module
291 self.assertEqual(inspect.getmodule(mod), mod)
292 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000293 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000294 # Check a method (no __module__ attribute, falls back to filename)
295 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
296 # Do it again (check the caching isn't broken)
297 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
298 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000299 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000300 # Check filename override
301 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000302
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000303 def test_getsource(self):
304 self.assertSourceEqual(git.abuse, 29, 39)
305 self.assertSourceEqual(mod.StupidGit, 21, 46)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000306
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000307 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000308 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
309 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000310 fn = "_non_existing_filename_used_for_sourcefile_test.py"
311 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000312 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000313 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200314 try:
315 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
316 finally:
317 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000318
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000319 def test_getfile(self):
320 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000321
Yury Selivanov2eed8b72014-01-27 13:24:56 -0500322 def test_getfile_class_without_module(self):
323 class CM(type):
324 @property
325 def __module__(cls):
326 raise AttributeError
327 class C(metaclass=CM):
328 pass
329 with self.assertRaises(TypeError):
330 inspect.getfile(C)
331
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000332 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000333 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000334 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000335 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000336 m.__file__ = "<string>" # hopefully not a real filename...
337 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000338 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000339 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000340 del sys.modules[name]
341 inspect.getmodule(compile('a=10','','single'))
342
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500343 def test_proceed_with_fake_filename(self):
344 '''doctest monkeypatches linecache to enable inspection'''
345 fn, source = '<test>', 'def x(): pass\n'
346 getlines = linecache.getlines
347 def monkey(filename, module_globals=None):
348 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300349 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500350 else:
351 return getlines(filename, module_globals)
352 linecache.getlines = monkey
353 try:
354 ns = {}
355 exec(compile(source, fn, 'single'), ns)
356 inspect.getsource(ns["x"])
357 finally:
358 linecache.getlines = getlines
359
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000360class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000361 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000362
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000363 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000364 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000365
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000366 def test_replacing_decorator(self):
367 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000368
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000369class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000370 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000371 def test_oneline_lambda(self):
372 # Test inspect.getsource with a one-line lambda function.
373 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000374
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000375 def test_threeline_lambda(self):
376 # Test inspect.getsource with a three-line lambda function,
377 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000378 self.assertSourceEqual(mod2.tll, 28, 30)
379
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000380 def test_twoline_indented_lambda(self):
381 # Test inspect.getsource with a two-line lambda function,
382 # where the second line _is_ indented.
383 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000384
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000385 def test_onelinefunc(self):
386 # Test inspect.getsource with a regular one-line function.
387 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000388
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000389 def test_manyargs(self):
390 # Test inspect.getsource with a regular function where
391 # the arguments are on two lines and _not_ indented and
392 # the body on the second line with the last arguments.
393 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000394
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000395 def test_twolinefunc(self):
396 # Test inspect.getsource with a regular function where
397 # the body is on two lines, following the argument list and
398 # continued on the next line by a \\.
399 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000400
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000401 def test_lambda_in_list(self):
402 # Test inspect.getsource with a one-line lambda function
403 # defined in a list, indented.
404 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000405
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000406 def test_anonymous(self):
407 # Test inspect.getsource with a lambda function defined
408 # as argument to another function.
409 self.assertSourceEqual(mod2.anonymous, 55, 55)
410
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000411class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000412 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000413
414 def test_with_comment(self):
415 self.assertSourceEqual(mod2.with_comment, 58, 59)
416
417 def test_multiline_sig(self):
418 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
419
Armin Rigodd5c0232005-09-25 11:45:45 +0000420 def test_nested_class(self):
421 self.assertSourceEqual(mod2.func69().func71, 71, 72)
422
423 def test_one_liner_followed_by_non_name(self):
424 self.assertSourceEqual(mod2.func77, 77, 77)
425
426 def test_one_liner_dedent_non_name(self):
427 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
428
429 def test_with_comment_instead_of_docstring(self):
430 self.assertSourceEqual(mod2.func88, 88, 90)
431
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000432 def test_method_in_dynamic_class(self):
433 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
434
R David Murray32562d72014-10-03 11:15:38 -0400435 # This should not skip for CPython, but might on a repackaged python where
436 # unicodedata is not an external module, or on pypy.
437 @unittest.skipIf(not hasattr(unicodedata, '__file__') or
438 unicodedata.__file__.endswith('.py'),
439 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000440 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200441 self.assertRaises(OSError, inspect.getsource, unicodedata)
442 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000443
R. David Murraya1b37402010-06-17 02:04:29 +0000444 def test_findsource_code_in_linecache(self):
445 lines = ["x=1"]
446 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200447 self.assertRaises(OSError, inspect.findsource, co)
448 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000449 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200450 try:
451 self.assertEqual(inspect.findsource(co), (lines,0))
452 self.assertEqual(inspect.getsource(co), lines[0])
453 finally:
454 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000455
Ezio Melotti1b145922013-03-30 05:17:24 +0200456 def test_findsource_without_filename(self):
457 for fname in ['', '<string>']:
458 co = compile('x=1', fname, "exec")
459 self.assertRaises(IOError, inspect.findsource, co)
460 self.assertRaises(IOError, inspect.getsource, co)
461
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000462class TestNoEOL(GetSourceBase):
463 def __init__(self, *args, **kwargs):
464 self.tempdir = TESTFN + '_dir'
465 os.mkdir(self.tempdir)
466 with open(os.path.join(self.tempdir,
467 'inspect_fodder3%spy' % os.extsep), 'w') as f:
468 f.write("class X:\n pass # No EOL")
469 with DirsOnSysPath(self.tempdir):
470 import inspect_fodder3 as mod3
471 self.fodderModule = mod3
472 GetSourceBase.__init__(self, *args, **kwargs)
473
474 def tearDown(self):
475 shutil.rmtree(self.tempdir)
476
477 def test_class(self):
478 self.assertSourceEqual(self.fodderModule.X, 1, 2)
479
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100480
481class _BrokenDataDescriptor(object):
482 """
483 A broken data descriptor. See bug #1785.
484 """
485 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700486 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100487
488 def __set__(*args):
489 raise RuntimeError
490
491 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700492 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100493
494
495class _BrokenMethodDescriptor(object):
496 """
497 A broken method descriptor. See bug #1785.
498 """
499 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700500 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100501
502 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700503 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100504
505
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000506# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000507def attrs_wo_objs(cls):
508 return [t[:3] for t in inspect.classify_class_attrs(cls)]
509
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100510
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000511class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000512 def test_newstyle_mro(self):
513 # The same w/ new-class MRO.
514 class A(object): pass
515 class B(A): pass
516 class C(A): pass
517 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000518
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000519 expected = (D, B, C, A, object)
520 got = inspect.getmro(D)
521 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000522
Christian Heimes3795b532007-11-08 13:48:53 +0000523 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
524 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000525 args, varargs, varkw, defaults = inspect.getargspec(routine)
526 self.assertEqual(args, args_e)
527 self.assertEqual(varargs, varargs_e)
528 self.assertEqual(varkw, varkw_e)
529 self.assertEqual(defaults, defaults_e)
530 if formatted is not None:
531 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
532 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000533
Christian Heimes3795b532007-11-08 13:48:53 +0000534 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
535 varkw_e=None, defaults_e=None,
536 kwonlyargs_e=[], kwonlydefaults_e=None,
537 ann_e={}, formatted=None):
538 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
539 inspect.getfullargspec(routine)
540 self.assertEqual(args, args_e)
541 self.assertEqual(varargs, varargs_e)
542 self.assertEqual(varkw, varkw_e)
543 self.assertEqual(defaults, defaults_e)
544 self.assertEqual(kwonlyargs, kwonlyargs_e)
545 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
546 self.assertEqual(ann, ann_e)
547 if formatted is not None:
548 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
549 kwonlyargs, kwonlydefaults, ann),
550 formatted)
551
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000552 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000553 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000554
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000555 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000556 ['a', 'b', 'c', 'd', 'e', 'f'],
557 'g', 'h', (3, 4, 5),
558 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000559
Christian Heimes3795b532007-11-08 13:48:53 +0000560 self.assertRaises(ValueError, self.assertArgSpecEquals,
561 mod2.keyworded, [])
562
563 self.assertRaises(ValueError, self.assertArgSpecEquals,
564 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000565 self.assertRaises(ValueError, self.assertArgSpecEquals,
566 mod2.keyword_only_arg, [])
567
Christian Heimes3795b532007-11-08 13:48:53 +0000568
569 def test_getfullargspec(self):
570 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
571 kwonlyargs_e=['arg2'],
572 kwonlydefaults_e={'arg2':1},
573 formatted='(*arg1, arg2=1)')
574
575 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000576 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000577 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000578 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
579 kwonlyargs_e=['arg'],
580 formatted='(*, arg)')
581
Yury Selivanovff385b82014-02-19 16:27:23 -0500582 def test_argspec_api_ignores_wrapped(self):
583 # Issue 20684: low level introspection API must ignore __wrapped__
584 @functools.wraps(mod.spam)
585 def ham(x, y):
586 pass
587 # Basic check
588 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
589 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
590 self.assertFullArgSpecEquals(functools.partial(ham),
591 ['x', 'y'], formatted='(x, y)')
592 # Other variants
593 def check_method(f):
594 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
595 formatted='(self, x, y)')
596 class C:
597 @functools.wraps(mod.spam)
598 def ham(self, x, y):
599 pass
600 pham = functools.partialmethod(ham)
601 @functools.wraps(mod.spam)
602 def __call__(self, x, y):
603 pass
604 check_method(C())
605 check_method(C.ham)
606 check_method(C().ham)
607 check_method(C.pham)
608 check_method(C().pham)
609
610 class C_new:
611 @functools.wraps(mod.spam)
612 def __new__(self, x, y):
613 pass
614 check_method(C_new)
615
616 class C_init:
617 @functools.wraps(mod.spam)
618 def __init__(self, x, y):
619 pass
620 check_method(C_init)
621
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500622 def test_getfullargspec_signature_attr(self):
623 def test():
624 pass
625 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
626 test.__signature__ = inspect.Signature(parameters=(spam_param,))
627
628 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
629
Yury Selivanov4cb93912014-01-29 11:54:12 -0500630 def test_getfullargspec_signature_annos(self):
631 def test(a:'spam') -> 'ham': pass
632 spec = inspect.getfullargspec(test)
633 self.assertEqual(test.__annotations__, spec.annotations)
634
635 def test(): pass
636 spec = inspect.getfullargspec(test)
637 self.assertEqual(test.__annotations__, spec.annotations)
638
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500639 @unittest.skipIf(MISSING_C_DOCSTRINGS,
640 "Signature information for builtins requires docstrings")
641 def test_getfullargspec_builtin_methods(self):
642 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
643 args_e=['self', 'obj'], formatted='(self, obj)')
644
645 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
646 args_e=['self', 'obj'], formatted='(self, obj)')
647
Yury Selivanovd224b6a2014-02-21 01:32:42 -0500648 self.assertFullArgSpecEquals(
649 os.stat,
650 args_e=['path'],
651 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
652 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
653 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
654
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200655 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500656 @unittest.skipIf(MISSING_C_DOCSTRINGS,
657 "Signature information for builtins requires docstrings")
658 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200659 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500660 builtin = _testcapi.docstring_with_signature_with_defaults
661 spec = inspect.getfullargspec(builtin)
662 self.assertEqual(spec.defaults[0], 'avocado')
663
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200664 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500665 @unittest.skipIf(MISSING_C_DOCSTRINGS,
666 "Signature information for builtins requires docstrings")
667 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200668 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500669 builtin = _testcapi.docstring_no_signature
670 with self.assertRaises(TypeError):
671 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000672
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000673 def test_getargspec_method(self):
674 class A(object):
675 def m(self):
676 pass
677 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000678
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000679 def test_classify_newstyle(self):
680 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000681
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000682 def s(): pass
683 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000684
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000685 def c(cls): pass
686 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000687
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000688 def getp(self): pass
689 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000690
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000691 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000692
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000693 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000694
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000695 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000696
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100697 dd = _BrokenDataDescriptor()
698 md = _BrokenMethodDescriptor()
699
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000700 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500701
702 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
703 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
704
Benjamin Peterson577473f2010-01-19 00:09:57 +0000705 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
706 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
707 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000708 self.assertIn(('m', 'method', A), attrs,
709 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000710 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
711 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100712 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
713 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000714
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000715 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000716
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000717 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000718
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000719 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000720 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
721 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
722 self.assertIn(('p', 'property', A), attrs, 'missing property')
723 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
724 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
725 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100726 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
727 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000728
729
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000730 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000731
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000732 def m(self): pass
733 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000734
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000735 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000736 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
737 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
738 self.assertIn(('p', 'property', A), attrs, 'missing property')
739 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
740 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
741 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100742 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
743 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000744
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000745 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000746
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000747 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000748
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000749 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000750 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
751 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
752 self.assertIn(('p', 'property', A), attrs, 'missing property')
753 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
754 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
755 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100756 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
757 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
758
759 def test_classify_builtin_types(self):
760 # Simple sanity check that all built-in types can have their
761 # attributes classified.
762 for name in dir(__builtins__):
763 builtin = getattr(__builtins__, name)
764 if isinstance(builtin, type):
765 inspect.classify_class_attrs(builtin)
766
Ethan Furman63c141c2013-10-18 00:27:39 -0700767 def test_classify_DynamicClassAttribute(self):
768 class Meta(type):
769 def __getattr__(self, name):
770 if name == 'ham':
771 return 'spam'
772 return super().__getattr__(name)
773 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700774 @types.DynamicClassAttribute
775 def ham(self):
776 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700777 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
778 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700779 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700780 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
781
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700782 def test_classify_metaclass_class_attribute(self):
783 class Meta(type):
784 fish = 'slap'
785 def __dir__(self):
786 return ['__class__', '__modules__', '__name__', 'fish']
787 class Class(metaclass=Meta):
788 pass
789 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
790 self.assertIn(should_find, inspect.classify_class_attrs(Class))
791
Ethan Furman63c141c2013-10-18 00:27:39 -0700792 def test_classify_VirtualAttribute(self):
793 class Meta(type):
794 def __dir__(cls):
795 return ['__class__', '__module__', '__name__', 'BOOM']
796 def __getattr__(self, name):
797 if name =='BOOM':
798 return 42
799 return super().__getattr(name)
800 class Class(metaclass=Meta):
801 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700802 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700803 self.assertIn(should_find, inspect.classify_class_attrs(Class))
804
805 def test_classify_VirtualAttribute_multi_classes(self):
806 class Meta1(type):
807 def __dir__(cls):
808 return ['__class__', '__module__', '__name__', 'one']
809 def __getattr__(self, name):
810 if name =='one':
811 return 1
812 return super().__getattr__(name)
813 class Meta2(type):
814 def __dir__(cls):
815 return ['__class__', '__module__', '__name__', 'two']
816 def __getattr__(self, name):
817 if name =='two':
818 return 2
819 return super().__getattr__(name)
820 class Meta3(Meta1, Meta2):
821 def __dir__(cls):
822 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
823 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
824 def __getattr__(self, name):
825 if name =='three':
826 return 3
827 return super().__getattr__(name)
828 class Class1(metaclass=Meta1):
829 pass
830 class Class2(Class1, metaclass=Meta3):
831 pass
832
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700833 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
834 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
835 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700836 cca = inspect.classify_class_attrs(Class2)
837 for sf in (should_find1, should_find2, should_find3):
838 self.assertIn(sf, cca)
839
840 def test_classify_class_attrs_with_buggy_dir(self):
841 class M(type):
842 def __dir__(cls):
843 return ['__class__', '__name__', 'missing']
844 class C(metaclass=M):
845 pass
846 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
847 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700848
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100849 def test_getmembers_descriptors(self):
850 class A(object):
851 dd = _BrokenDataDescriptor()
852 md = _BrokenMethodDescriptor()
853
854 def pred_wrapper(pred):
855 # A quick'n'dirty way to discard standard attributes of new-style
856 # classes.
857 class Empty(object):
858 pass
859 def wrapped(x):
860 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
861 return False
862 return pred(x)
863 return wrapped
864
865 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
866 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
867
868 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
869 [('md', A.__dict__['md'])])
870 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
871 [('dd', A.__dict__['dd'])])
872
873 class B(A):
874 pass
875
876 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
877 [('md', A.__dict__['md'])])
878 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
879 [('dd', A.__dict__['dd'])])
880
Antoine Pitrou0c603812012-01-18 17:40:18 +0100881 def test_getmembers_method(self):
882 class B:
883 def f(self):
884 pass
885
886 self.assertIn(('f', B.f), inspect.getmembers(B))
887 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
888 b = B()
889 self.assertIn(('f', b.f), inspect.getmembers(b))
890 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
891
Ethan Furmane03ea372013-09-25 07:14:41 -0700892 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700893 class M(type):
894 def __getattr__(cls, name):
895 if name == 'eggs':
896 return 'scrambled'
897 return super().__getattr__(name)
898 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700899 @types.DynamicClassAttribute
900 def eggs(self):
901 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700902 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
903 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
904
905 def test_getmembers_with_buggy_dir(self):
906 class M(type):
907 def __dir__(cls):
908 return ['__class__', '__name__', 'missing']
909 class C(metaclass=M):
910 pass
911 attrs = [a[0] for a in inspect.getmembers(C)]
912 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700913
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000914
Nick Coghlan2f92e542012-06-23 19:39:55 +1000915_global_ref = object()
916class TestGetClosureVars(unittest.TestCase):
917
918 def test_name_resolution(self):
919 # Basic test of the 4 different resolution mechanisms
920 def f(nonlocal_ref):
921 def g(local_ref):
922 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
923 return g
924 _arg = object()
925 nonlocal_vars = {"nonlocal_ref": _arg}
926 global_vars = {"_global_ref": _global_ref}
927 builtin_vars = {"print": print}
928 unbound_names = {"unbound_ref"}
929 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
930 builtin_vars, unbound_names)
931 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
932
933 def test_generator_closure(self):
934 def f(nonlocal_ref):
935 def g(local_ref):
936 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
937 yield
938 return g
939 _arg = object()
940 nonlocal_vars = {"nonlocal_ref": _arg}
941 global_vars = {"_global_ref": _global_ref}
942 builtin_vars = {"print": print}
943 unbound_names = {"unbound_ref"}
944 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
945 builtin_vars, unbound_names)
946 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
947
948 def test_method_closure(self):
949 class C:
950 def f(self, nonlocal_ref):
951 def g(local_ref):
952 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
953 return g
954 _arg = object()
955 nonlocal_vars = {"nonlocal_ref": _arg}
956 global_vars = {"_global_ref": _global_ref}
957 builtin_vars = {"print": print}
958 unbound_names = {"unbound_ref"}
959 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
960 builtin_vars, unbound_names)
961 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
962
963 def test_nonlocal_vars(self):
964 # More complex tests of nonlocal resolution
965 def _nonlocal_vars(f):
966 return inspect.getclosurevars(f).nonlocals
967
968 def make_adder(x):
969 def add(y):
970 return x + y
971 return add
972
973 def curry(func, arg1):
974 return lambda arg2: func(arg1, arg2)
975
976 def less_than(a, b):
977 return a < b
978
979 # The infamous Y combinator.
980 def Y(le):
981 def g(f):
982 return le(lambda x: f(f)(x))
983 Y.g_ref = g
984 return g(g)
985
986 def check_y_combinator(func):
987 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
988
989 inc = make_adder(1)
990 add_two = make_adder(2)
991 greater_than_five = curry(less_than, 5)
992
993 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
994 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
995 self.assertEqual(_nonlocal_vars(greater_than_five),
996 {'arg1': 5, 'func': less_than})
997 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
998 {'x': 3})
999 Y(check_y_combinator)
1000
1001 def test_getclosurevars_empty(self):
1002 def foo(): pass
1003 _empty = inspect.ClosureVars({}, {}, {}, set())
1004 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1005 self.assertEqual(inspect.getclosurevars(foo), _empty)
1006
1007 def test_getclosurevars_error(self):
1008 class T: pass
1009 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1010 self.assertRaises(TypeError, inspect.getclosurevars, list)
1011 self.assertRaises(TypeError, inspect.getclosurevars, {})
1012
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001013 def _private_globals(self):
1014 code = """def f(): print(path)"""
1015 ns = {}
1016 exec(code, ns)
1017 return ns["f"], ns
1018
1019 def test_builtins_fallback(self):
1020 f, ns = self._private_globals()
1021 ns.pop("__builtins__", None)
1022 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1023 self.assertEqual(inspect.getclosurevars(f), expected)
1024
1025 def test_builtins_as_dict(self):
1026 f, ns = self._private_globals()
1027 ns["__builtins__"] = {"path":1}
1028 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1029 self.assertEqual(inspect.getclosurevars(f), expected)
1030
1031 def test_builtins_as_module(self):
1032 f, ns = self._private_globals()
1033 ns["__builtins__"] = os
1034 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1035 self.assertEqual(inspect.getclosurevars(f), expected)
1036
Nick Coghlan2f92e542012-06-23 19:39:55 +10001037
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001038class TestGetcallargsFunctions(unittest.TestCase):
1039
1040 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1041 locs = dict(locs or {}, func=func)
1042 r1 = eval('func(%s)' % call_params_string, None, locs)
1043 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1044 locs)
1045 self.assertEqual(r1, r2)
1046
1047 def assertEqualException(self, func, call_param_string, locs=None):
1048 locs = dict(locs or {}, func=func)
1049 try:
1050 eval('func(%s)' % call_param_string, None, locs)
1051 except Exception as e:
1052 ex1 = e
1053 else:
1054 self.fail('Exception not raised')
1055 try:
1056 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1057 locs)
1058 except Exception as e:
1059 ex2 = e
1060 else:
1061 self.fail('Exception not raised')
1062 self.assertIs(type(ex1), type(ex2))
1063 self.assertEqual(str(ex1), str(ex2))
1064 del ex1, ex2
1065
1066 def makeCallable(self, signature):
1067 """Create a function that returns its locals()"""
1068 code = "lambda %s: locals()"
1069 return eval(code % signature)
1070
1071 def test_plain(self):
1072 f = self.makeCallable('a, b=1')
1073 self.assertEqualCallArgs(f, '2')
1074 self.assertEqualCallArgs(f, '2, 3')
1075 self.assertEqualCallArgs(f, 'a=2')
1076 self.assertEqualCallArgs(f, 'b=3, a=2')
1077 self.assertEqualCallArgs(f, '2, b=3')
1078 # expand *iterable / **mapping
1079 self.assertEqualCallArgs(f, '*(2,)')
1080 self.assertEqualCallArgs(f, '*[2]')
1081 self.assertEqualCallArgs(f, '*(2, 3)')
1082 self.assertEqualCallArgs(f, '*[2, 3]')
1083 self.assertEqualCallArgs(f, '**{"a":2}')
1084 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1085 self.assertEqualCallArgs(f, '2, **{"b":3}')
1086 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1087 # expand UserList / UserDict
1088 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1089 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1090 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1091 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1092 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1093
1094 def test_varargs(self):
1095 f = self.makeCallable('a, b=1, *c')
1096 self.assertEqualCallArgs(f, '2')
1097 self.assertEqualCallArgs(f, '2, 3')
1098 self.assertEqualCallArgs(f, '2, 3, 4')
1099 self.assertEqualCallArgs(f, '*(2,3,4)')
1100 self.assertEqualCallArgs(f, '2, *[3,4]')
1101 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1102
1103 def test_varkw(self):
1104 f = self.makeCallable('a, b=1, **c')
1105 self.assertEqualCallArgs(f, 'a=2')
1106 self.assertEqualCallArgs(f, '2, b=3, c=4')
1107 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1108 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1109 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1110 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1111 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1112 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1113 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1114
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001115 def test_varkw_only(self):
1116 # issue11256:
1117 f = self.makeCallable('**c')
1118 self.assertEqualCallArgs(f, '')
1119 self.assertEqualCallArgs(f, 'a=1')
1120 self.assertEqualCallArgs(f, 'a=1, b=2')
1121 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1122 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1123 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1124
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001125 def test_keyword_only(self):
1126 f = self.makeCallable('a=3, *, c, d=2')
1127 self.assertEqualCallArgs(f, 'c=3')
1128 self.assertEqualCallArgs(f, 'c=3, a=3')
1129 self.assertEqualCallArgs(f, 'a=2, c=4')
1130 self.assertEqualCallArgs(f, '4, c=4')
1131 self.assertEqualException(f, '')
1132 self.assertEqualException(f, '3')
1133 self.assertEqualException(f, 'a=3')
1134 self.assertEqualException(f, 'd=4')
1135
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001136 f = self.makeCallable('*, c, d=2')
1137 self.assertEqualCallArgs(f, 'c=3')
1138 self.assertEqualCallArgs(f, 'c=3, d=4')
1139 self.assertEqualCallArgs(f, 'd=4, c=3')
1140
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001141 def test_multiple_features(self):
1142 f = self.makeCallable('a, b=2, *f, **g')
1143 self.assertEqualCallArgs(f, '2, 3, 7')
1144 self.assertEqualCallArgs(f, '2, 3, x=8')
1145 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1146 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1147 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1148 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1149 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1150 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1151 '(4,[5,6])]), **collections.UserDict('
1152 'y=9, z=10)')
1153
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001154 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1155 self.assertEqualCallArgs(f, '2, 3, x=8')
1156 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1157 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1158 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1159 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1160 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1161 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1162 '(4,[5,6])]), q=0, **collections.UserDict('
1163 'y=9, z=10)')
1164
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001165 def test_errors(self):
1166 f0 = self.makeCallable('')
1167 f1 = self.makeCallable('a, b')
1168 f2 = self.makeCallable('a, b=1')
1169 # f0 takes no arguments
1170 self.assertEqualException(f0, '1')
1171 self.assertEqualException(f0, 'x=1')
1172 self.assertEqualException(f0, '1,x=1')
1173 # f1 takes exactly 2 arguments
1174 self.assertEqualException(f1, '')
1175 self.assertEqualException(f1, '1')
1176 self.assertEqualException(f1, 'a=2')
1177 self.assertEqualException(f1, 'b=3')
1178 # f2 takes at least 1 argument
1179 self.assertEqualException(f2, '')
1180 self.assertEqualException(f2, 'b=3')
1181 for f in f1, f2:
1182 # f1/f2 takes exactly/at most 2 arguments
1183 self.assertEqualException(f, '2, 3, 4')
1184 self.assertEqualException(f, '1, 2, 3, a=1')
1185 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001186 # XXX: success of this one depends on dict order
1187 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001188 # f got an unexpected keyword argument
1189 self.assertEqualException(f, 'c=2')
1190 self.assertEqualException(f, '2, c=3')
1191 self.assertEqualException(f, '2, 3, c=4')
1192 self.assertEqualException(f, '2, c=4, b=3')
1193 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1194 # f got multiple values for keyword argument
1195 self.assertEqualException(f, '1, a=2')
1196 self.assertEqualException(f, '1, **{"a":2}')
1197 self.assertEqualException(f, '1, 2, b=3')
1198 # XXX: Python inconsistency
1199 # - for functions and bound methods: unexpected keyword 'c'
1200 # - for unbound methods: multiple values for keyword 'a'
1201 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001202 # issue11256:
1203 f3 = self.makeCallable('**c')
1204 self.assertEqualException(f3, '1, 2')
1205 self.assertEqualException(f3, '1, 2, a=1, b=2')
1206 f4 = self.makeCallable('*, a, b=0')
1207 self.assertEqualException(f3, '1, 2')
1208 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001209
Yury Selivanovb1d060b2014-03-27 18:23:03 -04001210 # issue #20816: getcallargs() fails to iterate over non-existent
1211 # kwonlydefaults and raises a wrong TypeError
1212 def f5(*, a): pass
1213 with self.assertRaisesRegex(TypeError,
1214 'missing 1 required keyword-only'):
1215 inspect.getcallargs(f5)
1216
1217
Yury Selivanov2542b662014-03-27 18:42:52 -04001218 # issue20817:
1219 def f6(a, b, c):
1220 pass
1221 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1222 inspect.getcallargs(f6)
1223
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001224class TestGetcallargsMethods(TestGetcallargsFunctions):
1225
1226 def setUp(self):
1227 class Foo(object):
1228 pass
1229 self.cls = Foo
1230 self.inst = Foo()
1231
1232 def makeCallable(self, signature):
1233 assert 'self' not in signature
1234 mk = super(TestGetcallargsMethods, self).makeCallable
1235 self.cls.method = mk('self, ' + signature)
1236 return self.inst.method
1237
1238class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1239
1240 def makeCallable(self, signature):
1241 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1242 return self.cls.method
1243
1244 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1245 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1246 *self._getAssertEqualParams(func, call_params_string, locs))
1247
1248 def assertEqualException(self, func, call_params_string, locs=None):
1249 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1250 *self._getAssertEqualParams(func, call_params_string, locs))
1251
1252 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1253 assert 'inst' not in call_params_string
1254 locs = dict(locs or {}, inst=self.inst)
1255 return (func, 'inst,' + call_params_string, locs)
1256
Michael Foord95fc51d2010-11-20 15:07:30 +00001257
1258class TestGetattrStatic(unittest.TestCase):
1259
1260 def test_basic(self):
1261 class Thing(object):
1262 x = object()
1263
1264 thing = Thing()
1265 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1266 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1267 with self.assertRaises(AttributeError):
1268 inspect.getattr_static(thing, 'y')
1269
1270 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1271
1272 def test_inherited(self):
1273 class Thing(object):
1274 x = object()
1275 class OtherThing(Thing):
1276 pass
1277
1278 something = OtherThing()
1279 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1280
1281 def test_instance_attr(self):
1282 class Thing(object):
1283 x = 2
1284 def __init__(self, x):
1285 self.x = x
1286 thing = Thing(3)
1287 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1288 del thing.x
1289 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1290
1291 def test_property(self):
1292 class Thing(object):
1293 @property
1294 def x(self):
1295 raise AttributeError("I'm pretending not to exist")
1296 thing = Thing()
1297 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1298
Ezio Melotti75cbd732011-04-28 00:59:29 +03001299 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001300 class descriptor(object):
1301 def __get__(*_):
1302 raise AttributeError("I'm pretending not to exist")
1303 desc = descriptor()
1304 class Thing(object):
1305 x = desc
1306 thing = Thing()
1307 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1308
1309 def test_classAttribute(self):
1310 class Thing(object):
1311 x = object()
1312
1313 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1314
Ethan Furmane03ea372013-09-25 07:14:41 -07001315 def test_classVirtualAttribute(self):
1316 class Thing(object):
1317 @types.DynamicClassAttribute
1318 def x(self):
1319 return self._x
1320 _x = object()
1321
1322 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1323
Michael Foord95fc51d2010-11-20 15:07:30 +00001324 def test_inherited_classattribute(self):
1325 class Thing(object):
1326 x = object()
1327 class OtherThing(Thing):
1328 pass
1329
1330 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1331
1332 def test_slots(self):
1333 class Thing(object):
1334 y = 'bar'
1335 __slots__ = ['x']
1336 def __init__(self):
1337 self.x = 'foo'
1338 thing = Thing()
1339 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1340 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1341
1342 del thing.x
1343 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1344
1345 def test_metaclass(self):
1346 class meta(type):
1347 attr = 'foo'
1348 class Thing(object, metaclass=meta):
1349 pass
1350 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1351
1352 class sub(meta):
1353 pass
1354 class OtherThing(object, metaclass=sub):
1355 x = 3
1356 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1357
1358 class OtherOtherThing(OtherThing):
1359 pass
1360 # this test is odd, but it was added as it exposed a bug
1361 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1362
1363 def test_no_dict_no_slots(self):
1364 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1365 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1366
1367 def test_no_dict_no_slots_instance_member(self):
1368 # returns descriptor
1369 with open(__file__) as handle:
1370 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1371
1372 def test_inherited_slots(self):
1373 # returns descriptor
1374 class Thing(object):
1375 __slots__ = ['x']
1376 def __init__(self):
1377 self.x = 'foo'
1378
1379 class OtherThing(Thing):
1380 pass
1381 # it would be nice if this worked...
1382 # we get the descriptor instead of the instance attribute
1383 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1384
1385 def test_descriptor(self):
1386 class descriptor(object):
1387 def __get__(self, instance, owner):
1388 return 3
1389 class Foo(object):
1390 d = descriptor()
1391
1392 foo = Foo()
1393
1394 # for a non data descriptor we return the instance attribute
1395 foo.__dict__['d'] = 1
1396 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1397
1398 # if the descriptor is a data-desciptor we should return the
1399 # descriptor
1400 descriptor.__set__ = lambda s, i, v: None
1401 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1402
1403
1404 def test_metaclass_with_descriptor(self):
1405 class descriptor(object):
1406 def __get__(self, instance, owner):
1407 return 3
1408 class meta(type):
1409 d = descriptor()
1410 class Thing(object, metaclass=meta):
1411 pass
1412 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1413
1414
Michael Foordcc7ebb82010-11-20 16:20:16 +00001415 def test_class_as_property(self):
1416 class Base(object):
1417 foo = 3
1418
1419 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001420 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001421 @property
1422 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001423 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001424 return object
1425
Michael Foord35184ed2010-11-20 16:58:30 +00001426 instance = Something()
1427 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1428 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001429 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1430
Michael Foorde5162652010-11-20 16:40:44 +00001431 def test_mro_as_property(self):
1432 class Meta(type):
1433 @property
1434 def __mro__(self):
1435 return (object,)
1436
1437 class Base(object):
1438 foo = 3
1439
1440 class Something(Base, metaclass=Meta):
1441 pass
1442
1443 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1444 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1445
Michael Foorddcebe0f2011-03-15 19:20:44 -04001446 def test_dict_as_property(self):
1447 test = self
1448 test.called = False
1449
1450 class Foo(dict):
1451 a = 3
1452 @property
1453 def __dict__(self):
1454 test.called = True
1455 return {}
1456
1457 foo = Foo()
1458 foo.a = 4
1459 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1460 self.assertFalse(test.called)
1461
1462 def test_custom_object_dict(self):
1463 test = self
1464 test.called = False
1465
1466 class Custom(dict):
1467 def get(self, key, default=None):
1468 test.called = True
1469 super().get(key, default)
1470
1471 class Foo(object):
1472 a = 3
1473 foo = Foo()
1474 foo.__dict__ = Custom()
1475 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1476 self.assertFalse(test.called)
1477
1478 def test_metaclass_dict_as_property(self):
1479 class Meta(type):
1480 @property
1481 def __dict__(self):
1482 self.executed = True
1483
1484 class Thing(metaclass=Meta):
1485 executed = False
1486
1487 def __init__(self):
1488 self.spam = 42
1489
1490 instance = Thing()
1491 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1492 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001493
Michael Foorda51623b2011-12-18 22:01:40 +00001494 def test_module(self):
1495 sentinel = object()
1496 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1497 sentinel)
1498
Michael Foord3ba95f82011-12-22 01:13:37 +00001499 def test_metaclass_with_metaclass_with_dict_as_property(self):
1500 class MetaMeta(type):
1501 @property
1502 def __dict__(self):
1503 self.executed = True
1504 return dict(spam=42)
1505
1506 class Meta(type, metaclass=MetaMeta):
1507 executed = False
1508
1509 class Thing(metaclass=Meta):
1510 pass
1511
1512 with self.assertRaises(AttributeError):
1513 inspect.getattr_static(Thing, "spam")
1514 self.assertFalse(Thing.executed)
1515
Nick Coghlane0f04652010-11-21 03:44:04 +00001516class TestGetGeneratorState(unittest.TestCase):
1517
1518 def setUp(self):
1519 def number_generator():
1520 for number in range(5):
1521 yield number
1522 self.generator = number_generator()
1523
1524 def _generatorstate(self):
1525 return inspect.getgeneratorstate(self.generator)
1526
1527 def test_created(self):
1528 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1529
1530 def test_suspended(self):
1531 next(self.generator)
1532 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1533
1534 def test_closed_after_exhaustion(self):
1535 for i in self.generator:
1536 pass
1537 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1538
1539 def test_closed_after_immediate_exception(self):
1540 with self.assertRaises(RuntimeError):
1541 self.generator.throw(RuntimeError)
1542 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1543
1544 def test_running(self):
1545 # As mentioned on issue #10220, checking for the RUNNING state only
1546 # makes sense inside the generator itself.
1547 # The following generator checks for this by using the closure's
1548 # reference to self and the generator state checking helper method
1549 def running_check_generator():
1550 for number in range(5):
1551 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1552 yield number
1553 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1554 self.generator = running_check_generator()
1555 # Running up to the first yield
1556 next(self.generator)
1557 # Running after the first yield
1558 next(self.generator)
1559
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001560 def test_easy_debugging(self):
1561 # repr() and str() of a generator state should contain the state name
1562 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1563 for name in names:
1564 state = getattr(inspect, name)
1565 self.assertIn(name, repr(state))
1566 self.assertIn(name, str(state))
1567
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001568 def test_getgeneratorlocals(self):
1569 def each(lst, a=None):
1570 b=(1, 2, 3)
1571 for v in lst:
1572 if v == 3:
1573 c = 12
1574 yield v
1575
1576 numbers = each([1, 2, 3])
1577 self.assertEqual(inspect.getgeneratorlocals(numbers),
1578 {'a': None, 'lst': [1, 2, 3]})
1579 next(numbers)
1580 self.assertEqual(inspect.getgeneratorlocals(numbers),
1581 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1582 'b': (1, 2, 3)})
1583 next(numbers)
1584 self.assertEqual(inspect.getgeneratorlocals(numbers),
1585 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1586 'b': (1, 2, 3)})
1587 next(numbers)
1588 self.assertEqual(inspect.getgeneratorlocals(numbers),
1589 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1590 'b': (1, 2, 3), 'c': 12})
1591 try:
1592 next(numbers)
1593 except StopIteration:
1594 pass
1595 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1596
1597 def test_getgeneratorlocals_empty(self):
1598 def yield_one():
1599 yield 1
1600 one = yield_one()
1601 self.assertEqual(inspect.getgeneratorlocals(one), {})
1602 try:
1603 next(one)
1604 except StopIteration:
1605 pass
1606 self.assertEqual(inspect.getgeneratorlocals(one), {})
1607
1608 def test_getgeneratorlocals_error(self):
1609 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1610 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1611 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1612 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1613
Nick Coghlane0f04652010-11-21 03:44:04 +00001614
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001615class TestSignatureObject(unittest.TestCase):
1616 @staticmethod
1617 def signature(func):
1618 sig = inspect.signature(func)
1619 return (tuple((param.name,
1620 (... if param.default is param.empty else param.default),
1621 (... if param.annotation is param.empty
1622 else param.annotation),
1623 str(param.kind).lower())
1624 for param in sig.parameters.values()),
1625 (... if sig.return_annotation is sig.empty
1626 else sig.return_annotation))
1627
1628 def test_signature_object(self):
1629 S = inspect.Signature
1630 P = inspect.Parameter
1631
1632 self.assertEqual(str(S()), '()')
1633
Yury Selivanov07a9e452014-01-29 10:58:16 -05001634 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001635 pass
1636 sig = inspect.signature(test)
1637 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001638 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001639 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001640 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001641 args = sig.parameters['args']
1642 ko = sig.parameters['ko']
1643 kwargs = sig.parameters['kwargs']
1644
1645 S((po, pk, args, ko, kwargs))
1646
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001647 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001648 S((pk, po, args, ko, kwargs))
1649
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001650 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001651 S((po, args, pk, ko, kwargs))
1652
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001653 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001654 S((args, po, pk, ko, kwargs))
1655
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001656 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001657 S((po, pk, args, kwargs, ko))
1658
1659 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001660 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001661 S((po, pk, args, kwargs2, ko))
1662
Yury Selivanov07a9e452014-01-29 10:58:16 -05001663 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1664 S((pod, po))
1665
1666 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1667 S((po, pkd, pk))
1668
1669 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1670 S((pkd, pk))
1671
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001672 def test_signature_immutability(self):
1673 def test(a):
1674 pass
1675 sig = inspect.signature(test)
1676
1677 with self.assertRaises(AttributeError):
1678 sig.foo = 'bar'
1679
1680 with self.assertRaises(TypeError):
1681 sig.parameters['a'] = None
1682
1683 def test_signature_on_noarg(self):
1684 def test():
1685 pass
1686 self.assertEqual(self.signature(test), ((), ...))
1687
1688 def test_signature_on_wargs(self):
1689 def test(a, b:'foo') -> 123:
1690 pass
1691 self.assertEqual(self.signature(test),
1692 ((('a', ..., ..., "positional_or_keyword"),
1693 ('b', ..., 'foo', "positional_or_keyword")),
1694 123))
1695
1696 def test_signature_on_wkwonly(self):
1697 def test(*, a:float, b:str) -> int:
1698 pass
1699 self.assertEqual(self.signature(test),
1700 ((('a', ..., float, "keyword_only"),
1701 ('b', ..., str, "keyword_only")),
1702 int))
1703
1704 def test_signature_on_complex_args(self):
1705 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1706 pass
1707 self.assertEqual(self.signature(test),
1708 ((('a', ..., ..., "positional_or_keyword"),
1709 ('b', 10, 'foo', "positional_or_keyword"),
1710 ('args', ..., 'bar', "var_positional"),
1711 ('spam', ..., 'baz', "keyword_only"),
1712 ('ham', 123, ..., "keyword_only"),
1713 ('kwargs', ..., int, "var_keyword")),
1714 ...))
1715
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001716 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001717 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1718 "Signature information for builtins requires docstrings")
1719 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001720 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001721
Larry Hastings5c661892014-01-24 06:17:25 -08001722 def test_unbound_method(o):
1723 """Use this to test unbound methods (things that should have a self)"""
1724 signature = inspect.signature(o)
1725 self.assertTrue(isinstance(signature, inspect.Signature))
1726 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1727 return signature
1728
1729 def test_callable(o):
1730 """Use this to test bound methods or normal callables (things that don't expect self)"""
1731 signature = inspect.signature(o)
1732 self.assertTrue(isinstance(signature, inspect.Signature))
1733 if signature.parameters:
1734 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1735 return signature
1736
1737 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001738 def p(name): return signature.parameters[name].default
1739 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001740 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001741 self.assertEqual(p('d'), 3.14)
1742 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001743 self.assertEqual(p('n'), None)
1744 self.assertEqual(p('t'), True)
1745 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001746 self.assertEqual(p('local'), 3)
1747 self.assertEqual(p('sys'), sys.maxsize)
1748 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001749
Larry Hastings5c661892014-01-24 06:17:25 -08001750 test_callable(object)
1751
1752 # normal method
1753 # (PyMethodDescr_Type, "method_descriptor")
1754 test_unbound_method(_pickle.Pickler.dump)
1755 d = _pickle.Pickler(io.StringIO())
1756 test_callable(d.dump)
1757
1758 # static method
1759 test_callable(str.maketrans)
1760 test_callable('abc'.maketrans)
1761
1762 # class method
1763 test_callable(dict.fromkeys)
1764 test_callable({}.fromkeys)
1765
1766 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1767 test_unbound_method(type.__call__)
1768 test_unbound_method(int.__add__)
1769 test_callable((3).__add__)
1770
1771 # _PyMethodWrapper_Type
1772 # support for 'method-wrapper'
1773 test_callable(min.__call__)
1774
Larry Hastings2623c8c2014-02-08 22:15:29 -08001775 # This doesn't work now.
1776 # (We don't have a valid signature for "type" in 3.4)
1777 with self.assertRaisesRegex(ValueError, "no signature found"):
1778 class ThisWorksNow:
1779 __call__ = type
1780 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001781
Yury Selivanovd930d852014-03-02 12:25:27 -05001782 # Regression test for issue #20786
1783 test_unbound_method(dict.__delitem__)
1784 test_unbound_method(property.__delete__)
1785
1786
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001787 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001788 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1789 "Signature information for builtins requires docstrings")
1790 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001791 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001792 func = _testcapi.docstring_with_signature_with_defaults
1793
1794 def decorator(func):
1795 @functools.wraps(func)
1796 def wrapper(*args, **kwargs) -> int:
1797 return func(*args, **kwargs)
1798 return wrapper
1799
1800 decorated_func = decorator(func)
1801
1802 self.assertEqual(inspect.signature(func),
1803 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08001804
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001805 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08001806 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001807 import _testcapi
Larry Hastings5c661892014-01-24 06:17:25 -08001808 with self.assertRaisesRegex(ValueError, 'no signature found for builtin'):
1809 inspect.signature(_testcapi.docstring_no_signature)
1810
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001811 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001812 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001813 inspect.signature(42)
1814
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001815 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001816 inspect.Signature.from_function(42)
1817
Yury Selivanovb77511d2014-01-29 10:46:14 -05001818 def test_signature_from_builtin_errors(self):
1819 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1820 inspect.Signature.from_builtin(42)
1821
Yury Selivanov63da7c72014-01-31 14:48:37 -05001822 def test_signature_from_functionlike_object(self):
1823 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1824 pass
1825
1826 class funclike:
1827 # Has to be callable, and have correct
1828 # __code__, __annotations__, __defaults__, __name__,
1829 # and __kwdefaults__ attributes
1830
1831 def __init__(self, func):
1832 self.__name__ = func.__name__
1833 self.__code__ = func.__code__
1834 self.__annotations__ = func.__annotations__
1835 self.__defaults__ = func.__defaults__
1836 self.__kwdefaults__ = func.__kwdefaults__
1837 self.func = func
1838
1839 def __call__(self, *args, **kwargs):
1840 return self.func(*args, **kwargs)
1841
1842 sig_func = inspect.Signature.from_function(func)
1843
1844 sig_funclike = inspect.Signature.from_function(funclike(func))
1845 self.assertEqual(sig_funclike, sig_func)
1846
1847 sig_funclike = inspect.signature(funclike(func))
1848 self.assertEqual(sig_funclike, sig_func)
1849
1850 # If object is not a duck type of function, then
1851 # signature will try to get a signature for its '__call__'
1852 # method
1853 fl = funclike(func)
1854 del fl.__defaults__
1855 self.assertEqual(self.signature(fl),
1856 ((('args', ..., ..., "var_positional"),
1857 ('kwargs', ..., ..., "var_keyword")),
1858 ...))
1859
Yury Selivanov8dfb4572014-02-21 18:30:53 -05001860 # Test with cython-like builtins:
1861 _orig_isdesc = inspect.ismethoddescriptor
1862 def _isdesc(obj):
1863 if hasattr(obj, '_builtinmock'):
1864 return True
1865 return _orig_isdesc(obj)
1866
1867 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
1868 builtin_func = funclike(func)
1869 # Make sure that our mock setup is working
1870 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
1871 builtin_func._builtinmock = True
1872 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
1873 self.assertEqual(inspect.signature(builtin_func), sig_func)
1874
Yury Selivanov63da7c72014-01-31 14:48:37 -05001875 def test_signature_functionlike_class(self):
1876 # We only want to duck type function-like objects,
1877 # not classes.
1878
1879 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1880 pass
1881
1882 class funclike:
1883 def __init__(self, marker):
1884 pass
1885
1886 __name__ = func.__name__
1887 __code__ = func.__code__
1888 __annotations__ = func.__annotations__
1889 __defaults__ = func.__defaults__
1890 __kwdefaults__ = func.__kwdefaults__
1891
1892 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1893 inspect.Signature.from_function(funclike)
1894
1895 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1896
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001897 def test_signature_on_method(self):
1898 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05001899 def __init__(*args):
1900 pass
1901 def m1(self, arg1, arg2=1) -> int:
1902 pass
1903 def m2(*args):
1904 pass
1905 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001906 pass
1907
Yury Selivanov62560fb2014-01-28 12:26:24 -05001908 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001909 ((('arg1', ..., ..., "positional_or_keyword"),
1910 ('arg2', 1, ..., "positional_or_keyword")),
1911 int))
1912
Yury Selivanov62560fb2014-01-28 12:26:24 -05001913 self.assertEqual(self.signature(Test().m2),
1914 ((('args', ..., ..., "var_positional"),),
1915 ...))
1916
1917 self.assertEqual(self.signature(Test),
1918 ((('args', ..., ..., "var_positional"),),
1919 ...))
1920
1921 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
1922 self.signature(Test())
1923
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001924 def test_signature_on_classmethod(self):
1925 class Test:
1926 @classmethod
1927 def foo(cls, arg1, *, arg2=1):
1928 pass
1929
1930 meth = Test().foo
1931 self.assertEqual(self.signature(meth),
1932 ((('arg1', ..., ..., "positional_or_keyword"),
1933 ('arg2', 1, ..., "keyword_only")),
1934 ...))
1935
1936 meth = Test.foo
1937 self.assertEqual(self.signature(meth),
1938 ((('arg1', ..., ..., "positional_or_keyword"),
1939 ('arg2', 1, ..., "keyword_only")),
1940 ...))
1941
1942 def test_signature_on_staticmethod(self):
1943 class Test:
1944 @staticmethod
1945 def foo(cls, *, arg):
1946 pass
1947
1948 meth = Test().foo
1949 self.assertEqual(self.signature(meth),
1950 ((('cls', ..., ..., "positional_or_keyword"),
1951 ('arg', ..., ..., "keyword_only")),
1952 ...))
1953
1954 meth = Test.foo
1955 self.assertEqual(self.signature(meth),
1956 ((('cls', ..., ..., "positional_or_keyword"),
1957 ('arg', ..., ..., "keyword_only")),
1958 ...))
1959
1960 def test_signature_on_partial(self):
1961 from functools import partial
1962
Yury Selivanov0fceaf42014-04-08 11:28:02 -04001963 Parameter = inspect.Parameter
1964
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001965 def test():
1966 pass
1967
1968 self.assertEqual(self.signature(partial(test)), ((), ...))
1969
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001970 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001971 inspect.signature(partial(test, 1))
1972
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001973 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001974 inspect.signature(partial(test, a=1))
1975
1976 def test(a, b, *, c, d):
1977 pass
1978
1979 self.assertEqual(self.signature(partial(test)),
1980 ((('a', ..., ..., "positional_or_keyword"),
1981 ('b', ..., ..., "positional_or_keyword"),
1982 ('c', ..., ..., "keyword_only"),
1983 ('d', ..., ..., "keyword_only")),
1984 ...))
1985
1986 self.assertEqual(self.signature(partial(test, 1)),
1987 ((('b', ..., ..., "positional_or_keyword"),
1988 ('c', ..., ..., "keyword_only"),
1989 ('d', ..., ..., "keyword_only")),
1990 ...))
1991
1992 self.assertEqual(self.signature(partial(test, 1, c=2)),
1993 ((('b', ..., ..., "positional_or_keyword"),
1994 ('c', 2, ..., "keyword_only"),
1995 ('d', ..., ..., "keyword_only")),
1996 ...))
1997
1998 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1999 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002000 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002001 ('c', 2, ..., "keyword_only"),
2002 ('d', ..., ..., "keyword_only")),
2003 ...))
2004
2005 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002006 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002007 ('c', 2, ..., "keyword_only"),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002008 ('d', ..., ..., "keyword_only")),
2009 ...))
2010
2011 self.assertEqual(self.signature(partial(test, a=1)),
2012 ((('a', 1, ..., "keyword_only"),
2013 ('b', ..., ..., "keyword_only"),
2014 ('c', ..., ..., "keyword_only"),
2015 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002016 ...))
2017
2018 def test(a, *args, b, **kwargs):
2019 pass
2020
2021 self.assertEqual(self.signature(partial(test, 1)),
2022 ((('args', ..., ..., "var_positional"),
2023 ('b', ..., ..., "keyword_only"),
2024 ('kwargs', ..., ..., "var_keyword")),
2025 ...))
2026
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002027 self.assertEqual(self.signature(partial(test, a=1)),
2028 ((('a', 1, ..., "keyword_only"),
2029 ('b', ..., ..., "keyword_only"),
2030 ('kwargs', ..., ..., "var_keyword")),
2031 ...))
2032
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002033 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2034 ((('args', ..., ..., "var_positional"),
2035 ('b', ..., ..., "keyword_only"),
2036 ('kwargs', ..., ..., "var_keyword")),
2037 ...))
2038
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002039 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2040 ((('args', ..., ..., "var_positional"),
2041 ('b', ..., ..., "keyword_only"),
2042 ('kwargs', ..., ..., "var_keyword")),
2043 ...))
2044
2045 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2046 ((('args', ..., ..., "var_positional"),
2047 ('b', 0, ..., "keyword_only"),
2048 ('kwargs', ..., ..., "var_keyword")),
2049 ...))
2050
2051 self.assertEqual(self.signature(partial(test, b=0)),
2052 ((('a', ..., ..., "positional_or_keyword"),
2053 ('args', ..., ..., "var_positional"),
2054 ('b', 0, ..., "keyword_only"),
2055 ('kwargs', ..., ..., "var_keyword")),
2056 ...))
2057
2058 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2059 ((('a', ..., ..., "positional_or_keyword"),
2060 ('args', ..., ..., "var_positional"),
2061 ('b', 0, ..., "keyword_only"),
2062 ('kwargs', ..., ..., "var_keyword")),
2063 ...))
2064
2065 def test(a, b, c:int) -> 42:
2066 pass
2067
2068 sig = test.__signature__ = inspect.signature(test)
2069
2070 self.assertEqual(self.signature(partial(partial(test, 1))),
2071 ((('b', ..., ..., "positional_or_keyword"),
2072 ('c', ..., int, "positional_or_keyword")),
2073 42))
2074
2075 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2076 ((('c', ..., int, "positional_or_keyword"),),
2077 42))
2078
2079 psig = inspect.signature(partial(partial(test, 1), 2))
2080
2081 def foo(a):
2082 return a
2083 _foo = partial(partial(foo, a=10), a=20)
2084 self.assertEqual(self.signature(_foo),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002085 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002086 ...))
2087 # check that we don't have any side-effects in signature(),
2088 # and the partial object is still functioning
2089 self.assertEqual(_foo(), 20)
2090
2091 def foo(a, b, c):
2092 return a, b, c
2093 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002094
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002095 self.assertEqual(self.signature(_foo),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002096 ((('b', 30, ..., "keyword_only"),
2097 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002098 ...))
2099 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002100
2101 def foo(a, b, c, *, d):
2102 return a, b, c, d
2103 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2104 self.assertEqual(self.signature(_foo),
2105 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002106 ('b', 10, ..., "keyword_only"),
2107 ('c', 20, ..., "keyword_only"),
2108 ('d', 30, ..., "keyword_only"),
2109 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002110 ...))
2111 ba = inspect.signature(_foo).bind(a=200, b=11)
2112 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2113
2114 def foo(a=1, b=2, c=3):
2115 return a, b, c
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002116 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2117
2118 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002119 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002120
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002121 ba = inspect.signature(_foo).bind(11, 12)
2122 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002123
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002124 ba = inspect.signature(_foo).bind(11, b=12)
2125 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002126
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002127 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002128 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2129
2130 _foo = partial(_foo, b=10, c=20)
2131 ba = inspect.signature(_foo).bind(12)
2132 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2133
2134
2135 def foo(a, b, c, d, **kwargs):
2136 pass
2137 sig = inspect.signature(foo)
2138 params = sig.parameters.copy()
2139 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2140 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2141 foo.__signature__ = inspect.Signature(params.values())
2142 sig = inspect.signature(foo)
2143 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2144
2145 self.assertEqual(self.signature(partial(foo, 1)),
2146 ((('b', ..., ..., 'positional_only'),
2147 ('c', ..., ..., 'positional_or_keyword'),
2148 ('d', ..., ..., 'positional_or_keyword'),
2149 ('kwargs', ..., ..., 'var_keyword')),
2150 ...))
2151
2152 self.assertEqual(self.signature(partial(foo, 1, 2)),
2153 ((('c', ..., ..., 'positional_or_keyword'),
2154 ('d', ..., ..., 'positional_or_keyword'),
2155 ('kwargs', ..., ..., 'var_keyword')),
2156 ...))
2157
2158 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2159 ((('d', ..., ..., 'positional_or_keyword'),
2160 ('kwargs', ..., ..., 'var_keyword')),
2161 ...))
2162
2163 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2164 ((('c', 3, ..., 'keyword_only'),
2165 ('d', ..., ..., 'keyword_only'),
2166 ('kwargs', ..., ..., 'var_keyword')),
2167 ...))
2168
2169 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2170 ((('b', ..., ..., 'positional_only'),
2171 ('c', 3, ..., 'keyword_only'),
2172 ('d', ..., ..., 'keyword_only'),
2173 ('kwargs', ..., ..., 'var_keyword')),
2174 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002175
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002176 def test_signature_on_partialmethod(self):
2177 from functools import partialmethod
2178
2179 class Spam:
2180 def test():
2181 pass
2182 ham = partialmethod(test)
2183
2184 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2185 inspect.signature(Spam.ham)
2186
2187 class Spam:
2188 def test(it, a, *, c) -> 'spam':
2189 pass
2190 ham = partialmethod(test, c=1)
2191
2192 self.assertEqual(self.signature(Spam.ham),
2193 ((('it', ..., ..., 'positional_or_keyword'),
2194 ('a', ..., ..., 'positional_or_keyword'),
2195 ('c', 1, ..., 'keyword_only')),
2196 'spam'))
2197
2198 self.assertEqual(self.signature(Spam().ham),
2199 ((('a', ..., ..., 'positional_or_keyword'),
2200 ('c', 1, ..., 'keyword_only')),
2201 'spam'))
2202
Yury Selivanov0486f812014-01-29 12:18:59 -05002203 def test_signature_on_fake_partialmethod(self):
2204 def foo(a): pass
2205 foo._partialmethod = 'spam'
2206 self.assertEqual(str(inspect.signature(foo)), '(a)')
2207
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002208 def test_signature_on_decorated(self):
2209 import functools
2210
2211 def decorator(func):
2212 @functools.wraps(func)
2213 def wrapper(*args, **kwargs) -> int:
2214 return func(*args, **kwargs)
2215 return wrapper
2216
2217 class Foo:
2218 @decorator
2219 def bar(self, a, b):
2220 pass
2221
2222 self.assertEqual(self.signature(Foo.bar),
2223 ((('self', ..., ..., "positional_or_keyword"),
2224 ('a', ..., ..., "positional_or_keyword"),
2225 ('b', ..., ..., "positional_or_keyword")),
2226 ...))
2227
2228 self.assertEqual(self.signature(Foo().bar),
2229 ((('a', ..., ..., "positional_or_keyword"),
2230 ('b', ..., ..., "positional_or_keyword")),
2231 ...))
2232
2233 # Test that we handle method wrappers correctly
2234 def decorator(func):
2235 @functools.wraps(func)
2236 def wrapper(*args, **kwargs) -> int:
2237 return func(42, *args, **kwargs)
2238 sig = inspect.signature(func)
2239 new_params = tuple(sig.parameters.values())[1:]
2240 wrapper.__signature__ = sig.replace(parameters=new_params)
2241 return wrapper
2242
2243 class Foo:
2244 @decorator
2245 def __call__(self, a, b):
2246 pass
2247
2248 self.assertEqual(self.signature(Foo.__call__),
2249 ((('a', ..., ..., "positional_or_keyword"),
2250 ('b', ..., ..., "positional_or_keyword")),
2251 ...))
2252
2253 self.assertEqual(self.signature(Foo().__call__),
2254 ((('b', ..., ..., "positional_or_keyword"),),
2255 ...))
2256
Nick Coghlane8c45d62013-07-28 20:00:01 +10002257 # Test we handle __signature__ partway down the wrapper stack
2258 def wrapped_foo_call():
2259 pass
2260 wrapped_foo_call.__wrapped__ = Foo.__call__
2261
2262 self.assertEqual(self.signature(wrapped_foo_call),
2263 ((('a', ..., ..., "positional_or_keyword"),
2264 ('b', ..., ..., "positional_or_keyword")),
2265 ...))
2266
2267
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002268 def test_signature_on_class(self):
2269 class C:
2270 def __init__(self, a):
2271 pass
2272
2273 self.assertEqual(self.signature(C),
2274 ((('a', ..., ..., "positional_or_keyword"),),
2275 ...))
2276
2277 class CM(type):
2278 def __call__(cls, a):
2279 pass
2280 class C(metaclass=CM):
2281 def __init__(self, b):
2282 pass
2283
2284 self.assertEqual(self.signature(C),
2285 ((('a', ..., ..., "positional_or_keyword"),),
2286 ...))
2287
2288 class CM(type):
2289 def __new__(mcls, name, bases, dct, *, foo=1):
2290 return super().__new__(mcls, name, bases, dct)
2291 class C(metaclass=CM):
2292 def __init__(self, b):
2293 pass
2294
2295 self.assertEqual(self.signature(C),
2296 ((('b', ..., ..., "positional_or_keyword"),),
2297 ...))
2298
2299 self.assertEqual(self.signature(CM),
2300 ((('name', ..., ..., "positional_or_keyword"),
2301 ('bases', ..., ..., "positional_or_keyword"),
2302 ('dct', ..., ..., "positional_or_keyword"),
2303 ('foo', 1, ..., "keyword_only")),
2304 ...))
2305
2306 class CMM(type):
2307 def __new__(mcls, name, bases, dct, *, foo=1):
2308 return super().__new__(mcls, name, bases, dct)
2309 def __call__(cls, nm, bs, dt):
2310 return type(nm, bs, dt)
2311 class CM(type, metaclass=CMM):
2312 def __new__(mcls, name, bases, dct, *, bar=2):
2313 return super().__new__(mcls, name, bases, dct)
2314 class C(metaclass=CM):
2315 def __init__(self, b):
2316 pass
2317
2318 self.assertEqual(self.signature(CMM),
2319 ((('name', ..., ..., "positional_or_keyword"),
2320 ('bases', ..., ..., "positional_or_keyword"),
2321 ('dct', ..., ..., "positional_or_keyword"),
2322 ('foo', 1, ..., "keyword_only")),
2323 ...))
2324
2325 self.assertEqual(self.signature(CM),
2326 ((('nm', ..., ..., "positional_or_keyword"),
2327 ('bs', ..., ..., "positional_or_keyword"),
2328 ('dt', ..., ..., "positional_or_keyword")),
2329 ...))
2330
2331 self.assertEqual(self.signature(C),
2332 ((('b', ..., ..., "positional_or_keyword"),),
2333 ...))
2334
2335 class CM(type):
2336 def __init__(cls, name, bases, dct, *, bar=2):
2337 return super().__init__(name, bases, dct)
2338 class C(metaclass=CM):
2339 def __init__(self, b):
2340 pass
2341
2342 self.assertEqual(self.signature(CM),
2343 ((('name', ..., ..., "positional_or_keyword"),
2344 ('bases', ..., ..., "positional_or_keyword"),
2345 ('dct', ..., ..., "positional_or_keyword"),
2346 ('bar', 2, ..., "keyword_only")),
2347 ...))
2348
Yury Selivanov145dff82014-02-01 13:49:29 -05002349 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2350 "Signature information for builtins requires docstrings")
2351 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002352 # Test classes without user-defined __init__ or __new__
2353 class C: pass
2354 self.assertEqual(str(inspect.signature(C)), '()')
2355 class D(C): pass
2356 self.assertEqual(str(inspect.signature(D)), '()')
2357
2358 # Test meta-classes without user-defined __init__ or __new__
2359 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002360 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002361 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2362 self.assertEqual(inspect.signature(C), None)
2363 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2364 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002365
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002366 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2367 "Signature information for builtins requires docstrings")
2368 def test_signature_on_builtin_class(self):
2369 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2370 '(file, protocol=None, fix_imports=True)')
2371
2372 class P(_pickle.Pickler): pass
2373 class EmptyTrait: pass
2374 class P2(EmptyTrait, P): pass
2375 self.assertEqual(str(inspect.signature(P)),
2376 '(file, protocol=None, fix_imports=True)')
2377 self.assertEqual(str(inspect.signature(P2)),
2378 '(file, protocol=None, fix_imports=True)')
2379
2380 class P3(P2):
2381 def __init__(self, spam):
2382 pass
2383 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2384
2385 class MetaP(type):
2386 def __call__(cls, foo, bar):
2387 pass
2388 class P4(P2, metaclass=MetaP):
2389 pass
2390 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2391
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002392 def test_signature_on_callable_objects(self):
2393 class Foo:
2394 def __call__(self, a):
2395 pass
2396
2397 self.assertEqual(self.signature(Foo()),
2398 ((('a', ..., ..., "positional_or_keyword"),),
2399 ...))
2400
2401 class Spam:
2402 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002403 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002404 inspect.signature(Spam())
2405
2406 class Bar(Spam, Foo):
2407 pass
2408
2409 self.assertEqual(self.signature(Bar()),
2410 ((('a', ..., ..., "positional_or_keyword"),),
2411 ...))
2412
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002413 class Wrapped:
2414 pass
2415 Wrapped.__wrapped__ = lambda a: None
2416 self.assertEqual(self.signature(Wrapped),
2417 ((('a', ..., ..., "positional_or_keyword"),),
2418 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002419 # wrapper loop:
2420 Wrapped.__wrapped__ = Wrapped
2421 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2422 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002423
2424 def test_signature_on_lambdas(self):
2425 self.assertEqual(self.signature((lambda a=10: a)),
2426 ((('a', 10, ..., "positional_or_keyword"),),
2427 ...))
2428
2429 def test_signature_equality(self):
2430 def foo(a, *, b:int) -> float: pass
2431 self.assertNotEqual(inspect.signature(foo), 42)
2432
2433 def bar(a, *, b:int) -> float: pass
2434 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2435
2436 def bar(a, *, b:int) -> int: pass
2437 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2438
2439 def bar(a, *, b:int): pass
2440 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2441
2442 def bar(a, *, b:int=42) -> float: pass
2443 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2444
2445 def bar(a, *, c) -> float: pass
2446 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2447
2448 def bar(a, b:int) -> float: pass
2449 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2450 def spam(b:int, a) -> float: pass
2451 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2452
2453 def foo(*, a, b, c): pass
2454 def bar(*, c, b, a): pass
2455 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2456
2457 def foo(*, a=1, b, c): pass
2458 def bar(*, c, b, a=1): pass
2459 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2460
2461 def foo(pos, *, a=1, b, c): pass
2462 def bar(pos, *, c, b, a=1): pass
2463 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2464
2465 def foo(pos, *, a, b, c): pass
2466 def bar(pos, *, c, b, a=1): pass
2467 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2468
2469 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2470 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2471 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2472
2473 def test_signature_unhashable(self):
2474 def foo(a): pass
2475 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002476 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002477 hash(sig)
2478
2479 def test_signature_str(self):
2480 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2481 pass
2482 self.assertEqual(str(inspect.signature(foo)),
2483 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2484
2485 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2486 pass
2487 self.assertEqual(str(inspect.signature(foo)),
2488 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2489
2490 def foo():
2491 pass
2492 self.assertEqual(str(inspect.signature(foo)), '()')
2493
2494 def test_signature_str_positional_only(self):
2495 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002496 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002497
2498 def test(a_po, *, b, **kwargs):
2499 return a_po, kwargs
2500
2501 sig = inspect.signature(test)
2502 new_params = list(sig.parameters.values())
2503 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2504 test.__signature__ = sig.replace(parameters=new_params)
2505
2506 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002507 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002508
Yury Selivanov2393dca2014-01-27 15:07:58 -05002509 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2510 '(foo, /)')
2511
2512 self.assertEqual(str(S(parameters=[
2513 P('foo', P.POSITIONAL_ONLY),
2514 P('bar', P.VAR_KEYWORD)])),
2515 '(foo, /, **bar)')
2516
2517 self.assertEqual(str(S(parameters=[
2518 P('foo', P.POSITIONAL_ONLY),
2519 P('bar', P.VAR_POSITIONAL)])),
2520 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002521
2522 def test_signature_replace_anno(self):
2523 def test() -> 42:
2524 pass
2525
2526 sig = inspect.signature(test)
2527 sig = sig.replace(return_annotation=None)
2528 self.assertIs(sig.return_annotation, None)
2529 sig = sig.replace(return_annotation=sig.empty)
2530 self.assertIs(sig.return_annotation, sig.empty)
2531 sig = sig.replace(return_annotation=42)
2532 self.assertEqual(sig.return_annotation, 42)
2533 self.assertEqual(sig, inspect.signature(test))
2534
Yury Selivanov026019f2014-02-18 12:49:41 -05002535 def test_signature_on_mangled_parameters(self):
2536 class Spam:
2537 def foo(self, __p1:1=2, *, __p2:2=3):
2538 pass
2539 class Ham(Spam):
2540 pass
2541
2542 self.assertEqual(self.signature(Spam.foo),
2543 ((('self', ..., ..., "positional_or_keyword"),
2544 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2545 ('_Spam__p2', 3, 2, "keyword_only")),
2546 ...))
2547
2548 self.assertEqual(self.signature(Spam.foo),
2549 self.signature(Ham.foo))
2550
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002551
2552class TestParameterObject(unittest.TestCase):
2553 def test_signature_parameter_kinds(self):
2554 P = inspect.Parameter
2555 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2556 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2557
2558 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2559 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2560
2561 def test_signature_parameter_object(self):
2562 p = inspect.Parameter('foo', default=10,
2563 kind=inspect.Parameter.POSITIONAL_ONLY)
2564 self.assertEqual(p.name, 'foo')
2565 self.assertEqual(p.default, 10)
2566 self.assertIs(p.annotation, p.empty)
2567 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2568
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002569 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002570 inspect.Parameter('foo', default=10, kind='123')
2571
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002572 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002573 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2574
Yury Selivanov2393dca2014-01-27 15:07:58 -05002575 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002576 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2577
Yury Selivanov2393dca2014-01-27 15:07:58 -05002578 with self.assertRaisesRegex(ValueError,
2579 'is not a valid parameter name'):
2580 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2581
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002582 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002583 inspect.Parameter('a', default=42,
2584 kind=inspect.Parameter.VAR_KEYWORD)
2585
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002586 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002587 inspect.Parameter('a', default=42,
2588 kind=inspect.Parameter.VAR_POSITIONAL)
2589
2590 p = inspect.Parameter('a', default=42,
2591 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002592 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002593 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2594
2595 self.assertTrue(repr(p).startswith('<Parameter'))
2596
2597 def test_signature_parameter_equality(self):
2598 P = inspect.Parameter
2599 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2600
2601 self.assertEqual(p, p)
2602 self.assertNotEqual(p, 42)
2603
2604 self.assertEqual(p, P('foo', default=42,
2605 kind=inspect.Parameter.KEYWORD_ONLY))
2606
2607 def test_signature_parameter_unhashable(self):
2608 p = inspect.Parameter('foo', default=42,
2609 kind=inspect.Parameter.KEYWORD_ONLY)
2610
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002611 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002612 hash(p)
2613
2614 def test_signature_parameter_replace(self):
2615 p = inspect.Parameter('foo', default=42,
2616 kind=inspect.Parameter.KEYWORD_ONLY)
2617
2618 self.assertIsNot(p, p.replace())
2619 self.assertEqual(p, p.replace())
2620
2621 p2 = p.replace(annotation=1)
2622 self.assertEqual(p2.annotation, 1)
2623 p2 = p2.replace(annotation=p2.empty)
2624 self.assertEqual(p, p2)
2625
2626 p2 = p2.replace(name='bar')
2627 self.assertEqual(p2.name, 'bar')
2628 self.assertNotEqual(p2, p)
2629
Yury Selivanov2393dca2014-01-27 15:07:58 -05002630 with self.assertRaisesRegex(ValueError,
2631 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002632 p2 = p2.replace(name=p2.empty)
2633
2634 p2 = p2.replace(name='foo', default=None)
2635 self.assertIs(p2.default, None)
2636 self.assertNotEqual(p2, p)
2637
2638 p2 = p2.replace(name='foo', default=p2.empty)
2639 self.assertIs(p2.default, p2.empty)
2640
2641
2642 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2643 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2644 self.assertNotEqual(p2, p)
2645
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002646 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002647 p2 = p2.replace(kind=p2.empty)
2648
2649 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2650 self.assertEqual(p2, p)
2651
2652 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002653 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2654 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002655
2656 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002657 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002658
2659 with self.assertRaises(AttributeError):
2660 p.foo = 'bar'
2661
2662 with self.assertRaises(AttributeError):
2663 p.kind = 123
2664
2665
2666class TestSignatureBind(unittest.TestCase):
2667 @staticmethod
2668 def call(func, *args, **kwargs):
2669 sig = inspect.signature(func)
2670 ba = sig.bind(*args, **kwargs)
2671 return func(*ba.args, **ba.kwargs)
2672
2673 def test_signature_bind_empty(self):
2674 def test():
2675 return 42
2676
2677 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002678 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002679 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002680 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002681 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002682 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002683 self.call(test, spam=1)
2684
2685 def test_signature_bind_var(self):
2686 def test(*args, **kwargs):
2687 return args, kwargs
2688
2689 self.assertEqual(self.call(test), ((), {}))
2690 self.assertEqual(self.call(test, 1), ((1,), {}))
2691 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2692 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2693 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2694 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2695 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2696 ((1, 2), {'foo': 'bar'}))
2697
2698 def test_signature_bind_just_args(self):
2699 def test(a, b, c):
2700 return a, b, c
2701
2702 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2703
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002704 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002705 self.call(test, 1, 2, 3, 4)
2706
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002707 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002708 self.call(test, 1)
2709
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002710 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002711 self.call(test)
2712
2713 def test(a, b, c=10):
2714 return a, b, c
2715 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2716 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2717
2718 def test(a=1, b=2, c=3):
2719 return a, b, c
2720 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2721 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2722 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2723
2724 def test_signature_bind_varargs_order(self):
2725 def test(*args):
2726 return args
2727
2728 self.assertEqual(self.call(test), ())
2729 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2730
2731 def test_signature_bind_args_and_varargs(self):
2732 def test(a, b, c=3, *args):
2733 return a, b, c, args
2734
2735 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2736 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2737 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2738 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2739
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002740 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002741 "multiple values for argument 'c'"):
2742 self.call(test, 1, 2, 3, c=4)
2743
2744 def test_signature_bind_just_kwargs(self):
2745 def test(**kwargs):
2746 return kwargs
2747
2748 self.assertEqual(self.call(test), {})
2749 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2750 {'foo': 'bar', 'spam': 'ham'})
2751
2752 def test_signature_bind_args_and_kwargs(self):
2753 def test(a, b, c=3, **kwargs):
2754 return a, b, c, kwargs
2755
2756 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2757 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2758 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2759 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2760 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2761 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2762 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2763 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2764 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2765 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2766 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2767 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2768 (1, 2, 4, {'foo': 'bar'}))
2769 self.assertEqual(self.call(test, c=5, a=4, b=3),
2770 (4, 3, 5, {}))
2771
2772 def test_signature_bind_kwonly(self):
2773 def test(*, foo):
2774 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002775 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002776 'too many positional arguments'):
2777 self.call(test, 1)
2778 self.assertEqual(self.call(test, foo=1), 1)
2779
2780 def test(a, *, foo=1, bar):
2781 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002782 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002783 "'bar' parameter lacking default value"):
2784 self.call(test, 1)
2785
2786 def test(foo, *, bar):
2787 return foo, bar
2788 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2789 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2790
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002791 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002792 'too many keyword arguments'):
2793 self.call(test, bar=2, foo=1, spam=10)
2794
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002795 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002796 'too many positional arguments'):
2797 self.call(test, 1, 2)
2798
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002799 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002800 'too many positional arguments'):
2801 self.call(test, 1, 2, bar=2)
2802
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002803 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002804 'too many keyword arguments'):
2805 self.call(test, 1, bar=2, spam='ham')
2806
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002807 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002808 "'bar' parameter lacking default value"):
2809 self.call(test, 1)
2810
2811 def test(foo, *, bar, **bin):
2812 return foo, bar, bin
2813 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2814 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2815 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2816 (1, 2, {'spam': 'ham'}))
2817 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2818 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002819 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002820 "'foo' parameter lacking default value"):
2821 self.call(test, spam='ham', bar=2)
2822 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2823 (1, 2, {'bin': 1, 'spam': 10}))
2824
2825 def test_signature_bind_arguments(self):
2826 def test(a, *args, b, z=100, **kwargs):
2827 pass
2828 sig = inspect.signature(test)
2829 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2830 # we won't have 'z' argument in the bound arguments object, as we didn't
2831 # pass it to the 'bind'
2832 self.assertEqual(tuple(ba.arguments.items()),
2833 (('a', 10), ('args', (20,)), ('b', 30),
2834 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2835 self.assertEqual(ba.kwargs,
2836 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2837 self.assertEqual(ba.args, (10, 20))
2838
2839 def test_signature_bind_positional_only(self):
2840 P = inspect.Parameter
2841
2842 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2843 return a_po, b_po, c_po, foo, bar, kwargs
2844
2845 sig = inspect.signature(test)
2846 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2847 for name in ('a_po', 'b_po', 'c_po'):
2848 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2849 new_sig = sig.replace(parameters=new_params.values())
2850 test.__signature__ = new_sig
2851
2852 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2853 (1, 2, 4, 5, 6, {}))
2854
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002855 self.assertEqual(self.call(test, 1, 2),
2856 (1, 2, 3, 42, 50, {}))
2857
2858 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
2859 (1, 2, 3, 4, 5, {}))
2860
2861 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
2862 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
2863
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002864 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002865 self.call(test, 1, 2, c_po=4)
2866
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002867 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002868 self.call(test, a_po=1, b_po=2)
2869
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002870 def test_signature_bind_with_self_arg(self):
2871 # Issue #17071: one of the parameters is named "self
2872 def test(a, self, b):
2873 pass
2874 sig = inspect.signature(test)
2875 ba = sig.bind(1, 2, 3)
2876 self.assertEqual(ba.args, (1, 2, 3))
2877 ba = sig.bind(1, self=2, b=3)
2878 self.assertEqual(ba.args, (1, 2, 3))
2879
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002880 def test_signature_bind_vararg_name(self):
2881 def test(a, *args):
2882 return a, args
2883 sig = inspect.signature(test)
2884
2885 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
2886 sig.bind(a=0, args=1)
2887
2888 def test(*args, **kwargs):
2889 return args, kwargs
2890 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
2891
2892 sig = inspect.signature(test)
2893 ba = sig.bind(args=1)
2894 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
2895
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002896
2897class TestBoundArguments(unittest.TestCase):
2898 def test_signature_bound_arguments_unhashable(self):
2899 def foo(a): pass
2900 ba = inspect.signature(foo).bind(1)
2901
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002902 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002903 hash(ba)
2904
2905 def test_signature_bound_arguments_equality(self):
2906 def foo(a): pass
2907 ba = inspect.signature(foo).bind(1)
2908 self.assertEqual(ba, ba)
2909
2910 ba2 = inspect.signature(foo).bind(1)
2911 self.assertEqual(ba, ba2)
2912
2913 ba3 = inspect.signature(foo).bind(2)
2914 self.assertNotEqual(ba, ba3)
2915 ba3.arguments['a'] = 1
2916 self.assertEqual(ba, ba3)
2917
2918 def bar(b): pass
2919 ba4 = inspect.signature(bar).bind(1)
2920 self.assertNotEqual(ba, ba4)
2921
2922
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002923class TestSignaturePrivateHelpers(unittest.TestCase):
2924 def test_signature_get_bound_param(self):
2925 getter = inspect._signature_get_bound_param
2926
2927 self.assertEqual(getter('($self)'), 'self')
2928 self.assertEqual(getter('($self, obj)'), 'self')
2929 self.assertEqual(getter('($cls, /, obj)'), 'cls')
2930
Larry Hastings2623c8c2014-02-08 22:15:29 -08002931 def _strip_non_python_syntax(self, input,
2932 clean_signature, self_parameter, last_positional_only):
2933 computed_clean_signature, \
2934 computed_self_parameter, \
2935 computed_last_positional_only = \
2936 inspect._signature_strip_non_python_syntax(input)
2937 self.assertEqual(computed_clean_signature, clean_signature)
2938 self.assertEqual(computed_self_parameter, self_parameter)
2939 self.assertEqual(computed_last_positional_only, last_positional_only)
2940
2941 def test_signature_strip_non_python_syntax(self):
2942 self._strip_non_python_syntax(
2943 "($module, /, path, mode, *, dir_fd=None, " +
2944 "effective_ids=False,\n follow_symlinks=True)",
2945 "(module, path, mode, *, dir_fd=None, " +
2946 "effective_ids=False, follow_symlinks=True)",
2947 0,
2948 0)
2949
2950 self._strip_non_python_syntax(
2951 "($module, word, salt, /)",
2952 "(module, word, salt)",
2953 0,
2954 2)
2955
2956 self._strip_non_python_syntax(
2957 "(x, y=None, z=None, /)",
2958 "(x, y=None, z=None)",
2959 None,
2960 2)
2961
2962 self._strip_non_python_syntax(
2963 "(x, y=None, z=None)",
2964 "(x, y=None, z=None)",
2965 None,
2966 None)
2967
2968 self._strip_non_python_syntax(
2969 "(x,\n y=None,\n z = None )",
2970 "(x, y=None, z=None)",
2971 None,
2972 None)
2973
2974 self._strip_non_python_syntax(
2975 "",
2976 "",
2977 None,
2978 None)
2979
2980 self._strip_non_python_syntax(
2981 None,
2982 None,
2983 None,
2984 None)
2985
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002986
Nick Coghlane8c45d62013-07-28 20:00:01 +10002987class TestUnwrap(unittest.TestCase):
2988
2989 def test_unwrap_one(self):
2990 def func(a, b):
2991 return a + b
2992 wrapper = functools.lru_cache(maxsize=20)(func)
2993 self.assertIs(inspect.unwrap(wrapper), func)
2994
2995 def test_unwrap_several(self):
2996 def func(a, b):
2997 return a + b
2998 wrapper = func
2999 for __ in range(10):
3000 @functools.wraps(wrapper)
3001 def wrapper():
3002 pass
3003 self.assertIsNot(wrapper.__wrapped__, func)
3004 self.assertIs(inspect.unwrap(wrapper), func)
3005
3006 def test_stop(self):
3007 def func1(a, b):
3008 return a + b
3009 @functools.wraps(func1)
3010 def func2():
3011 pass
3012 @functools.wraps(func2)
3013 def wrapper():
3014 pass
3015 func2.stop_here = 1
3016 unwrapped = inspect.unwrap(wrapper,
3017 stop=(lambda f: hasattr(f, "stop_here")))
3018 self.assertIs(unwrapped, func2)
3019
3020 def test_cycle(self):
3021 def func1(): pass
3022 func1.__wrapped__ = func1
3023 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3024 inspect.unwrap(func1)
3025
3026 def func2(): pass
3027 func2.__wrapped__ = func1
3028 func1.__wrapped__ = func2
3029 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3030 inspect.unwrap(func1)
3031 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3032 inspect.unwrap(func2)
3033
3034 def test_unhashable(self):
3035 def func(): pass
3036 func.__wrapped__ = None
3037 class C:
3038 __hash__ = None
3039 __wrapped__ = func
3040 self.assertIsNone(inspect.unwrap(C()))
3041
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003042class TestMain(unittest.TestCase):
3043 def test_only_source(self):
3044 module = importlib.import_module('unittest')
3045 rc, out, err = assert_python_ok('-m', 'inspect',
3046 'unittest')
3047 lines = out.decode().splitlines()
3048 # ignore the final newline
3049 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3050 self.assertEqual(err, b'')
3051
Yury Selivanovc0f964f2014-06-23 10:21:04 -07003052 def test_custom_getattr(self):
3053 def foo():
3054 pass
3055 foo.__signature__ = 42
3056 with self.assertRaises(TypeError):
3057 inspect.signature(foo)
3058
Brett Cannon634a8fc2013-10-02 10:25:42 -04003059 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003060 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003061 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003062 rc, out, err = assert_python_ok('-m', 'inspect',
3063 'concurrent.futures:ThreadPoolExecutor')
3064 lines = out.decode().splitlines()
3065 # ignore the final newline
3066 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003067 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003068 self.assertEqual(err, b'')
3069
3070 def test_builtins(self):
3071 module = importlib.import_module('unittest')
3072 _, out, err = assert_python_failure('-m', 'inspect',
3073 'sys')
3074 lines = err.decode().splitlines()
3075 self.assertEqual(lines, ["Can't get info for builtin modules."])
3076
3077 def test_details(self):
3078 module = importlib.import_module('unittest')
3079 rc, out, err = assert_python_ok('-m', 'inspect',
3080 'unittest', '--details')
3081 output = out.decode()
3082 # Just a quick sanity check on the output
3083 self.assertIn(module.__name__, output)
3084 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003085 if not sys.flags.optimize:
3086 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003087 self.assertEqual(err, b'')
3088
3089
3090
Nick Coghlane8c45d62013-07-28 20:00:01 +10003091
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003092def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003093 run_unittest(
3094 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3095 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3096 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003097 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003098 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003099 TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars,
3100 TestUnwrap, TestMain
Michael Foord95fc51d2010-11-20 15:07:30 +00003101 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003102
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003103if __name__ == "__main__":
3104 test_main()