blob: 1ede3b5097adae86346f23ce1dab0c6e46060549 [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 Murrayb5655772009-05-14 16:17:50 +0000435 @unittest.skipIf(
436 not hasattr(unicodedata, '__file__') or
437 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
438 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000439 def test_findsource_binary(self):
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200440 self.assertRaises(OSError, inspect.getsource, unicodedata)
441 self.assertRaises(OSError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000442
R. David Murraya1b37402010-06-17 02:04:29 +0000443 def test_findsource_code_in_linecache(self):
444 lines = ["x=1"]
445 co = compile(lines[0], "_dynamically_created_file", "exec")
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200446 self.assertRaises(OSError, inspect.findsource, co)
447 self.assertRaises(OSError, inspect.getsource, co)
R. David Murraya1b37402010-06-17 02:04:29 +0000448 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200449 try:
450 self.assertEqual(inspect.findsource(co), (lines,0))
451 self.assertEqual(inspect.getsource(co), lines[0])
452 finally:
453 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000454
Ezio Melotti1b145922013-03-30 05:17:24 +0200455 def test_findsource_without_filename(self):
456 for fname in ['', '<string>']:
457 co = compile('x=1', fname, "exec")
458 self.assertRaises(IOError, inspect.findsource, co)
459 self.assertRaises(IOError, inspect.getsource, co)
460
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000461class TestNoEOL(GetSourceBase):
462 def __init__(self, *args, **kwargs):
463 self.tempdir = TESTFN + '_dir'
464 os.mkdir(self.tempdir)
465 with open(os.path.join(self.tempdir,
466 'inspect_fodder3%spy' % os.extsep), 'w') as f:
467 f.write("class X:\n pass # No EOL")
468 with DirsOnSysPath(self.tempdir):
469 import inspect_fodder3 as mod3
470 self.fodderModule = mod3
471 GetSourceBase.__init__(self, *args, **kwargs)
472
473 def tearDown(self):
474 shutil.rmtree(self.tempdir)
475
476 def test_class(self):
477 self.assertSourceEqual(self.fodderModule.X, 1, 2)
478
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100479
480class _BrokenDataDescriptor(object):
481 """
482 A broken data descriptor. See bug #1785.
483 """
484 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700485 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100486
487 def __set__(*args):
488 raise RuntimeError
489
490 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700491 raise AttributeError("broken data descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100492
493
494class _BrokenMethodDescriptor(object):
495 """
496 A broken method descriptor. See bug #1785.
497 """
498 def __get__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700499 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100500
501 def __getattr__(*args):
Ethan Furman63c141c2013-10-18 00:27:39 -0700502 raise AttributeError("broken method descriptor")
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100503
504
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000505# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000506def attrs_wo_objs(cls):
507 return [t[:3] for t in inspect.classify_class_attrs(cls)]
508
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100509
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000510class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000511 def test_newstyle_mro(self):
512 # The same w/ new-class MRO.
513 class A(object): pass
514 class B(A): pass
515 class C(A): pass
516 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000517
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000518 expected = (D, B, C, A, object)
519 got = inspect.getmro(D)
520 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000521
Christian Heimes3795b532007-11-08 13:48:53 +0000522 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
523 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000524 args, varargs, varkw, defaults = inspect.getargspec(routine)
525 self.assertEqual(args, args_e)
526 self.assertEqual(varargs, varargs_e)
527 self.assertEqual(varkw, varkw_e)
528 self.assertEqual(defaults, defaults_e)
529 if formatted is not None:
530 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
531 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000532
Christian Heimes3795b532007-11-08 13:48:53 +0000533 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
534 varkw_e=None, defaults_e=None,
535 kwonlyargs_e=[], kwonlydefaults_e=None,
536 ann_e={}, formatted=None):
537 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
538 inspect.getfullargspec(routine)
539 self.assertEqual(args, args_e)
540 self.assertEqual(varargs, varargs_e)
541 self.assertEqual(varkw, varkw_e)
542 self.assertEqual(defaults, defaults_e)
543 self.assertEqual(kwonlyargs, kwonlyargs_e)
544 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
545 self.assertEqual(ann, ann_e)
546 if formatted is not None:
547 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
548 kwonlyargs, kwonlydefaults, ann),
549 formatted)
550
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000551 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000552 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000553
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000554 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000555 ['a', 'b', 'c', 'd', 'e', 'f'],
556 'g', 'h', (3, 4, 5),
557 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000558
Christian Heimes3795b532007-11-08 13:48:53 +0000559 self.assertRaises(ValueError, self.assertArgSpecEquals,
560 mod2.keyworded, [])
561
562 self.assertRaises(ValueError, self.assertArgSpecEquals,
563 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000564 self.assertRaises(ValueError, self.assertArgSpecEquals,
565 mod2.keyword_only_arg, [])
566
Christian Heimes3795b532007-11-08 13:48:53 +0000567
568 def test_getfullargspec(self):
569 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
570 kwonlyargs_e=['arg2'],
571 kwonlydefaults_e={'arg2':1},
572 formatted='(*arg1, arg2=1)')
573
574 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000575 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000576 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000577 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
578 kwonlyargs_e=['arg'],
579 formatted='(*, arg)')
580
Yury Selivanovff385b82014-02-19 16:27:23 -0500581 def test_argspec_api_ignores_wrapped(self):
582 # Issue 20684: low level introspection API must ignore __wrapped__
583 @functools.wraps(mod.spam)
584 def ham(x, y):
585 pass
586 # Basic check
587 self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
588 self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)')
589 self.assertFullArgSpecEquals(functools.partial(ham),
590 ['x', 'y'], formatted='(x, y)')
591 # Other variants
592 def check_method(f):
593 self.assertArgSpecEquals(f, ['self', 'x', 'y'],
594 formatted='(self, x, y)')
595 class C:
596 @functools.wraps(mod.spam)
597 def ham(self, x, y):
598 pass
599 pham = functools.partialmethod(ham)
600 @functools.wraps(mod.spam)
601 def __call__(self, x, y):
602 pass
603 check_method(C())
604 check_method(C.ham)
605 check_method(C().ham)
606 check_method(C.pham)
607 check_method(C().pham)
608
609 class C_new:
610 @functools.wraps(mod.spam)
611 def __new__(self, x, y):
612 pass
613 check_method(C_new)
614
615 class C_init:
616 @functools.wraps(mod.spam)
617 def __init__(self, x, y):
618 pass
619 check_method(C_init)
620
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500621 def test_getfullargspec_signature_attr(self):
622 def test():
623 pass
624 spam_param = inspect.Parameter('spam', inspect.Parameter.POSITIONAL_ONLY)
625 test.__signature__ = inspect.Signature(parameters=(spam_param,))
626
627 self.assertFullArgSpecEquals(test, args_e=['spam'], formatted='(spam)')
628
Yury Selivanov4cb93912014-01-29 11:54:12 -0500629 def test_getfullargspec_signature_annos(self):
630 def test(a:'spam') -> 'ham': pass
631 spec = inspect.getfullargspec(test)
632 self.assertEqual(test.__annotations__, spec.annotations)
633
634 def test(): pass
635 spec = inspect.getfullargspec(test)
636 self.assertEqual(test.__annotations__, spec.annotations)
637
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500638 @unittest.skipIf(MISSING_C_DOCSTRINGS,
639 "Signature information for builtins requires docstrings")
640 def test_getfullargspec_builtin_methods(self):
641 self.assertFullArgSpecEquals(_pickle.Pickler.dump,
642 args_e=['self', 'obj'], formatted='(self, obj)')
643
644 self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump,
645 args_e=['self', 'obj'], formatted='(self, obj)')
646
Yury Selivanovd224b6a2014-02-21 01:32:42 -0500647 self.assertFullArgSpecEquals(
648 os.stat,
649 args_e=['path'],
650 kwonlyargs_e=['dir_fd', 'follow_symlinks'],
651 kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True},
652 formatted='(path, *, dir_fd=None, follow_symlinks=True)')
653
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200654 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500655 @unittest.skipIf(MISSING_C_DOCSTRINGS,
656 "Signature information for builtins requires docstrings")
657 def test_getfullagrspec_builtin_func(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200658 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500659 builtin = _testcapi.docstring_with_signature_with_defaults
660 spec = inspect.getfullargspec(builtin)
661 self.assertEqual(spec.defaults[0], 'avocado')
662
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200663 @cpython_only
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500664 @unittest.skipIf(MISSING_C_DOCSTRINGS,
665 "Signature information for builtins requires docstrings")
666 def test_getfullagrspec_builtin_func_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +0200667 import _testcapi
Yury Selivanovd82eddc2014-01-29 11:24:39 -0500668 builtin = _testcapi.docstring_no_signature
669 with self.assertRaises(TypeError):
670 inspect.getfullargspec(builtin)
Christian Heimes3795b532007-11-08 13:48:53 +0000671
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000672 def test_getargspec_method(self):
673 class A(object):
674 def m(self):
675 pass
676 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000677
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000678 def test_classify_newstyle(self):
679 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000680
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000681 def s(): pass
682 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000683
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000684 def c(cls): pass
685 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000686
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000687 def getp(self): pass
688 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000689
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000690 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000691
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000692 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000693
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000694 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000695
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100696 dd = _BrokenDataDescriptor()
697 md = _BrokenMethodDescriptor()
698
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000699 attrs = attrs_wo_objs(A)
Yury Selivanov0860a0b2014-01-31 14:28:44 -0500700
701 self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
702 self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
703
Benjamin Peterson577473f2010-01-19 00:09:57 +0000704 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
705 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
706 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000707 self.assertIn(('m', 'method', A), attrs,
708 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000709 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
710 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100711 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
712 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000713
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000714 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000715
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000716 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000717
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000718 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000719 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
720 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
721 self.assertIn(('p', 'property', A), attrs, 'missing property')
722 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
723 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
724 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100725 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
726 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000727
728
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000729 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000730
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000731 def m(self): pass
732 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000733
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000734 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000735 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
736 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
737 self.assertIn(('p', 'property', A), attrs, 'missing property')
738 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
739 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
740 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100741 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
742 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000743
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000744 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000745
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000746 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000747
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000748 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000749 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
750 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
751 self.assertIn(('p', 'property', A), attrs, 'missing property')
752 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
753 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
754 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100755 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
756 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
757
758 def test_classify_builtin_types(self):
759 # Simple sanity check that all built-in types can have their
760 # attributes classified.
761 for name in dir(__builtins__):
762 builtin = getattr(__builtins__, name)
763 if isinstance(builtin, type):
764 inspect.classify_class_attrs(builtin)
765
Ethan Furman63c141c2013-10-18 00:27:39 -0700766 def test_classify_DynamicClassAttribute(self):
767 class Meta(type):
768 def __getattr__(self, name):
769 if name == 'ham':
770 return 'spam'
771 return super().__getattr__(name)
772 class VA(metaclass=Meta):
Ethan Furmane03ea372013-09-25 07:14:41 -0700773 @types.DynamicClassAttribute
774 def ham(self):
775 return 'eggs'
Ethan Furman63c141c2013-10-18 00:27:39 -0700776 should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham'])
777 self.assertIn(should_find_dca, inspect.classify_class_attrs(VA))
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700778 should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam')
Ethan Furman63c141c2013-10-18 00:27:39 -0700779 self.assertIn(should_find_ga, inspect.classify_class_attrs(VA))
780
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700781 def test_classify_metaclass_class_attribute(self):
782 class Meta(type):
783 fish = 'slap'
784 def __dir__(self):
785 return ['__class__', '__modules__', '__name__', 'fish']
786 class Class(metaclass=Meta):
787 pass
788 should_find = inspect.Attribute('fish', 'data', Meta, 'slap')
789 self.assertIn(should_find, inspect.classify_class_attrs(Class))
790
Ethan Furman63c141c2013-10-18 00:27:39 -0700791 def test_classify_VirtualAttribute(self):
792 class Meta(type):
793 def __dir__(cls):
794 return ['__class__', '__module__', '__name__', 'BOOM']
795 def __getattr__(self, name):
796 if name =='BOOM':
797 return 42
798 return super().__getattr(name)
799 class Class(metaclass=Meta):
800 pass
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700801 should_find = inspect.Attribute('BOOM', 'data', Meta, 42)
Ethan Furman63c141c2013-10-18 00:27:39 -0700802 self.assertIn(should_find, inspect.classify_class_attrs(Class))
803
804 def test_classify_VirtualAttribute_multi_classes(self):
805 class Meta1(type):
806 def __dir__(cls):
807 return ['__class__', '__module__', '__name__', 'one']
808 def __getattr__(self, name):
809 if name =='one':
810 return 1
811 return super().__getattr__(name)
812 class Meta2(type):
813 def __dir__(cls):
814 return ['__class__', '__module__', '__name__', 'two']
815 def __getattr__(self, name):
816 if name =='two':
817 return 2
818 return super().__getattr__(name)
819 class Meta3(Meta1, Meta2):
820 def __dir__(cls):
821 return list(sorted(set(['__class__', '__module__', '__name__', 'three'] +
822 Meta1.__dir__(cls) + Meta2.__dir__(cls))))
823 def __getattr__(self, name):
824 if name =='three':
825 return 3
826 return super().__getattr__(name)
827 class Class1(metaclass=Meta1):
828 pass
829 class Class2(Class1, metaclass=Meta3):
830 pass
831
Ethan Furmanb0c84cd2013-10-20 22:37:39 -0700832 should_find1 = inspect.Attribute('one', 'data', Meta1, 1)
833 should_find2 = inspect.Attribute('two', 'data', Meta2, 2)
834 should_find3 = inspect.Attribute('three', 'data', Meta3, 3)
Ethan Furman63c141c2013-10-18 00:27:39 -0700835 cca = inspect.classify_class_attrs(Class2)
836 for sf in (should_find1, should_find2, should_find3):
837 self.assertIn(sf, cca)
838
839 def test_classify_class_attrs_with_buggy_dir(self):
840 class M(type):
841 def __dir__(cls):
842 return ['__class__', '__name__', 'missing']
843 class C(metaclass=M):
844 pass
845 attrs = [a[0] for a in inspect.classify_class_attrs(C)]
846 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700847
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100848 def test_getmembers_descriptors(self):
849 class A(object):
850 dd = _BrokenDataDescriptor()
851 md = _BrokenMethodDescriptor()
852
853 def pred_wrapper(pred):
854 # A quick'n'dirty way to discard standard attributes of new-style
855 # classes.
856 class Empty(object):
857 pass
858 def wrapped(x):
859 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
860 return False
861 return pred(x)
862 return wrapped
863
864 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
865 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
866
867 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
868 [('md', A.__dict__['md'])])
869 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
870 [('dd', A.__dict__['dd'])])
871
872 class B(A):
873 pass
874
875 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
876 [('md', A.__dict__['md'])])
877 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
878 [('dd', A.__dict__['dd'])])
879
Antoine Pitrou0c603812012-01-18 17:40:18 +0100880 def test_getmembers_method(self):
881 class B:
882 def f(self):
883 pass
884
885 self.assertIn(('f', B.f), inspect.getmembers(B))
886 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
887 b = B()
888 self.assertIn(('f', b.f), inspect.getmembers(b))
889 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
890
Ethan Furmane03ea372013-09-25 07:14:41 -0700891 def test_getmembers_VirtualAttribute(self):
Ethan Furman63c141c2013-10-18 00:27:39 -0700892 class M(type):
893 def __getattr__(cls, name):
894 if name == 'eggs':
895 return 'scrambled'
896 return super().__getattr__(name)
897 class A(metaclass=M):
Ethan Furmane03ea372013-09-25 07:14:41 -0700898 @types.DynamicClassAttribute
899 def eggs(self):
900 return 'spam'
Ethan Furman63c141c2013-10-18 00:27:39 -0700901 self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
902 self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
903
904 def test_getmembers_with_buggy_dir(self):
905 class M(type):
906 def __dir__(cls):
907 return ['__class__', '__name__', 'missing']
908 class C(metaclass=M):
909 pass
910 attrs = [a[0] for a in inspect.getmembers(C)]
911 self.assertNotIn('missing', attrs)
Ethan Furmane03ea372013-09-25 07:14:41 -0700912
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000913
Nick Coghlan2f92e542012-06-23 19:39:55 +1000914_global_ref = object()
915class TestGetClosureVars(unittest.TestCase):
916
917 def test_name_resolution(self):
918 # Basic test of the 4 different resolution mechanisms
919 def f(nonlocal_ref):
920 def g(local_ref):
921 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
922 return g
923 _arg = object()
924 nonlocal_vars = {"nonlocal_ref": _arg}
925 global_vars = {"_global_ref": _global_ref}
926 builtin_vars = {"print": print}
927 unbound_names = {"unbound_ref"}
928 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
929 builtin_vars, unbound_names)
930 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
931
932 def test_generator_closure(self):
933 def f(nonlocal_ref):
934 def g(local_ref):
935 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
936 yield
937 return g
938 _arg = object()
939 nonlocal_vars = {"nonlocal_ref": _arg}
940 global_vars = {"_global_ref": _global_ref}
941 builtin_vars = {"print": print}
942 unbound_names = {"unbound_ref"}
943 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
944 builtin_vars, unbound_names)
945 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
946
947 def test_method_closure(self):
948 class C:
949 def f(self, nonlocal_ref):
950 def g(local_ref):
951 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
952 return g
953 _arg = object()
954 nonlocal_vars = {"nonlocal_ref": _arg}
955 global_vars = {"_global_ref": _global_ref}
956 builtin_vars = {"print": print}
957 unbound_names = {"unbound_ref"}
958 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
959 builtin_vars, unbound_names)
960 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
961
962 def test_nonlocal_vars(self):
963 # More complex tests of nonlocal resolution
964 def _nonlocal_vars(f):
965 return inspect.getclosurevars(f).nonlocals
966
967 def make_adder(x):
968 def add(y):
969 return x + y
970 return add
971
972 def curry(func, arg1):
973 return lambda arg2: func(arg1, arg2)
974
975 def less_than(a, b):
976 return a < b
977
978 # The infamous Y combinator.
979 def Y(le):
980 def g(f):
981 return le(lambda x: f(f)(x))
982 Y.g_ref = g
983 return g(g)
984
985 def check_y_combinator(func):
986 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
987
988 inc = make_adder(1)
989 add_two = make_adder(2)
990 greater_than_five = curry(less_than, 5)
991
992 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
993 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
994 self.assertEqual(_nonlocal_vars(greater_than_five),
995 {'arg1': 5, 'func': less_than})
996 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
997 {'x': 3})
998 Y(check_y_combinator)
999
1000 def test_getclosurevars_empty(self):
1001 def foo(): pass
1002 _empty = inspect.ClosureVars({}, {}, {}, set())
1003 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
1004 self.assertEqual(inspect.getclosurevars(foo), _empty)
1005
1006 def test_getclosurevars_error(self):
1007 class T: pass
1008 self.assertRaises(TypeError, inspect.getclosurevars, 1)
1009 self.assertRaises(TypeError, inspect.getclosurevars, list)
1010 self.assertRaises(TypeError, inspect.getclosurevars, {})
1011
Nick Coghlan6c6e2542012-06-23 20:07:39 +10001012 def _private_globals(self):
1013 code = """def f(): print(path)"""
1014 ns = {}
1015 exec(code, ns)
1016 return ns["f"], ns
1017
1018 def test_builtins_fallback(self):
1019 f, ns = self._private_globals()
1020 ns.pop("__builtins__", None)
1021 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
1022 self.assertEqual(inspect.getclosurevars(f), expected)
1023
1024 def test_builtins_as_dict(self):
1025 f, ns = self._private_globals()
1026 ns["__builtins__"] = {"path":1}
1027 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
1028 self.assertEqual(inspect.getclosurevars(f), expected)
1029
1030 def test_builtins_as_module(self):
1031 f, ns = self._private_globals()
1032 ns["__builtins__"] = os
1033 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
1034 self.assertEqual(inspect.getclosurevars(f), expected)
1035
Nick Coghlan2f92e542012-06-23 19:39:55 +10001036
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001037class TestGetcallargsFunctions(unittest.TestCase):
1038
1039 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1040 locs = dict(locs or {}, func=func)
1041 r1 = eval('func(%s)' % call_params_string, None, locs)
1042 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
1043 locs)
1044 self.assertEqual(r1, r2)
1045
1046 def assertEqualException(self, func, call_param_string, locs=None):
1047 locs = dict(locs or {}, func=func)
1048 try:
1049 eval('func(%s)' % call_param_string, None, locs)
1050 except Exception as e:
1051 ex1 = e
1052 else:
1053 self.fail('Exception not raised')
1054 try:
1055 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
1056 locs)
1057 except Exception as e:
1058 ex2 = e
1059 else:
1060 self.fail('Exception not raised')
1061 self.assertIs(type(ex1), type(ex2))
1062 self.assertEqual(str(ex1), str(ex2))
1063 del ex1, ex2
1064
1065 def makeCallable(self, signature):
1066 """Create a function that returns its locals()"""
1067 code = "lambda %s: locals()"
1068 return eval(code % signature)
1069
1070 def test_plain(self):
1071 f = self.makeCallable('a, b=1')
1072 self.assertEqualCallArgs(f, '2')
1073 self.assertEqualCallArgs(f, '2, 3')
1074 self.assertEqualCallArgs(f, 'a=2')
1075 self.assertEqualCallArgs(f, 'b=3, a=2')
1076 self.assertEqualCallArgs(f, '2, b=3')
1077 # expand *iterable / **mapping
1078 self.assertEqualCallArgs(f, '*(2,)')
1079 self.assertEqualCallArgs(f, '*[2]')
1080 self.assertEqualCallArgs(f, '*(2, 3)')
1081 self.assertEqualCallArgs(f, '*[2, 3]')
1082 self.assertEqualCallArgs(f, '**{"a":2}')
1083 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
1084 self.assertEqualCallArgs(f, '2, **{"b":3}')
1085 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
1086 # expand UserList / UserDict
1087 self.assertEqualCallArgs(f, '*collections.UserList([2])')
1088 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
1089 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
1090 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
1091 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
1092
1093 def test_varargs(self):
1094 f = self.makeCallable('a, b=1, *c')
1095 self.assertEqualCallArgs(f, '2')
1096 self.assertEqualCallArgs(f, '2, 3')
1097 self.assertEqualCallArgs(f, '2, 3, 4')
1098 self.assertEqualCallArgs(f, '*(2,3,4)')
1099 self.assertEqualCallArgs(f, '2, *[3,4]')
1100 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
1101
1102 def test_varkw(self):
1103 f = self.makeCallable('a, b=1, **c')
1104 self.assertEqualCallArgs(f, 'a=2')
1105 self.assertEqualCallArgs(f, '2, b=3, c=4')
1106 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
1107 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
1108 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
1109 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
1110 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
1111 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
1112 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
1113
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001114 def test_varkw_only(self):
1115 # issue11256:
1116 f = self.makeCallable('**c')
1117 self.assertEqualCallArgs(f, '')
1118 self.assertEqualCallArgs(f, 'a=1')
1119 self.assertEqualCallArgs(f, 'a=1, b=2')
1120 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
1121 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
1122 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
1123
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001124 def test_keyword_only(self):
1125 f = self.makeCallable('a=3, *, c, d=2')
1126 self.assertEqualCallArgs(f, 'c=3')
1127 self.assertEqualCallArgs(f, 'c=3, a=3')
1128 self.assertEqualCallArgs(f, 'a=2, c=4')
1129 self.assertEqualCallArgs(f, '4, c=4')
1130 self.assertEqualException(f, '')
1131 self.assertEqualException(f, '3')
1132 self.assertEqualException(f, 'a=3')
1133 self.assertEqualException(f, 'd=4')
1134
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001135 f = self.makeCallable('*, c, d=2')
1136 self.assertEqualCallArgs(f, 'c=3')
1137 self.assertEqualCallArgs(f, 'c=3, d=4')
1138 self.assertEqualCallArgs(f, 'd=4, c=3')
1139
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001140 def test_multiple_features(self):
1141 f = self.makeCallable('a, b=2, *f, **g')
1142 self.assertEqualCallArgs(f, '2, 3, 7')
1143 self.assertEqualCallArgs(f, '2, 3, x=8')
1144 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1145 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
1146 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
1147 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1148 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
1149 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1150 '(4,[5,6])]), **collections.UserDict('
1151 'y=9, z=10)')
1152
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001153 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
1154 self.assertEqualCallArgs(f, '2, 3, x=8')
1155 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
1156 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
1157 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
1158 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
1159 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
1160 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
1161 '(4,[5,6])]), q=0, **collections.UserDict('
1162 'y=9, z=10)')
1163
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001164 def test_errors(self):
1165 f0 = self.makeCallable('')
1166 f1 = self.makeCallable('a, b')
1167 f2 = self.makeCallable('a, b=1')
1168 # f0 takes no arguments
1169 self.assertEqualException(f0, '1')
1170 self.assertEqualException(f0, 'x=1')
1171 self.assertEqualException(f0, '1,x=1')
1172 # f1 takes exactly 2 arguments
1173 self.assertEqualException(f1, '')
1174 self.assertEqualException(f1, '1')
1175 self.assertEqualException(f1, 'a=2')
1176 self.assertEqualException(f1, 'b=3')
1177 # f2 takes at least 1 argument
1178 self.assertEqualException(f2, '')
1179 self.assertEqualException(f2, 'b=3')
1180 for f in f1, f2:
1181 # f1/f2 takes exactly/at most 2 arguments
1182 self.assertEqualException(f, '2, 3, 4')
1183 self.assertEqualException(f, '1, 2, 3, a=1')
1184 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +01001185 # XXX: success of this one depends on dict order
1186 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001187 # f got an unexpected keyword argument
1188 self.assertEqualException(f, 'c=2')
1189 self.assertEqualException(f, '2, c=3')
1190 self.assertEqualException(f, '2, 3, c=4')
1191 self.assertEqualException(f, '2, c=4, b=3')
1192 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
1193 # f got multiple values for keyword argument
1194 self.assertEqualException(f, '1, a=2')
1195 self.assertEqualException(f, '1, **{"a":2}')
1196 self.assertEqualException(f, '1, 2, b=3')
1197 # XXX: Python inconsistency
1198 # - for functions and bound methods: unexpected keyword 'c'
1199 # - for unbound methods: multiple values for keyword 'a'
1200 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -05001201 # issue11256:
1202 f3 = self.makeCallable('**c')
1203 self.assertEqualException(f3, '1, 2')
1204 self.assertEqualException(f3, '1, 2, a=1, b=2')
1205 f4 = self.makeCallable('*, a, b=0')
1206 self.assertEqualException(f3, '1, 2')
1207 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001208
Yury Selivanovb1d060b2014-03-27 18:23:03 -04001209 # issue #20816: getcallargs() fails to iterate over non-existent
1210 # kwonlydefaults and raises a wrong TypeError
1211 def f5(*, a): pass
1212 with self.assertRaisesRegex(TypeError,
1213 'missing 1 required keyword-only'):
1214 inspect.getcallargs(f5)
1215
1216
Yury Selivanov2542b662014-03-27 18:42:52 -04001217 # issue20817:
1218 def f6(a, b, c):
1219 pass
1220 with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"):
1221 inspect.getcallargs(f6)
1222
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001223class TestGetcallargsMethods(TestGetcallargsFunctions):
1224
1225 def setUp(self):
1226 class Foo(object):
1227 pass
1228 self.cls = Foo
1229 self.inst = Foo()
1230
1231 def makeCallable(self, signature):
1232 assert 'self' not in signature
1233 mk = super(TestGetcallargsMethods, self).makeCallable
1234 self.cls.method = mk('self, ' + signature)
1235 return self.inst.method
1236
1237class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
1238
1239 def makeCallable(self, signature):
1240 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
1241 return self.cls.method
1242
1243 def assertEqualCallArgs(self, func, call_params_string, locs=None):
1244 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
1245 *self._getAssertEqualParams(func, call_params_string, locs))
1246
1247 def assertEqualException(self, func, call_params_string, locs=None):
1248 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1249 *self._getAssertEqualParams(func, call_params_string, locs))
1250
1251 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1252 assert 'inst' not in call_params_string
1253 locs = dict(locs or {}, inst=self.inst)
1254 return (func, 'inst,' + call_params_string, locs)
1255
Michael Foord95fc51d2010-11-20 15:07:30 +00001256
1257class TestGetattrStatic(unittest.TestCase):
1258
1259 def test_basic(self):
1260 class Thing(object):
1261 x = object()
1262
1263 thing = Thing()
1264 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1265 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1266 with self.assertRaises(AttributeError):
1267 inspect.getattr_static(thing, 'y')
1268
1269 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1270
1271 def test_inherited(self):
1272 class Thing(object):
1273 x = object()
1274 class OtherThing(Thing):
1275 pass
1276
1277 something = OtherThing()
1278 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1279
1280 def test_instance_attr(self):
1281 class Thing(object):
1282 x = 2
1283 def __init__(self, x):
1284 self.x = x
1285 thing = Thing(3)
1286 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1287 del thing.x
1288 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1289
1290 def test_property(self):
1291 class Thing(object):
1292 @property
1293 def x(self):
1294 raise AttributeError("I'm pretending not to exist")
1295 thing = Thing()
1296 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1297
Ezio Melotti75cbd732011-04-28 00:59:29 +03001298 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001299 class descriptor(object):
1300 def __get__(*_):
1301 raise AttributeError("I'm pretending not to exist")
1302 desc = descriptor()
1303 class Thing(object):
1304 x = desc
1305 thing = Thing()
1306 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1307
1308 def test_classAttribute(self):
1309 class Thing(object):
1310 x = object()
1311
1312 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1313
Ethan Furmane03ea372013-09-25 07:14:41 -07001314 def test_classVirtualAttribute(self):
1315 class Thing(object):
1316 @types.DynamicClassAttribute
1317 def x(self):
1318 return self._x
1319 _x = object()
1320
1321 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.__dict__['x'])
1322
Michael Foord95fc51d2010-11-20 15:07:30 +00001323 def test_inherited_classattribute(self):
1324 class Thing(object):
1325 x = object()
1326 class OtherThing(Thing):
1327 pass
1328
1329 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1330
1331 def test_slots(self):
1332 class Thing(object):
1333 y = 'bar'
1334 __slots__ = ['x']
1335 def __init__(self):
1336 self.x = 'foo'
1337 thing = Thing()
1338 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1339 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1340
1341 del thing.x
1342 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1343
1344 def test_metaclass(self):
1345 class meta(type):
1346 attr = 'foo'
1347 class Thing(object, metaclass=meta):
1348 pass
1349 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1350
1351 class sub(meta):
1352 pass
1353 class OtherThing(object, metaclass=sub):
1354 x = 3
1355 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1356
1357 class OtherOtherThing(OtherThing):
1358 pass
1359 # this test is odd, but it was added as it exposed a bug
1360 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1361
1362 def test_no_dict_no_slots(self):
1363 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1364 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1365
1366 def test_no_dict_no_slots_instance_member(self):
1367 # returns descriptor
1368 with open(__file__) as handle:
1369 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1370
1371 def test_inherited_slots(self):
1372 # returns descriptor
1373 class Thing(object):
1374 __slots__ = ['x']
1375 def __init__(self):
1376 self.x = 'foo'
1377
1378 class OtherThing(Thing):
1379 pass
1380 # it would be nice if this worked...
1381 # we get the descriptor instead of the instance attribute
1382 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1383
1384 def test_descriptor(self):
1385 class descriptor(object):
1386 def __get__(self, instance, owner):
1387 return 3
1388 class Foo(object):
1389 d = descriptor()
1390
1391 foo = Foo()
1392
1393 # for a non data descriptor we return the instance attribute
1394 foo.__dict__['d'] = 1
1395 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1396
1397 # if the descriptor is a data-desciptor we should return the
1398 # descriptor
1399 descriptor.__set__ = lambda s, i, v: None
1400 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1401
1402
1403 def test_metaclass_with_descriptor(self):
1404 class descriptor(object):
1405 def __get__(self, instance, owner):
1406 return 3
1407 class meta(type):
1408 d = descriptor()
1409 class Thing(object, metaclass=meta):
1410 pass
1411 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1412
1413
Michael Foordcc7ebb82010-11-20 16:20:16 +00001414 def test_class_as_property(self):
1415 class Base(object):
1416 foo = 3
1417
1418 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001419 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001420 @property
1421 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001422 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001423 return object
1424
Michael Foord35184ed2010-11-20 16:58:30 +00001425 instance = Something()
1426 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1427 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001428 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1429
Michael Foorde5162652010-11-20 16:40:44 +00001430 def test_mro_as_property(self):
1431 class Meta(type):
1432 @property
1433 def __mro__(self):
1434 return (object,)
1435
1436 class Base(object):
1437 foo = 3
1438
1439 class Something(Base, metaclass=Meta):
1440 pass
1441
1442 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1443 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1444
Michael Foorddcebe0f2011-03-15 19:20:44 -04001445 def test_dict_as_property(self):
1446 test = self
1447 test.called = False
1448
1449 class Foo(dict):
1450 a = 3
1451 @property
1452 def __dict__(self):
1453 test.called = True
1454 return {}
1455
1456 foo = Foo()
1457 foo.a = 4
1458 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1459 self.assertFalse(test.called)
1460
1461 def test_custom_object_dict(self):
1462 test = self
1463 test.called = False
1464
1465 class Custom(dict):
1466 def get(self, key, default=None):
1467 test.called = True
1468 super().get(key, default)
1469
1470 class Foo(object):
1471 a = 3
1472 foo = Foo()
1473 foo.__dict__ = Custom()
1474 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1475 self.assertFalse(test.called)
1476
1477 def test_metaclass_dict_as_property(self):
1478 class Meta(type):
1479 @property
1480 def __dict__(self):
1481 self.executed = True
1482
1483 class Thing(metaclass=Meta):
1484 executed = False
1485
1486 def __init__(self):
1487 self.spam = 42
1488
1489 instance = Thing()
1490 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1491 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001492
Michael Foorda51623b2011-12-18 22:01:40 +00001493 def test_module(self):
1494 sentinel = object()
1495 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1496 sentinel)
1497
Michael Foord3ba95f82011-12-22 01:13:37 +00001498 def test_metaclass_with_metaclass_with_dict_as_property(self):
1499 class MetaMeta(type):
1500 @property
1501 def __dict__(self):
1502 self.executed = True
1503 return dict(spam=42)
1504
1505 class Meta(type, metaclass=MetaMeta):
1506 executed = False
1507
1508 class Thing(metaclass=Meta):
1509 pass
1510
1511 with self.assertRaises(AttributeError):
1512 inspect.getattr_static(Thing, "spam")
1513 self.assertFalse(Thing.executed)
1514
Nick Coghlane0f04652010-11-21 03:44:04 +00001515class TestGetGeneratorState(unittest.TestCase):
1516
1517 def setUp(self):
1518 def number_generator():
1519 for number in range(5):
1520 yield number
1521 self.generator = number_generator()
1522
1523 def _generatorstate(self):
1524 return inspect.getgeneratorstate(self.generator)
1525
1526 def test_created(self):
1527 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1528
1529 def test_suspended(self):
1530 next(self.generator)
1531 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1532
1533 def test_closed_after_exhaustion(self):
1534 for i in self.generator:
1535 pass
1536 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1537
1538 def test_closed_after_immediate_exception(self):
1539 with self.assertRaises(RuntimeError):
1540 self.generator.throw(RuntimeError)
1541 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1542
1543 def test_running(self):
1544 # As mentioned on issue #10220, checking for the RUNNING state only
1545 # makes sense inside the generator itself.
1546 # The following generator checks for this by using the closure's
1547 # reference to self and the generator state checking helper method
1548 def running_check_generator():
1549 for number in range(5):
1550 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1551 yield number
1552 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1553 self.generator = running_check_generator()
1554 # Running up to the first yield
1555 next(self.generator)
1556 # Running after the first yield
1557 next(self.generator)
1558
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001559 def test_easy_debugging(self):
1560 # repr() and str() of a generator state should contain the state name
1561 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1562 for name in names:
1563 state = getattr(inspect, name)
1564 self.assertIn(name, repr(state))
1565 self.assertIn(name, str(state))
1566
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001567 def test_getgeneratorlocals(self):
1568 def each(lst, a=None):
1569 b=(1, 2, 3)
1570 for v in lst:
1571 if v == 3:
1572 c = 12
1573 yield v
1574
1575 numbers = each([1, 2, 3])
1576 self.assertEqual(inspect.getgeneratorlocals(numbers),
1577 {'a': None, 'lst': [1, 2, 3]})
1578 next(numbers)
1579 self.assertEqual(inspect.getgeneratorlocals(numbers),
1580 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1581 'b': (1, 2, 3)})
1582 next(numbers)
1583 self.assertEqual(inspect.getgeneratorlocals(numbers),
1584 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1585 'b': (1, 2, 3)})
1586 next(numbers)
1587 self.assertEqual(inspect.getgeneratorlocals(numbers),
1588 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1589 'b': (1, 2, 3), 'c': 12})
1590 try:
1591 next(numbers)
1592 except StopIteration:
1593 pass
1594 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1595
1596 def test_getgeneratorlocals_empty(self):
1597 def yield_one():
1598 yield 1
1599 one = yield_one()
1600 self.assertEqual(inspect.getgeneratorlocals(one), {})
1601 try:
1602 next(one)
1603 except StopIteration:
1604 pass
1605 self.assertEqual(inspect.getgeneratorlocals(one), {})
1606
1607 def test_getgeneratorlocals_error(self):
1608 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1609 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1610 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1611 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1612
Nick Coghlane0f04652010-11-21 03:44:04 +00001613
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001614class TestSignatureObject(unittest.TestCase):
1615 @staticmethod
1616 def signature(func):
1617 sig = inspect.signature(func)
1618 return (tuple((param.name,
1619 (... if param.default is param.empty else param.default),
1620 (... if param.annotation is param.empty
1621 else param.annotation),
1622 str(param.kind).lower())
1623 for param in sig.parameters.values()),
1624 (... if sig.return_annotation is sig.empty
1625 else sig.return_annotation))
1626
1627 def test_signature_object(self):
1628 S = inspect.Signature
1629 P = inspect.Parameter
1630
1631 self.assertEqual(str(S()), '()')
1632
Yury Selivanov07a9e452014-01-29 10:58:16 -05001633 def test(po, pk, pod=42, pkd=100, *args, ko, **kwargs):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001634 pass
1635 sig = inspect.signature(test)
1636 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
Yury Selivanov07a9e452014-01-29 10:58:16 -05001637 pod = sig.parameters['pod'].replace(kind=P.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001638 pk = sig.parameters['pk']
Yury Selivanov07a9e452014-01-29 10:58:16 -05001639 pkd = sig.parameters['pkd']
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001640 args = sig.parameters['args']
1641 ko = sig.parameters['ko']
1642 kwargs = sig.parameters['kwargs']
1643
1644 S((po, pk, args, ko, kwargs))
1645
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001646 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001647 S((pk, po, args, ko, kwargs))
1648
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001649 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001650 S((po, args, pk, ko, kwargs))
1651
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001652 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001653 S((args, po, pk, ko, kwargs))
1654
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001655 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001656 S((po, pk, args, kwargs, ko))
1657
1658 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001659 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001660 S((po, pk, args, kwargs2, ko))
1661
Yury Selivanov07a9e452014-01-29 10:58:16 -05001662 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1663 S((pod, po))
1664
1665 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1666 S((po, pkd, pk))
1667
1668 with self.assertRaisesRegex(ValueError, 'follows default argument'):
1669 S((pkd, pk))
1670
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001671 def test_signature_immutability(self):
1672 def test(a):
1673 pass
1674 sig = inspect.signature(test)
1675
1676 with self.assertRaises(AttributeError):
1677 sig.foo = 'bar'
1678
1679 with self.assertRaises(TypeError):
1680 sig.parameters['a'] = None
1681
1682 def test_signature_on_noarg(self):
1683 def test():
1684 pass
1685 self.assertEqual(self.signature(test), ((), ...))
1686
1687 def test_signature_on_wargs(self):
1688 def test(a, b:'foo') -> 123:
1689 pass
1690 self.assertEqual(self.signature(test),
1691 ((('a', ..., ..., "positional_or_keyword"),
1692 ('b', ..., 'foo', "positional_or_keyword")),
1693 123))
1694
1695 def test_signature_on_wkwonly(self):
1696 def test(*, a:float, b:str) -> int:
1697 pass
1698 self.assertEqual(self.signature(test),
1699 ((('a', ..., float, "keyword_only"),
1700 ('b', ..., str, "keyword_only")),
1701 int))
1702
1703 def test_signature_on_complex_args(self):
1704 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1705 pass
1706 self.assertEqual(self.signature(test),
1707 ((('a', ..., ..., "positional_or_keyword"),
1708 ('b', 10, 'foo', "positional_or_keyword"),
1709 ('args', ..., 'bar', "var_positional"),
1710 ('spam', ..., 'baz', "keyword_only"),
1711 ('ham', 123, ..., "keyword_only"),
1712 ('kwargs', ..., int, "var_keyword")),
1713 ...))
1714
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001715 @cpython_only
Larry Hastingsfcafe432013-11-23 17:35:48 -08001716 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1717 "Signature information for builtins requires docstrings")
1718 def test_signature_on_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001719 import _testcapi
Larry Hastings16c51912014-01-07 11:53:01 -08001720
Larry Hastings5c661892014-01-24 06:17:25 -08001721 def test_unbound_method(o):
1722 """Use this to test unbound methods (things that should have a self)"""
1723 signature = inspect.signature(o)
1724 self.assertTrue(isinstance(signature, inspect.Signature))
1725 self.assertEqual(list(signature.parameters.values())[0].name, 'self')
1726 return signature
1727
1728 def test_callable(o):
1729 """Use this to test bound methods or normal callables (things that don't expect self)"""
1730 signature = inspect.signature(o)
1731 self.assertTrue(isinstance(signature, inspect.Signature))
1732 if signature.parameters:
1733 self.assertNotEqual(list(signature.parameters.values())[0].name, 'self')
1734 return signature
1735
1736 signature = test_callable(_testcapi.docstring_with_signature_with_defaults)
Larry Hastings16c51912014-01-07 11:53:01 -08001737 def p(name): return signature.parameters[name].default
1738 self.assertEqual(p('s'), 'avocado')
Larry Hastings2a727912014-01-16 11:32:01 -08001739 self.assertEqual(p('b'), b'bytes')
Larry Hastings16c51912014-01-07 11:53:01 -08001740 self.assertEqual(p('d'), 3.14)
1741 self.assertEqual(p('i'), 35)
Larry Hastings16c51912014-01-07 11:53:01 -08001742 self.assertEqual(p('n'), None)
1743 self.assertEqual(p('t'), True)
1744 self.assertEqual(p('f'), False)
Larry Hastings2a727912014-01-16 11:32:01 -08001745 self.assertEqual(p('local'), 3)
1746 self.assertEqual(p('sys'), sys.maxsize)
1747 self.assertEqual(p('exp'), sys.maxsize - 1)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001748
Larry Hastings5c661892014-01-24 06:17:25 -08001749 test_callable(object)
1750
1751 # normal method
1752 # (PyMethodDescr_Type, "method_descriptor")
1753 test_unbound_method(_pickle.Pickler.dump)
1754 d = _pickle.Pickler(io.StringIO())
1755 test_callable(d.dump)
1756
1757 # static method
1758 test_callable(str.maketrans)
1759 test_callable('abc'.maketrans)
1760
1761 # class method
1762 test_callable(dict.fromkeys)
1763 test_callable({}.fromkeys)
1764
1765 # wrapper around slot (PyWrapperDescr_Type, "wrapper_descriptor")
1766 test_unbound_method(type.__call__)
1767 test_unbound_method(int.__add__)
1768 test_callable((3).__add__)
1769
1770 # _PyMethodWrapper_Type
1771 # support for 'method-wrapper'
1772 test_callable(min.__call__)
1773
Larry Hastings2623c8c2014-02-08 22:15:29 -08001774 # This doesn't work now.
1775 # (We don't have a valid signature for "type" in 3.4)
1776 with self.assertRaisesRegex(ValueError, "no signature found"):
1777 class ThisWorksNow:
1778 __call__ = type
1779 test_callable(ThisWorksNow())
Larry Hastings5c661892014-01-24 06:17:25 -08001780
Yury Selivanovd930d852014-03-02 12:25:27 -05001781 # Regression test for issue #20786
1782 test_unbound_method(dict.__delitem__)
1783 test_unbound_method(property.__delete__)
1784
1785
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001786 @cpython_only
Yury Selivanov76c6c592014-01-29 10:52:57 -05001787 @unittest.skipIf(MISSING_C_DOCSTRINGS,
1788 "Signature information for builtins requires docstrings")
1789 def test_signature_on_decorated_builtins(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001790 import _testcapi
Yury Selivanov76c6c592014-01-29 10:52:57 -05001791 func = _testcapi.docstring_with_signature_with_defaults
1792
1793 def decorator(func):
1794 @functools.wraps(func)
1795 def wrapper(*args, **kwargs) -> int:
1796 return func(*args, **kwargs)
1797 return wrapper
1798
1799 decorated_func = decorator(func)
1800
1801 self.assertEqual(inspect.signature(func),
1802 inspect.signature(decorated_func))
Larry Hastings5c661892014-01-24 06:17:25 -08001803
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001804 @cpython_only
Larry Hastings5c661892014-01-24 06:17:25 -08001805 def test_signature_on_builtins_no_signature(self):
Serhiy Storchakaf28ba362014-02-07 10:10:55 +02001806 import _testcapi
Larry Hastings5c661892014-01-24 06:17:25 -08001807 with self.assertRaisesRegex(ValueError, 'no signature found for builtin'):
1808 inspect.signature(_testcapi.docstring_no_signature)
1809
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001810 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001811 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001812 inspect.signature(42)
1813
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001814 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001815 inspect.Signature.from_function(42)
1816
Yury Selivanovb77511d2014-01-29 10:46:14 -05001817 def test_signature_from_builtin_errors(self):
1818 with self.assertRaisesRegex(TypeError, 'is not a Python builtin'):
1819 inspect.Signature.from_builtin(42)
1820
Yury Selivanov63da7c72014-01-31 14:48:37 -05001821 def test_signature_from_functionlike_object(self):
1822 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1823 pass
1824
1825 class funclike:
1826 # Has to be callable, and have correct
1827 # __code__, __annotations__, __defaults__, __name__,
1828 # and __kwdefaults__ attributes
1829
1830 def __init__(self, func):
1831 self.__name__ = func.__name__
1832 self.__code__ = func.__code__
1833 self.__annotations__ = func.__annotations__
1834 self.__defaults__ = func.__defaults__
1835 self.__kwdefaults__ = func.__kwdefaults__
1836 self.func = func
1837
1838 def __call__(self, *args, **kwargs):
1839 return self.func(*args, **kwargs)
1840
1841 sig_func = inspect.Signature.from_function(func)
1842
1843 sig_funclike = inspect.Signature.from_function(funclike(func))
1844 self.assertEqual(sig_funclike, sig_func)
1845
1846 sig_funclike = inspect.signature(funclike(func))
1847 self.assertEqual(sig_funclike, sig_func)
1848
1849 # If object is not a duck type of function, then
1850 # signature will try to get a signature for its '__call__'
1851 # method
1852 fl = funclike(func)
1853 del fl.__defaults__
1854 self.assertEqual(self.signature(fl),
1855 ((('args', ..., ..., "var_positional"),
1856 ('kwargs', ..., ..., "var_keyword")),
1857 ...))
1858
Yury Selivanov8dfb4572014-02-21 18:30:53 -05001859 # Test with cython-like builtins:
1860 _orig_isdesc = inspect.ismethoddescriptor
1861 def _isdesc(obj):
1862 if hasattr(obj, '_builtinmock'):
1863 return True
1864 return _orig_isdesc(obj)
1865
1866 with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc):
1867 builtin_func = funclike(func)
1868 # Make sure that our mock setup is working
1869 self.assertFalse(inspect.ismethoddescriptor(builtin_func))
1870 builtin_func._builtinmock = True
1871 self.assertTrue(inspect.ismethoddescriptor(builtin_func))
1872 self.assertEqual(inspect.signature(builtin_func), sig_func)
1873
Yury Selivanov63da7c72014-01-31 14:48:37 -05001874 def test_signature_functionlike_class(self):
1875 # We only want to duck type function-like objects,
1876 # not classes.
1877
1878 def func(a,b, *args, kwonly=True, kwonlyreq, **kwargs):
1879 pass
1880
1881 class funclike:
1882 def __init__(self, marker):
1883 pass
1884
1885 __name__ = func.__name__
1886 __code__ = func.__code__
1887 __annotations__ = func.__annotations__
1888 __defaults__ = func.__defaults__
1889 __kwdefaults__ = func.__kwdefaults__
1890
1891 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
1892 inspect.Signature.from_function(funclike)
1893
1894 self.assertEqual(str(inspect.signature(funclike)), '(marker)')
1895
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001896 def test_signature_on_method(self):
1897 class Test:
Yury Selivanov62560fb2014-01-28 12:26:24 -05001898 def __init__(*args):
1899 pass
1900 def m1(self, arg1, arg2=1) -> int:
1901 pass
1902 def m2(*args):
1903 pass
1904 def __call__(*, a):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001905 pass
1906
Yury Selivanov62560fb2014-01-28 12:26:24 -05001907 self.assertEqual(self.signature(Test().m1),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001908 ((('arg1', ..., ..., "positional_or_keyword"),
1909 ('arg2', 1, ..., "positional_or_keyword")),
1910 int))
1911
Yury Selivanov62560fb2014-01-28 12:26:24 -05001912 self.assertEqual(self.signature(Test().m2),
1913 ((('args', ..., ..., "var_positional"),),
1914 ...))
1915
1916 self.assertEqual(self.signature(Test),
1917 ((('args', ..., ..., "var_positional"),),
1918 ...))
1919
1920 with self.assertRaisesRegex(ValueError, 'invalid method signature'):
1921 self.signature(Test())
1922
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001923 def test_signature_on_classmethod(self):
1924 class Test:
1925 @classmethod
1926 def foo(cls, arg1, *, arg2=1):
1927 pass
1928
1929 meth = Test().foo
1930 self.assertEqual(self.signature(meth),
1931 ((('arg1', ..., ..., "positional_or_keyword"),
1932 ('arg2', 1, ..., "keyword_only")),
1933 ...))
1934
1935 meth = Test.foo
1936 self.assertEqual(self.signature(meth),
1937 ((('arg1', ..., ..., "positional_or_keyword"),
1938 ('arg2', 1, ..., "keyword_only")),
1939 ...))
1940
1941 def test_signature_on_staticmethod(self):
1942 class Test:
1943 @staticmethod
1944 def foo(cls, *, arg):
1945 pass
1946
1947 meth = Test().foo
1948 self.assertEqual(self.signature(meth),
1949 ((('cls', ..., ..., "positional_or_keyword"),
1950 ('arg', ..., ..., "keyword_only")),
1951 ...))
1952
1953 meth = Test.foo
1954 self.assertEqual(self.signature(meth),
1955 ((('cls', ..., ..., "positional_or_keyword"),
1956 ('arg', ..., ..., "keyword_only")),
1957 ...))
1958
1959 def test_signature_on_partial(self):
1960 from functools import partial
1961
Yury Selivanov0fceaf42014-04-08 11:28:02 -04001962 Parameter = inspect.Parameter
1963
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001964 def test():
1965 pass
1966
1967 self.assertEqual(self.signature(partial(test)), ((), ...))
1968
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001969 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001970 inspect.signature(partial(test, 1))
1971
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001972 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001973 inspect.signature(partial(test, a=1))
1974
1975 def test(a, b, *, c, d):
1976 pass
1977
1978 self.assertEqual(self.signature(partial(test)),
1979 ((('a', ..., ..., "positional_or_keyword"),
1980 ('b', ..., ..., "positional_or_keyword"),
1981 ('c', ..., ..., "keyword_only"),
1982 ('d', ..., ..., "keyword_only")),
1983 ...))
1984
1985 self.assertEqual(self.signature(partial(test, 1)),
1986 ((('b', ..., ..., "positional_or_keyword"),
1987 ('c', ..., ..., "keyword_only"),
1988 ('d', ..., ..., "keyword_only")),
1989 ...))
1990
1991 self.assertEqual(self.signature(partial(test, 1, c=2)),
1992 ((('b', ..., ..., "positional_or_keyword"),
1993 ('c', 2, ..., "keyword_only"),
1994 ('d', ..., ..., "keyword_only")),
1995 ...))
1996
1997 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1998 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04001999 ('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002000 ('c', 2, ..., "keyword_only"),
2001 ('d', ..., ..., "keyword_only")),
2002 ...))
2003
2004 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002005 ((('b', 1, ..., "keyword_only"),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002006 ('c', 2, ..., "keyword_only"),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002007 ('d', ..., ..., "keyword_only")),
2008 ...))
2009
2010 self.assertEqual(self.signature(partial(test, a=1)),
2011 ((('a', 1, ..., "keyword_only"),
2012 ('b', ..., ..., "keyword_only"),
2013 ('c', ..., ..., "keyword_only"),
2014 ('d', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002015 ...))
2016
2017 def test(a, *args, b, **kwargs):
2018 pass
2019
2020 self.assertEqual(self.signature(partial(test, 1)),
2021 ((('args', ..., ..., "var_positional"),
2022 ('b', ..., ..., "keyword_only"),
2023 ('kwargs', ..., ..., "var_keyword")),
2024 ...))
2025
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002026 self.assertEqual(self.signature(partial(test, a=1)),
2027 ((('a', 1, ..., "keyword_only"),
2028 ('b', ..., ..., "keyword_only"),
2029 ('kwargs', ..., ..., "var_keyword")),
2030 ...))
2031
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002032 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
2033 ((('args', ..., ..., "var_positional"),
2034 ('b', ..., ..., "keyword_only"),
2035 ('kwargs', ..., ..., "var_keyword")),
2036 ...))
2037
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002038 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
2039 ((('args', ..., ..., "var_positional"),
2040 ('b', ..., ..., "keyword_only"),
2041 ('kwargs', ..., ..., "var_keyword")),
2042 ...))
2043
2044 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
2045 ((('args', ..., ..., "var_positional"),
2046 ('b', 0, ..., "keyword_only"),
2047 ('kwargs', ..., ..., "var_keyword")),
2048 ...))
2049
2050 self.assertEqual(self.signature(partial(test, b=0)),
2051 ((('a', ..., ..., "positional_or_keyword"),
2052 ('args', ..., ..., "var_positional"),
2053 ('b', 0, ..., "keyword_only"),
2054 ('kwargs', ..., ..., "var_keyword")),
2055 ...))
2056
2057 self.assertEqual(self.signature(partial(test, b=0, test=1)),
2058 ((('a', ..., ..., "positional_or_keyword"),
2059 ('args', ..., ..., "var_positional"),
2060 ('b', 0, ..., "keyword_only"),
2061 ('kwargs', ..., ..., "var_keyword")),
2062 ...))
2063
2064 def test(a, b, c:int) -> 42:
2065 pass
2066
2067 sig = test.__signature__ = inspect.signature(test)
2068
2069 self.assertEqual(self.signature(partial(partial(test, 1))),
2070 ((('b', ..., ..., "positional_or_keyword"),
2071 ('c', ..., int, "positional_or_keyword")),
2072 42))
2073
2074 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
2075 ((('c', ..., int, "positional_or_keyword"),),
2076 42))
2077
2078 psig = inspect.signature(partial(partial(test, 1), 2))
2079
2080 def foo(a):
2081 return a
2082 _foo = partial(partial(foo, a=10), a=20)
2083 self.assertEqual(self.signature(_foo),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002084 ((('a', 20, ..., "keyword_only"),),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002085 ...))
2086 # check that we don't have any side-effects in signature(),
2087 # and the partial object is still functioning
2088 self.assertEqual(_foo(), 20)
2089
2090 def foo(a, b, c):
2091 return a, b, c
2092 _foo = partial(partial(foo, 1, b=20), b=30)
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002093
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002094 self.assertEqual(self.signature(_foo),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002095 ((('b', 30, ..., "keyword_only"),
2096 ('c', ..., ..., "keyword_only")),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002097 ...))
2098 self.assertEqual(_foo(c=10), (1, 30, 10))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002099
2100 def foo(a, b, c, *, d):
2101 return a, b, c, d
2102 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
2103 self.assertEqual(self.signature(_foo),
2104 ((('a', ..., ..., "positional_or_keyword"),
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002105 ('b', 10, ..., "keyword_only"),
2106 ('c', 20, ..., "keyword_only"),
2107 ('d', 30, ..., "keyword_only"),
2108 ),
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002109 ...))
2110 ba = inspect.signature(_foo).bind(a=200, b=11)
2111 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
2112
2113 def foo(a=1, b=2, c=3):
2114 return a, b, c
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002115 _foo = partial(foo, c=13) # (a=1, b=2, *, c=13)
2116
2117 ba = inspect.signature(_foo).bind(a=11)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002118 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002119
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002120 ba = inspect.signature(_foo).bind(11, 12)
2121 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002122
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002123 ba = inspect.signature(_foo).bind(11, b=12)
2124 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002125
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002126 ba = inspect.signature(_foo).bind(b=12)
Yury Selivanov0fceaf42014-04-08 11:28:02 -04002127 self.assertEqual(_foo(*ba.args, **ba.kwargs), (1, 12, 13))
2128
2129 _foo = partial(_foo, b=10, c=20)
2130 ba = inspect.signature(_foo).bind(12)
2131 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 10, 20))
2132
2133
2134 def foo(a, b, c, d, **kwargs):
2135 pass
2136 sig = inspect.signature(foo)
2137 params = sig.parameters.copy()
2138 params['a'] = params['a'].replace(kind=Parameter.POSITIONAL_ONLY)
2139 params['b'] = params['b'].replace(kind=Parameter.POSITIONAL_ONLY)
2140 foo.__signature__ = inspect.Signature(params.values())
2141 sig = inspect.signature(foo)
2142 self.assertEqual(str(sig), '(a, b, /, c, d, **kwargs)')
2143
2144 self.assertEqual(self.signature(partial(foo, 1)),
2145 ((('b', ..., ..., 'positional_only'),
2146 ('c', ..., ..., 'positional_or_keyword'),
2147 ('d', ..., ..., 'positional_or_keyword'),
2148 ('kwargs', ..., ..., 'var_keyword')),
2149 ...))
2150
2151 self.assertEqual(self.signature(partial(foo, 1, 2)),
2152 ((('c', ..., ..., 'positional_or_keyword'),
2153 ('d', ..., ..., 'positional_or_keyword'),
2154 ('kwargs', ..., ..., 'var_keyword')),
2155 ...))
2156
2157 self.assertEqual(self.signature(partial(foo, 1, 2, 3)),
2158 ((('d', ..., ..., 'positional_or_keyword'),
2159 ('kwargs', ..., ..., 'var_keyword')),
2160 ...))
2161
2162 self.assertEqual(self.signature(partial(foo, 1, 2, c=3)),
2163 ((('c', 3, ..., 'keyword_only'),
2164 ('d', ..., ..., 'keyword_only'),
2165 ('kwargs', ..., ..., 'var_keyword')),
2166 ...))
2167
2168 self.assertEqual(self.signature(partial(foo, 1, c=3)),
2169 ((('b', ..., ..., 'positional_only'),
2170 ('c', 3, ..., 'keyword_only'),
2171 ('d', ..., ..., 'keyword_only'),
2172 ('kwargs', ..., ..., 'var_keyword')),
2173 ...))
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002174
Yury Selivanovda5fe4f2014-01-27 17:28:37 -05002175 def test_signature_on_partialmethod(self):
2176 from functools import partialmethod
2177
2178 class Spam:
2179 def test():
2180 pass
2181 ham = partialmethod(test)
2182
2183 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
2184 inspect.signature(Spam.ham)
2185
2186 class Spam:
2187 def test(it, a, *, c) -> 'spam':
2188 pass
2189 ham = partialmethod(test, c=1)
2190
2191 self.assertEqual(self.signature(Spam.ham),
2192 ((('it', ..., ..., 'positional_or_keyword'),
2193 ('a', ..., ..., 'positional_or_keyword'),
2194 ('c', 1, ..., 'keyword_only')),
2195 'spam'))
2196
2197 self.assertEqual(self.signature(Spam().ham),
2198 ((('a', ..., ..., 'positional_or_keyword'),
2199 ('c', 1, ..., 'keyword_only')),
2200 'spam'))
2201
Yury Selivanov0486f812014-01-29 12:18:59 -05002202 def test_signature_on_fake_partialmethod(self):
2203 def foo(a): pass
2204 foo._partialmethod = 'spam'
2205 self.assertEqual(str(inspect.signature(foo)), '(a)')
2206
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002207 def test_signature_on_decorated(self):
2208 import functools
2209
2210 def decorator(func):
2211 @functools.wraps(func)
2212 def wrapper(*args, **kwargs) -> int:
2213 return func(*args, **kwargs)
2214 return wrapper
2215
2216 class Foo:
2217 @decorator
2218 def bar(self, a, b):
2219 pass
2220
2221 self.assertEqual(self.signature(Foo.bar),
2222 ((('self', ..., ..., "positional_or_keyword"),
2223 ('a', ..., ..., "positional_or_keyword"),
2224 ('b', ..., ..., "positional_or_keyword")),
2225 ...))
2226
2227 self.assertEqual(self.signature(Foo().bar),
2228 ((('a', ..., ..., "positional_or_keyword"),
2229 ('b', ..., ..., "positional_or_keyword")),
2230 ...))
2231
2232 # Test that we handle method wrappers correctly
2233 def decorator(func):
2234 @functools.wraps(func)
2235 def wrapper(*args, **kwargs) -> int:
2236 return func(42, *args, **kwargs)
2237 sig = inspect.signature(func)
2238 new_params = tuple(sig.parameters.values())[1:]
2239 wrapper.__signature__ = sig.replace(parameters=new_params)
2240 return wrapper
2241
2242 class Foo:
2243 @decorator
2244 def __call__(self, a, b):
2245 pass
2246
2247 self.assertEqual(self.signature(Foo.__call__),
2248 ((('a', ..., ..., "positional_or_keyword"),
2249 ('b', ..., ..., "positional_or_keyword")),
2250 ...))
2251
2252 self.assertEqual(self.signature(Foo().__call__),
2253 ((('b', ..., ..., "positional_or_keyword"),),
2254 ...))
2255
Nick Coghlane8c45d62013-07-28 20:00:01 +10002256 # Test we handle __signature__ partway down the wrapper stack
2257 def wrapped_foo_call():
2258 pass
2259 wrapped_foo_call.__wrapped__ = Foo.__call__
2260
2261 self.assertEqual(self.signature(wrapped_foo_call),
2262 ((('a', ..., ..., "positional_or_keyword"),
2263 ('b', ..., ..., "positional_or_keyword")),
2264 ...))
2265
2266
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002267 def test_signature_on_class(self):
2268 class C:
2269 def __init__(self, a):
2270 pass
2271
2272 self.assertEqual(self.signature(C),
2273 ((('a', ..., ..., "positional_or_keyword"),),
2274 ...))
2275
2276 class CM(type):
2277 def __call__(cls, a):
2278 pass
2279 class C(metaclass=CM):
2280 def __init__(self, b):
2281 pass
2282
2283 self.assertEqual(self.signature(C),
2284 ((('a', ..., ..., "positional_or_keyword"),),
2285 ...))
2286
2287 class CM(type):
2288 def __new__(mcls, name, bases, dct, *, foo=1):
2289 return super().__new__(mcls, name, bases, dct)
2290 class C(metaclass=CM):
2291 def __init__(self, b):
2292 pass
2293
2294 self.assertEqual(self.signature(C),
2295 ((('b', ..., ..., "positional_or_keyword"),),
2296 ...))
2297
2298 self.assertEqual(self.signature(CM),
2299 ((('name', ..., ..., "positional_or_keyword"),
2300 ('bases', ..., ..., "positional_or_keyword"),
2301 ('dct', ..., ..., "positional_or_keyword"),
2302 ('foo', 1, ..., "keyword_only")),
2303 ...))
2304
2305 class CMM(type):
2306 def __new__(mcls, name, bases, dct, *, foo=1):
2307 return super().__new__(mcls, name, bases, dct)
2308 def __call__(cls, nm, bs, dt):
2309 return type(nm, bs, dt)
2310 class CM(type, metaclass=CMM):
2311 def __new__(mcls, name, bases, dct, *, bar=2):
2312 return super().__new__(mcls, name, bases, dct)
2313 class C(metaclass=CM):
2314 def __init__(self, b):
2315 pass
2316
2317 self.assertEqual(self.signature(CMM),
2318 ((('name', ..., ..., "positional_or_keyword"),
2319 ('bases', ..., ..., "positional_or_keyword"),
2320 ('dct', ..., ..., "positional_or_keyword"),
2321 ('foo', 1, ..., "keyword_only")),
2322 ...))
2323
2324 self.assertEqual(self.signature(CM),
2325 ((('nm', ..., ..., "positional_or_keyword"),
2326 ('bs', ..., ..., "positional_or_keyword"),
2327 ('dt', ..., ..., "positional_or_keyword")),
2328 ...))
2329
2330 self.assertEqual(self.signature(C),
2331 ((('b', ..., ..., "positional_or_keyword"),),
2332 ...))
2333
2334 class CM(type):
2335 def __init__(cls, name, bases, dct, *, bar=2):
2336 return super().__init__(name, bases, dct)
2337 class C(metaclass=CM):
2338 def __init__(self, b):
2339 pass
2340
2341 self.assertEqual(self.signature(CM),
2342 ((('name', ..., ..., "positional_or_keyword"),
2343 ('bases', ..., ..., "positional_or_keyword"),
2344 ('dct', ..., ..., "positional_or_keyword"),
2345 ('bar', 2, ..., "keyword_only")),
2346 ...))
2347
Yury Selivanov145dff82014-02-01 13:49:29 -05002348 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2349 "Signature information for builtins requires docstrings")
2350 def test_signature_on_class_without_init(self):
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002351 # Test classes without user-defined __init__ or __new__
2352 class C: pass
2353 self.assertEqual(str(inspect.signature(C)), '()')
2354 class D(C): pass
2355 self.assertEqual(str(inspect.signature(D)), '()')
2356
2357 # Test meta-classes without user-defined __init__ or __new__
2358 class C(type): pass
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002359 class D(C): pass
Larry Hastings2623c8c2014-02-08 22:15:29 -08002360 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2361 self.assertEqual(inspect.signature(C), None)
2362 with self.assertRaisesRegex(ValueError, "callable.*is not supported"):
2363 self.assertEqual(inspect.signature(D), None)
Yury Selivanove7dcc5e2014-01-27 19:29:45 -05002364
Yury Selivanov7d2bfed2014-02-03 02:46:07 -05002365 @unittest.skipIf(MISSING_C_DOCSTRINGS,
2366 "Signature information for builtins requires docstrings")
2367 def test_signature_on_builtin_class(self):
2368 self.assertEqual(str(inspect.signature(_pickle.Pickler)),
2369 '(file, protocol=None, fix_imports=True)')
2370
2371 class P(_pickle.Pickler): pass
2372 class EmptyTrait: pass
2373 class P2(EmptyTrait, P): pass
2374 self.assertEqual(str(inspect.signature(P)),
2375 '(file, protocol=None, fix_imports=True)')
2376 self.assertEqual(str(inspect.signature(P2)),
2377 '(file, protocol=None, fix_imports=True)')
2378
2379 class P3(P2):
2380 def __init__(self, spam):
2381 pass
2382 self.assertEqual(str(inspect.signature(P3)), '(spam)')
2383
2384 class MetaP(type):
2385 def __call__(cls, foo, bar):
2386 pass
2387 class P4(P2, metaclass=MetaP):
2388 pass
2389 self.assertEqual(str(inspect.signature(P4)), '(foo, bar)')
2390
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002391 def test_signature_on_callable_objects(self):
2392 class Foo:
2393 def __call__(self, a):
2394 pass
2395
2396 self.assertEqual(self.signature(Foo()),
2397 ((('a', ..., ..., "positional_or_keyword"),),
2398 ...))
2399
2400 class Spam:
2401 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002402 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002403 inspect.signature(Spam())
2404
2405 class Bar(Spam, Foo):
2406 pass
2407
2408 self.assertEqual(self.signature(Bar()),
2409 ((('a', ..., ..., "positional_or_keyword"),),
2410 ...))
2411
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002412 class Wrapped:
2413 pass
2414 Wrapped.__wrapped__ = lambda a: None
2415 self.assertEqual(self.signature(Wrapped),
2416 ((('a', ..., ..., "positional_or_keyword"),),
2417 ...))
Nick Coghlane8c45d62013-07-28 20:00:01 +10002418 # wrapper loop:
2419 Wrapped.__wrapped__ = Wrapped
2420 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
2421 self.signature(Wrapped)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002422
2423 def test_signature_on_lambdas(self):
2424 self.assertEqual(self.signature((lambda a=10: a)),
2425 ((('a', 10, ..., "positional_or_keyword"),),
2426 ...))
2427
2428 def test_signature_equality(self):
2429 def foo(a, *, b:int) -> float: pass
2430 self.assertNotEqual(inspect.signature(foo), 42)
2431
2432 def bar(a, *, b:int) -> float: pass
2433 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2434
2435 def bar(a, *, b:int) -> int: pass
2436 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2437
2438 def bar(a, *, b:int): pass
2439 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2440
2441 def bar(a, *, b:int=42) -> float: pass
2442 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2443
2444 def bar(a, *, c) -> float: pass
2445 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2446
2447 def bar(a, b:int) -> float: pass
2448 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2449 def spam(b:int, a) -> float: pass
2450 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
2451
2452 def foo(*, a, b, c): pass
2453 def bar(*, c, b, a): pass
2454 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2455
2456 def foo(*, a=1, b, c): pass
2457 def bar(*, c, b, a=1): pass
2458 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2459
2460 def foo(pos, *, a=1, b, c): pass
2461 def bar(pos, *, c, b, a=1): pass
2462 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2463
2464 def foo(pos, *, a, b, c): pass
2465 def bar(pos, *, c, b, a=1): pass
2466 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
2467
2468 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
2469 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
2470 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
2471
2472 def test_signature_unhashable(self):
2473 def foo(a): pass
2474 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002475 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002476 hash(sig)
2477
2478 def test_signature_str(self):
2479 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
2480 pass
2481 self.assertEqual(str(inspect.signature(foo)),
2482 '(a:int=1, *, b, c=None, **kwargs) -> 42')
2483
2484 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
2485 pass
2486 self.assertEqual(str(inspect.signature(foo)),
2487 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
2488
2489 def foo():
2490 pass
2491 self.assertEqual(str(inspect.signature(foo)), '()')
2492
2493 def test_signature_str_positional_only(self):
2494 P = inspect.Parameter
Yury Selivanov2393dca2014-01-27 15:07:58 -05002495 S = inspect.Signature
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002496
2497 def test(a_po, *, b, **kwargs):
2498 return a_po, kwargs
2499
2500 sig = inspect.signature(test)
2501 new_params = list(sig.parameters.values())
2502 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
2503 test.__signature__ = sig.replace(parameters=new_params)
2504
2505 self.assertEqual(str(inspect.signature(test)),
Yury Selivanov2393dca2014-01-27 15:07:58 -05002506 '(a_po, /, *, b, **kwargs)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002507
Yury Selivanov2393dca2014-01-27 15:07:58 -05002508 self.assertEqual(str(S(parameters=[P('foo', P.POSITIONAL_ONLY)])),
2509 '(foo, /)')
2510
2511 self.assertEqual(str(S(parameters=[
2512 P('foo', P.POSITIONAL_ONLY),
2513 P('bar', P.VAR_KEYWORD)])),
2514 '(foo, /, **bar)')
2515
2516 self.assertEqual(str(S(parameters=[
2517 P('foo', P.POSITIONAL_ONLY),
2518 P('bar', P.VAR_POSITIONAL)])),
2519 '(foo, /, *bar)')
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002520
2521 def test_signature_replace_anno(self):
2522 def test() -> 42:
2523 pass
2524
2525 sig = inspect.signature(test)
2526 sig = sig.replace(return_annotation=None)
2527 self.assertIs(sig.return_annotation, None)
2528 sig = sig.replace(return_annotation=sig.empty)
2529 self.assertIs(sig.return_annotation, sig.empty)
2530 sig = sig.replace(return_annotation=42)
2531 self.assertEqual(sig.return_annotation, 42)
2532 self.assertEqual(sig, inspect.signature(test))
2533
Yury Selivanov026019f2014-02-18 12:49:41 -05002534 def test_signature_on_mangled_parameters(self):
2535 class Spam:
2536 def foo(self, __p1:1=2, *, __p2:2=3):
2537 pass
2538 class Ham(Spam):
2539 pass
2540
2541 self.assertEqual(self.signature(Spam.foo),
2542 ((('self', ..., ..., "positional_or_keyword"),
2543 ('_Spam__p1', 2, 1, "positional_or_keyword"),
2544 ('_Spam__p2', 3, 2, "keyword_only")),
2545 ...))
2546
2547 self.assertEqual(self.signature(Spam.foo),
2548 self.signature(Ham.foo))
2549
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002550
2551class TestParameterObject(unittest.TestCase):
2552 def test_signature_parameter_kinds(self):
2553 P = inspect.Parameter
2554 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
2555 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
2556
2557 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
2558 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
2559
2560 def test_signature_parameter_object(self):
2561 p = inspect.Parameter('foo', default=10,
2562 kind=inspect.Parameter.POSITIONAL_ONLY)
2563 self.assertEqual(p.name, 'foo')
2564 self.assertEqual(p.default, 10)
2565 self.assertIs(p.annotation, p.empty)
2566 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
2567
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002568 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002569 inspect.Parameter('foo', default=10, kind='123')
2570
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002571 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002572 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
2573
Yury Selivanov2393dca2014-01-27 15:07:58 -05002574 with self.assertRaisesRegex(TypeError, 'name must be a str'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002575 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
2576
Yury Selivanov2393dca2014-01-27 15:07:58 -05002577 with self.assertRaisesRegex(ValueError,
2578 'is not a valid parameter name'):
2579 inspect.Parameter('$', kind=inspect.Parameter.VAR_KEYWORD)
2580
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002581 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002582 inspect.Parameter('a', default=42,
2583 kind=inspect.Parameter.VAR_KEYWORD)
2584
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002585 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002586 inspect.Parameter('a', default=42,
2587 kind=inspect.Parameter.VAR_POSITIONAL)
2588
2589 p = inspect.Parameter('a', default=42,
2590 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002591 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002592 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
2593
2594 self.assertTrue(repr(p).startswith('<Parameter'))
2595
2596 def test_signature_parameter_equality(self):
2597 P = inspect.Parameter
2598 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
2599
2600 self.assertEqual(p, p)
2601 self.assertNotEqual(p, 42)
2602
2603 self.assertEqual(p, P('foo', default=42,
2604 kind=inspect.Parameter.KEYWORD_ONLY))
2605
2606 def test_signature_parameter_unhashable(self):
2607 p = inspect.Parameter('foo', default=42,
2608 kind=inspect.Parameter.KEYWORD_ONLY)
2609
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002610 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002611 hash(p)
2612
2613 def test_signature_parameter_replace(self):
2614 p = inspect.Parameter('foo', default=42,
2615 kind=inspect.Parameter.KEYWORD_ONLY)
2616
2617 self.assertIsNot(p, p.replace())
2618 self.assertEqual(p, p.replace())
2619
2620 p2 = p.replace(annotation=1)
2621 self.assertEqual(p2.annotation, 1)
2622 p2 = p2.replace(annotation=p2.empty)
2623 self.assertEqual(p, p2)
2624
2625 p2 = p2.replace(name='bar')
2626 self.assertEqual(p2.name, 'bar')
2627 self.assertNotEqual(p2, p)
2628
Yury Selivanov2393dca2014-01-27 15:07:58 -05002629 with self.assertRaisesRegex(ValueError,
2630 'name is a required attribute'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002631 p2 = p2.replace(name=p2.empty)
2632
2633 p2 = p2.replace(name='foo', default=None)
2634 self.assertIs(p2.default, None)
2635 self.assertNotEqual(p2, p)
2636
2637 p2 = p2.replace(name='foo', default=p2.empty)
2638 self.assertIs(p2.default, p2.empty)
2639
2640
2641 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2642 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2643 self.assertNotEqual(p2, p)
2644
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002645 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002646 p2 = p2.replace(kind=p2.empty)
2647
2648 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2649 self.assertEqual(p2, p)
2650
2651 def test_signature_parameter_positional_only(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002652 with self.assertRaisesRegex(TypeError, 'name must be a str'):
2653 inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002654
2655 def test_signature_parameter_immutability(self):
Yury Selivanov2393dca2014-01-27 15:07:58 -05002656 p = inspect.Parameter('spam', kind=inspect.Parameter.KEYWORD_ONLY)
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002657
2658 with self.assertRaises(AttributeError):
2659 p.foo = 'bar'
2660
2661 with self.assertRaises(AttributeError):
2662 p.kind = 123
2663
2664
2665class TestSignatureBind(unittest.TestCase):
2666 @staticmethod
2667 def call(func, *args, **kwargs):
2668 sig = inspect.signature(func)
2669 ba = sig.bind(*args, **kwargs)
2670 return func(*ba.args, **ba.kwargs)
2671
2672 def test_signature_bind_empty(self):
2673 def test():
2674 return 42
2675
2676 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002677 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002678 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002679 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002680 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002681 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002682 self.call(test, spam=1)
2683
2684 def test_signature_bind_var(self):
2685 def test(*args, **kwargs):
2686 return args, kwargs
2687
2688 self.assertEqual(self.call(test), ((), {}))
2689 self.assertEqual(self.call(test, 1), ((1,), {}))
2690 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2691 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2692 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2693 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2694 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2695 ((1, 2), {'foo': 'bar'}))
2696
2697 def test_signature_bind_just_args(self):
2698 def test(a, b, c):
2699 return a, b, c
2700
2701 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2702
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002703 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002704 self.call(test, 1, 2, 3, 4)
2705
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002706 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002707 self.call(test, 1)
2708
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002709 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002710 self.call(test)
2711
2712 def test(a, b, c=10):
2713 return a, b, c
2714 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2715 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2716
2717 def test(a=1, b=2, c=3):
2718 return a, b, c
2719 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2720 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2721 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2722
2723 def test_signature_bind_varargs_order(self):
2724 def test(*args):
2725 return args
2726
2727 self.assertEqual(self.call(test), ())
2728 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2729
2730 def test_signature_bind_args_and_varargs(self):
2731 def test(a, b, c=3, *args):
2732 return a, b, c, args
2733
2734 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2735 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2736 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2737 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2738
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002739 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002740 "multiple values for argument 'c'"):
2741 self.call(test, 1, 2, 3, c=4)
2742
2743 def test_signature_bind_just_kwargs(self):
2744 def test(**kwargs):
2745 return kwargs
2746
2747 self.assertEqual(self.call(test), {})
2748 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2749 {'foo': 'bar', 'spam': 'ham'})
2750
2751 def test_signature_bind_args_and_kwargs(self):
2752 def test(a, b, c=3, **kwargs):
2753 return a, b, c, kwargs
2754
2755 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2756 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2757 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2758 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2759 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2760 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2761 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2762 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2763 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2764 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2765 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2766 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2767 (1, 2, 4, {'foo': 'bar'}))
2768 self.assertEqual(self.call(test, c=5, a=4, b=3),
2769 (4, 3, 5, {}))
2770
2771 def test_signature_bind_kwonly(self):
2772 def test(*, foo):
2773 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002774 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002775 'too many positional arguments'):
2776 self.call(test, 1)
2777 self.assertEqual(self.call(test, foo=1), 1)
2778
2779 def test(a, *, foo=1, bar):
2780 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002781 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002782 "'bar' parameter lacking default value"):
2783 self.call(test, 1)
2784
2785 def test(foo, *, bar):
2786 return foo, bar
2787 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2788 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2789
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002790 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002791 'too many keyword arguments'):
2792 self.call(test, bar=2, foo=1, spam=10)
2793
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002794 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002795 'too many positional arguments'):
2796 self.call(test, 1, 2)
2797
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002798 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002799 'too many positional arguments'):
2800 self.call(test, 1, 2, bar=2)
2801
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002802 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002803 'too many keyword arguments'):
2804 self.call(test, 1, bar=2, spam='ham')
2805
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002806 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002807 "'bar' parameter lacking default value"):
2808 self.call(test, 1)
2809
2810 def test(foo, *, bar, **bin):
2811 return foo, bar, bin
2812 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2813 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2814 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2815 (1, 2, {'spam': 'ham'}))
2816 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2817 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002818 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002819 "'foo' parameter lacking default value"):
2820 self.call(test, spam='ham', bar=2)
2821 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2822 (1, 2, {'bin': 1, 'spam': 10}))
2823
2824 def test_signature_bind_arguments(self):
2825 def test(a, *args, b, z=100, **kwargs):
2826 pass
2827 sig = inspect.signature(test)
2828 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2829 # we won't have 'z' argument in the bound arguments object, as we didn't
2830 # pass it to the 'bind'
2831 self.assertEqual(tuple(ba.arguments.items()),
2832 (('a', 10), ('args', (20,)), ('b', 30),
2833 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2834 self.assertEqual(ba.kwargs,
2835 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2836 self.assertEqual(ba.args, (10, 20))
2837
2838 def test_signature_bind_positional_only(self):
2839 P = inspect.Parameter
2840
2841 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2842 return a_po, b_po, c_po, foo, bar, kwargs
2843
2844 sig = inspect.signature(test)
2845 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2846 for name in ('a_po', 'b_po', 'c_po'):
2847 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2848 new_sig = sig.replace(parameters=new_params.values())
2849 test.__signature__ = new_sig
2850
2851 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2852 (1, 2, 4, 5, 6, {}))
2853
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002854 self.assertEqual(self.call(test, 1, 2),
2855 (1, 2, 3, 42, 50, {}))
2856
2857 self.assertEqual(self.call(test, 1, 2, foo=4, bar=5),
2858 (1, 2, 3, 4, 5, {}))
2859
2860 with self.assertRaisesRegex(TypeError, "but was passed as a keyword"):
2861 self.call(test, 1, 2, foo=4, bar=5, c_po=10)
2862
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002863 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002864 self.call(test, 1, 2, c_po=4)
2865
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002866 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002867 self.call(test, a_po=1, b_po=2)
2868
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002869 def test_signature_bind_with_self_arg(self):
2870 # Issue #17071: one of the parameters is named "self
2871 def test(a, self, b):
2872 pass
2873 sig = inspect.signature(test)
2874 ba = sig.bind(1, 2, 3)
2875 self.assertEqual(ba.args, (1, 2, 3))
2876 ba = sig.bind(1, self=2, b=3)
2877 self.assertEqual(ba.args, (1, 2, 3))
2878
Yury Selivanov38b0d5a2014-01-28 17:27:39 -05002879 def test_signature_bind_vararg_name(self):
2880 def test(a, *args):
2881 return a, args
2882 sig = inspect.signature(test)
2883
2884 with self.assertRaisesRegex(TypeError, "too many keyword arguments"):
2885 sig.bind(a=0, args=1)
2886
2887 def test(*args, **kwargs):
2888 return args, kwargs
2889 self.assertEqual(self.call(test, args=1), ((), {'args': 1}))
2890
2891 sig = inspect.signature(test)
2892 ba = sig.bind(args=1)
2893 self.assertEqual(ba.arguments, {'kwargs': {'args': 1}})
2894
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002895
2896class TestBoundArguments(unittest.TestCase):
2897 def test_signature_bound_arguments_unhashable(self):
2898 def foo(a): pass
2899 ba = inspect.signature(foo).bind(1)
2900
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002901 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002902 hash(ba)
2903
2904 def test_signature_bound_arguments_equality(self):
2905 def foo(a): pass
2906 ba = inspect.signature(foo).bind(1)
2907 self.assertEqual(ba, ba)
2908
2909 ba2 = inspect.signature(foo).bind(1)
2910 self.assertEqual(ba, ba2)
2911
2912 ba3 = inspect.signature(foo).bind(2)
2913 self.assertNotEqual(ba, ba3)
2914 ba3.arguments['a'] = 1
2915 self.assertEqual(ba, ba3)
2916
2917 def bar(b): pass
2918 ba4 = inspect.signature(bar).bind(1)
2919 self.assertNotEqual(ba, ba4)
2920
2921
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002922class TestSignaturePrivateHelpers(unittest.TestCase):
2923 def test_signature_get_bound_param(self):
2924 getter = inspect._signature_get_bound_param
2925
2926 self.assertEqual(getter('($self)'), 'self')
2927 self.assertEqual(getter('($self, obj)'), 'self')
2928 self.assertEqual(getter('($cls, /, obj)'), 'cls')
2929
Larry Hastings2623c8c2014-02-08 22:15:29 -08002930 def _strip_non_python_syntax(self, input,
2931 clean_signature, self_parameter, last_positional_only):
2932 computed_clean_signature, \
2933 computed_self_parameter, \
2934 computed_last_positional_only = \
2935 inspect._signature_strip_non_python_syntax(input)
2936 self.assertEqual(computed_clean_signature, clean_signature)
2937 self.assertEqual(computed_self_parameter, self_parameter)
2938 self.assertEqual(computed_last_positional_only, last_positional_only)
2939
2940 def test_signature_strip_non_python_syntax(self):
2941 self._strip_non_python_syntax(
2942 "($module, /, path, mode, *, dir_fd=None, " +
2943 "effective_ids=False,\n follow_symlinks=True)",
2944 "(module, path, mode, *, dir_fd=None, " +
2945 "effective_ids=False, follow_symlinks=True)",
2946 0,
2947 0)
2948
2949 self._strip_non_python_syntax(
2950 "($module, word, salt, /)",
2951 "(module, word, salt)",
2952 0,
2953 2)
2954
2955 self._strip_non_python_syntax(
2956 "(x, y=None, z=None, /)",
2957 "(x, y=None, z=None)",
2958 None,
2959 2)
2960
2961 self._strip_non_python_syntax(
2962 "(x, y=None, z=None)",
2963 "(x, y=None, z=None)",
2964 None,
2965 None)
2966
2967 self._strip_non_python_syntax(
2968 "(x,\n y=None,\n z = None )",
2969 "(x, y=None, z=None)",
2970 None,
2971 None)
2972
2973 self._strip_non_python_syntax(
2974 "",
2975 "",
2976 None,
2977 None)
2978
2979 self._strip_non_python_syntax(
2980 None,
2981 None,
2982 None,
2983 None)
2984
Yury Selivanovd82eddc2014-01-29 11:24:39 -05002985
Nick Coghlane8c45d62013-07-28 20:00:01 +10002986class TestUnwrap(unittest.TestCase):
2987
2988 def test_unwrap_one(self):
2989 def func(a, b):
2990 return a + b
2991 wrapper = functools.lru_cache(maxsize=20)(func)
2992 self.assertIs(inspect.unwrap(wrapper), func)
2993
2994 def test_unwrap_several(self):
2995 def func(a, b):
2996 return a + b
2997 wrapper = func
2998 for __ in range(10):
2999 @functools.wraps(wrapper)
3000 def wrapper():
3001 pass
3002 self.assertIsNot(wrapper.__wrapped__, func)
3003 self.assertIs(inspect.unwrap(wrapper), func)
3004
3005 def test_stop(self):
3006 def func1(a, b):
3007 return a + b
3008 @functools.wraps(func1)
3009 def func2():
3010 pass
3011 @functools.wraps(func2)
3012 def wrapper():
3013 pass
3014 func2.stop_here = 1
3015 unwrapped = inspect.unwrap(wrapper,
3016 stop=(lambda f: hasattr(f, "stop_here")))
3017 self.assertIs(unwrapped, func2)
3018
3019 def test_cycle(self):
3020 def func1(): pass
3021 func1.__wrapped__ = func1
3022 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3023 inspect.unwrap(func1)
3024
3025 def func2(): pass
3026 func2.__wrapped__ = func1
3027 func1.__wrapped__ = func2
3028 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3029 inspect.unwrap(func1)
3030 with self.assertRaisesRegex(ValueError, 'wrapper loop'):
3031 inspect.unwrap(func2)
3032
3033 def test_unhashable(self):
3034 def func(): pass
3035 func.__wrapped__ = None
3036 class C:
3037 __hash__ = None
3038 __wrapped__ = func
3039 self.assertIsNone(inspect.unwrap(C()))
3040
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003041class TestMain(unittest.TestCase):
3042 def test_only_source(self):
3043 module = importlib.import_module('unittest')
3044 rc, out, err = assert_python_ok('-m', 'inspect',
3045 'unittest')
3046 lines = out.decode().splitlines()
3047 # ignore the final newline
3048 self.assertEqual(lines[:-1], inspect.getsource(module).splitlines())
3049 self.assertEqual(err, b'')
3050
Brett Cannon634a8fc2013-10-02 10:25:42 -04003051 @unittest.skipIf(ThreadPoolExecutor is None,
Brett Cannon0de3f012013-10-02 10:58:58 -04003052 'threads required to test __qualname__ for source files')
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003053 def test_qualname_source(self):
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003054 rc, out, err = assert_python_ok('-m', 'inspect',
3055 'concurrent.futures:ThreadPoolExecutor')
3056 lines = out.decode().splitlines()
3057 # ignore the final newline
3058 self.assertEqual(lines[:-1],
Brett Cannon634a8fc2013-10-02 10:25:42 -04003059 inspect.getsource(ThreadPoolExecutor).splitlines())
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003060 self.assertEqual(err, b'')
3061
3062 def test_builtins(self):
3063 module = importlib.import_module('unittest')
3064 _, out, err = assert_python_failure('-m', 'inspect',
3065 'sys')
3066 lines = err.decode().splitlines()
3067 self.assertEqual(lines, ["Can't get info for builtin modules."])
3068
3069 def test_details(self):
3070 module = importlib.import_module('unittest')
3071 rc, out, err = assert_python_ok('-m', 'inspect',
3072 'unittest', '--details')
3073 output = out.decode()
3074 # Just a quick sanity check on the output
3075 self.assertIn(module.__name__, output)
3076 self.assertIn(module.__file__, output)
Serhiy Storchakab12cb6a2013-12-08 18:16:18 +02003077 if not sys.flags.optimize:
3078 self.assertIn(module.__cached__, output)
Nick Coghlanf94a16b2013-09-22 22:46:49 +10003079 self.assertEqual(err, b'')
3080
3081
3082
Nick Coghlane8c45d62013-07-28 20:00:01 +10003083
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003084def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00003085 run_unittest(
3086 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
3087 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
3088 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00003089 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07003090 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Yury Selivanovd82eddc2014-01-29 11:24:39 -05003091 TestBoundArguments, TestSignaturePrivateHelpers, TestGetClosureVars,
3092 TestUnwrap, TestMain
Michael Foord95fc51d2010-11-20 15:07:30 +00003093 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00003094
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00003095if __name__ == "__main__":
3096 test_main()