blob: 7f70342b884ee165d0e2a06c06477177cdaac3c3 [file] [log] [blame]
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00001import re
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002import sys
Thomas Wouters0e3f5912006-08-11 14:57:12 +00003import types
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004import unittest
5import inspect
R. David Murraya1b37402010-06-17 02:04:29 +00006import linecache
Thomas Wouters0e3f5912006-08-11 14:57:12 +00007import datetime
Guido van Rossum813b0e52007-05-21 18:11:34 +00008import collections
Alexander Belopolskyf546e702010-12-02 00:10:11 +00009import os
10import shutil
Christian Heimesa3538eb2007-11-06 11:44:48 +000011from os.path import normcase
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000012
Alexander Belopolskyf546e702010-12-02 00:10:11 +000013from test.support import run_unittest, TESTFN, DirsOnSysPath
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000014
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000015from test import inspect_fodder as mod
16from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000017
R. David Murray74b89242009-05-13 17:33:03 +000018# C module for test_findsource_binary
R. David Murrayb5655772009-05-14 16:17:50 +000019import unicodedata
R. David Murray74b89242009-05-13 17:33:03 +000020
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000021# Functions tested in this suite:
22# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Christian Heimes7131fd92008-02-19 14:21:46 +000023# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
24# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
25# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
26# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000027
Nick Coghlanf088e5e2008-12-14 11:50:48 +000028# NOTE: There are some additional tests relating to interaction with
29# zipimport in the test_zipimport_support test module.
30
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000031modfile = mod.__file__
Thomas Wouters0e3f5912006-08-11 14:57:12 +000032if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000033 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000034
Christian Heimesa3538eb2007-11-06 11:44:48 +000035# Normalize file names: on Windows, the case of file names of compiled
36# modules depends on the path used to start the python executable.
37modfile = normcase(modfile)
38
39def revise(filename, *args):
40 return (normcase(filename),) + args
41
Georg Brandl1a3284e2007-12-02 09:40:06 +000042import builtins
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000043
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000044git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000045
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000046class IsTestBase(unittest.TestCase):
47 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
48 inspect.isframe, inspect.isfunction, inspect.ismethod,
Christian Heimes7131fd92008-02-19 14:21:46 +000049 inspect.ismodule, inspect.istraceback,
50 inspect.isgenerator, inspect.isgeneratorfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000051
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000052 def istest(self, predicate, exp):
53 obj = eval(exp)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000054 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000055
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000056 for other in self.predicates - set([predicate]):
Christian Heimes7131fd92008-02-19 14:21:46 +000057 if predicate == inspect.isgeneratorfunction and\
58 other == inspect.isfunction:
59 continue
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000060 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000061
Christian Heimes7131fd92008-02-19 14:21:46 +000062def generator_function_example(self):
63 for i in range(2):
64 yield i
65
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000066class TestPredicates(IsTestBase):
Christian Heimes227c8002008-03-03 20:34:40 +000067 def test_sixteen(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +000068 count = len([x for x in dir(inspect) if x.startswith('is')])
Christian Heimes7131fd92008-02-19 14:21:46 +000069 # This test is here for remember you to update Doc/library/inspect.rst
Christian Heimes78644762008-03-04 23:39:23 +000070 # which claims there are 16 such functions
Christian Heimes227c8002008-03-03 20:34:40 +000071 expected = 16
Thomas Wouters0e3f5912006-08-11 14:57:12 +000072 err_msg = "There are %d (not %d) is* functions" % (count, expected)
73 self.assertEqual(count, expected, err_msg)
Tim Peters5a9fb3c2005-01-07 16:01:32 +000074
Christian Heimes7131fd92008-02-19 14:21:46 +000075
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000076 def test_excluding_predicates(self):
Antoine Pitroud5a1a212012-06-17 23:18:07 +020077 global tb
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000078 self.istest(inspect.isbuiltin, 'sys.exit')
79 self.istest(inspect.isbuiltin, '[].append')
Neal Norwitz221085d2007-02-25 20:55:47 +000080 self.istest(inspect.iscode, 'mod.spam.__code__')
Antoine Pitroud5a1a212012-06-17 23:18:07 +020081 try:
82 1/0
83 except:
84 tb = sys.exc_info()[2]
85 self.istest(inspect.isframe, 'tb.tb_frame')
86 self.istest(inspect.istraceback, 'tb')
87 if hasattr(types, 'GetSetDescriptorType'):
88 self.istest(inspect.isgetsetdescriptor,
89 'type(tb.tb_frame).f_locals')
90 else:
91 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
92 finally:
93 # Clear traceback and all the frames and local variables hanging to it.
94 tb = None
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000095 self.istest(inspect.isfunction, 'mod.spam')
Christian Heimes4a22b5d2007-11-25 09:39:14 +000096 self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000097 self.istest(inspect.ismethod, 'git.argue')
98 self.istest(inspect.ismodule, 'mod')
Guido van Rossum813b0e52007-05-21 18:11:34 +000099 self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
Christian Heimes7131fd92008-02-19 14:21:46 +0000100 self.istest(inspect.isgenerator, '(x for x in range(2))')
101 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000102 if hasattr(types, 'MemberDescriptorType'):
103 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
104 else:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000105 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000106
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000107 def test_isroutine(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000108 self.assertTrue(inspect.isroutine(mod.spam))
109 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000110
Benjamin Petersonc4656002009-01-17 22:41:18 +0000111 def test_isclass(self):
112 self.istest(inspect.isclass, 'mod.StupidGit')
113 self.assertTrue(inspect.isclass(list))
114
115 class CustomGetattr(object):
116 def __getattr__(self, attr):
117 return None
118 self.assertFalse(inspect.isclass(CustomGetattr()))
119
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000120 def test_get_slot_members(self):
121 class C(object):
122 __slots__ = ("a", "b")
123
124 x = C()
125 x.a = 42
126 members = dict(inspect.getmembers(x))
Benjamin Peterson577473f2010-01-19 00:09:57 +0000127 self.assertIn('a', members)
128 self.assertNotIn('b', members)
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000129
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000130 def test_isabstract(self):
131 from abc import ABCMeta, abstractmethod
132
133 class AbstractClassExample(metaclass=ABCMeta):
134
135 @abstractmethod
136 def foo(self):
137 pass
138
139 class ClassExample(AbstractClassExample):
140 def foo(self):
141 pass
142
143 a = ClassExample()
144
145 # Test general behaviour.
146 self.assertTrue(inspect.isabstract(AbstractClassExample))
147 self.assertFalse(inspect.isabstract(ClassExample))
148 self.assertFalse(inspect.isabstract(a))
149 self.assertFalse(inspect.isabstract(int))
150 self.assertFalse(inspect.isabstract(5))
151
Benjamin Peterson058e31e2009-01-16 03:54:08 +0000152
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000153class TestInterpreterStack(IsTestBase):
154 def __init__(self, *args, **kwargs):
155 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000156
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000157 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000158
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000159 def test_abuse_done(self):
160 self.istest(inspect.istraceback, 'git.ex[2]')
161 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000162
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000163 def test_stack(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000164 self.assertTrue(len(mod.st) >= 5)
Christian Heimesa3538eb2007-11-06 11:44:48 +0000165 self.assertEqual(revise(*mod.st[0][1:]),
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000166 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000167 self.assertEqual(revise(*mod.st[1][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000168 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000169 self.assertEqual(revise(*mod.st[2][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000170 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
Christian Heimesa3538eb2007-11-06 11:44:48 +0000171 self.assertEqual(revise(*mod.st[3][1:]),
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000172 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000173
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000174 def test_trace(self):
175 self.assertEqual(len(git.tr), 3)
Florent Xiclunac8575922010-03-24 17:37:49 +0000176 self.assertEqual(revise(*git.tr[0][1:]),
177 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
178 self.assertEqual(revise(*git.tr[1][1:]),
179 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
180 self.assertEqual(revise(*git.tr[2][1:]),
181 (modfile, 18, 'eggs', [' q = y / 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000182
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000183 def test_frame(self):
184 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
185 self.assertEqual(args, ['x', 'y'])
186 self.assertEqual(varargs, None)
187 self.assertEqual(varkw, None)
188 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
189 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
190 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000191
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000192 def test_previous_frame(self):
193 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000194 self.assertEqual(args, ['a', 'b', 'c', 'd', 'e', 'f'])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000195 self.assertEqual(varargs, 'g')
196 self.assertEqual(varkw, 'h')
197 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000198 '(a=7, b=8, c=9, d=3, e=4, f=5, *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000199
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000200class GetSourceBase(unittest.TestCase):
201 # Subclasses must override.
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000202 fodderModule = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000203
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000204 def __init__(self, *args, **kwargs):
205 unittest.TestCase.__init__(self, *args, **kwargs)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000206
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000207 with open(inspect.getsourcefile(self.fodderModule)) as fp:
Philip Jenveya27c5bd2009-05-28 06:09:08 +0000208 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000209
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000210 def sourcerange(self, top, bottom):
211 lines = self.source.split("\n")
212 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000213
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000214 def assertSourceEqual(self, obj, top, bottom):
215 self.assertEqual(inspect.getsource(obj),
216 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000217
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000218class TestRetrievingSourceCode(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000219 fodderModule = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000220
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000221 def test_getclasses(self):
222 classes = inspect.getmembers(mod, inspect.isclass)
223 self.assertEqual(classes,
224 [('FesteringGob', mod.FesteringGob),
225 ('MalodorousPervert', mod.MalodorousPervert),
226 ('ParrotDroppings', mod.ParrotDroppings),
227 ('StupidGit', mod.StupidGit)])
228 tree = inspect.getclasstree([cls[1] for cls in classes], 1)
229 self.assertEqual(tree,
Thomas Wouters725af872006-04-15 09:13:19 +0000230 [(object, ()),
231 [(mod.ParrotDroppings, (object,)),
232 (mod.StupidGit, (object,)),
233 [(mod.MalodorousPervert, (mod.StupidGit,)),
234 [(mod.FesteringGob, (mod.MalodorousPervert,
235 mod.ParrotDroppings))
236 ]
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000237 ]
238 ]
239 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000240
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000241 def test_getfunctions(self):
242 functions = inspect.getmembers(mod, inspect.isfunction)
243 self.assertEqual(functions, [('eggs', mod.eggs),
244 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000245
R. David Murray378c0cf2010-02-24 01:46:21 +0000246 @unittest.skipIf(sys.flags.optimize >= 2,
247 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000248 def test_getdoc(self):
249 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
250 self.assertEqual(inspect.getdoc(mod.StupidGit),
251 'A longer,\n\nindented\n\ndocstring.')
252 self.assertEqual(inspect.getdoc(git.abuse),
253 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000254
Georg Brandl0c77a822008-06-10 16:37:50 +0000255 def test_cleandoc(self):
256 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
257 'An\nindented\ndocstring.')
258
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000259 def test_getcomments(self):
260 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
261 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000262
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000263 def test_getmodule(self):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000264 # Check actual module
265 self.assertEqual(inspect.getmodule(mod), mod)
266 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000267 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000268 # Check a method (no __module__ attribute, falls back to filename)
269 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
270 # Do it again (check the caching isn't broken)
271 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
272 # Check a builtin
Georg Brandl1a3284e2007-12-02 09:40:06 +0000273 self.assertEqual(inspect.getmodule(str), sys.modules["builtins"])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000274 # Check filename override
275 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000276
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000277 def test_getsource(self):
278 self.assertSourceEqual(git.abuse, 29, 39)
279 self.assertSourceEqual(mod.StupidGit, 21, 46)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000280
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000281 def test_getsourcefile(self):
Christian Heimesa3538eb2007-11-06 11:44:48 +0000282 self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile)
283 self.assertEqual(normcase(inspect.getsourcefile(git.abuse)), modfile)
R. David Murraya1b37402010-06-17 02:04:29 +0000284 fn = "_non_existing_filename_used_for_sourcefile_test.py"
285 co = compile("None", fn, "exec")
R. David Murray4155f972010-06-17 13:23:18 +0000286 self.assertEqual(inspect.getsourcefile(co), None)
R. David Murraya1b37402010-06-17 02:04:29 +0000287 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
288 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000289
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000290 def test_getfile(self):
291 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000292
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000293 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000294 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000295 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000296 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000297 m.__file__ = "<string>" # hopefully not a real filename...
298 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000299 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000300 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000301 del sys.modules[name]
302 inspect.getmodule(compile('a=10','','single'))
303
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500304 def test_proceed_with_fake_filename(self):
305 '''doctest monkeypatches linecache to enable inspection'''
306 fn, source = '<test>', 'def x(): pass\n'
307 getlines = linecache.getlines
308 def monkey(filename, module_globals=None):
309 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300310 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500311 else:
312 return getlines(filename, module_globals)
313 linecache.getlines = monkey
314 try:
315 ns = {}
316 exec(compile(source, fn, 'single'), ns)
317 inspect.getsource(ns["x"])
318 finally:
319 linecache.getlines = getlines
320
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000321class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000322 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000323
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000324 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000325 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000326
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000327 def test_replacing_decorator(self):
328 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000329
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000330class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000331 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000332 def test_oneline_lambda(self):
333 # Test inspect.getsource with a one-line lambda function.
334 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000335
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000336 def test_threeline_lambda(self):
337 # Test inspect.getsource with a three-line lambda function,
338 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000339 self.assertSourceEqual(mod2.tll, 28, 30)
340
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000341 def test_twoline_indented_lambda(self):
342 # Test inspect.getsource with a two-line lambda function,
343 # where the second line _is_ indented.
344 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000345
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000346 def test_onelinefunc(self):
347 # Test inspect.getsource with a regular one-line function.
348 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000349
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000350 def test_manyargs(self):
351 # Test inspect.getsource with a regular function where
352 # the arguments are on two lines and _not_ indented and
353 # the body on the second line with the last arguments.
354 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000355
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000356 def test_twolinefunc(self):
357 # Test inspect.getsource with a regular function where
358 # the body is on two lines, following the argument list and
359 # continued on the next line by a \\.
360 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000361
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000362 def test_lambda_in_list(self):
363 # Test inspect.getsource with a one-line lambda function
364 # defined in a list, indented.
365 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000366
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000367 def test_anonymous(self):
368 # Test inspect.getsource with a lambda function defined
369 # as argument to another function.
370 self.assertSourceEqual(mod2.anonymous, 55, 55)
371
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000372class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000373 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000374
375 def test_with_comment(self):
376 self.assertSourceEqual(mod2.with_comment, 58, 59)
377
378 def test_multiline_sig(self):
379 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
380
Armin Rigodd5c0232005-09-25 11:45:45 +0000381 def test_nested_class(self):
382 self.assertSourceEqual(mod2.func69().func71, 71, 72)
383
384 def test_one_liner_followed_by_non_name(self):
385 self.assertSourceEqual(mod2.func77, 77, 77)
386
387 def test_one_liner_dedent_non_name(self):
388 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
389
390 def test_with_comment_instead_of_docstring(self):
391 self.assertSourceEqual(mod2.func88, 88, 90)
392
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000393 def test_method_in_dynamic_class(self):
394 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
395
R. David Murrayb5655772009-05-14 16:17:50 +0000396 @unittest.skipIf(
397 not hasattr(unicodedata, '__file__') or
398 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
399 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000400 def test_findsource_binary(self):
R. David Murrayb5655772009-05-14 16:17:50 +0000401 self.assertRaises(IOError, inspect.getsource, unicodedata)
402 self.assertRaises(IOError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000403
R. David Murraya1b37402010-06-17 02:04:29 +0000404 def test_findsource_code_in_linecache(self):
405 lines = ["x=1"]
406 co = compile(lines[0], "_dynamically_created_file", "exec")
407 self.assertRaises(IOError, inspect.findsource, co)
408 self.assertRaises(IOError, inspect.getsource, co)
409 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000410 self.assertEqual(inspect.findsource(co), (lines,0))
411 self.assertEqual(inspect.getsource(co), lines[0])
R. David Murraya1b37402010-06-17 02:04:29 +0000412
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000413class TestNoEOL(GetSourceBase):
414 def __init__(self, *args, **kwargs):
415 self.tempdir = TESTFN + '_dir'
416 os.mkdir(self.tempdir)
417 with open(os.path.join(self.tempdir,
418 'inspect_fodder3%spy' % os.extsep), 'w') as f:
419 f.write("class X:\n pass # No EOL")
420 with DirsOnSysPath(self.tempdir):
421 import inspect_fodder3 as mod3
422 self.fodderModule = mod3
423 GetSourceBase.__init__(self, *args, **kwargs)
424
425 def tearDown(self):
426 shutil.rmtree(self.tempdir)
427
428 def test_class(self):
429 self.assertSourceEqual(self.fodderModule.X, 1, 2)
430
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100431
432class _BrokenDataDescriptor(object):
433 """
434 A broken data descriptor. See bug #1785.
435 """
436 def __get__(*args):
437 raise AssertionError("should not __get__ data descriptors")
438
439 def __set__(*args):
440 raise RuntimeError
441
442 def __getattr__(*args):
443 raise AssertionError("should not __getattr__ data descriptors")
444
445
446class _BrokenMethodDescriptor(object):
447 """
448 A broken method descriptor. See bug #1785.
449 """
450 def __get__(*args):
451 raise AssertionError("should not __get__ method descriptors")
452
453 def __getattr__(*args):
454 raise AssertionError("should not __getattr__ method descriptors")
455
456
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000457# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000458def attrs_wo_objs(cls):
459 return [t[:3] for t in inspect.classify_class_attrs(cls)]
460
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100461
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000462class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000463 def test_newstyle_mro(self):
464 # The same w/ new-class MRO.
465 class A(object): pass
466 class B(A): pass
467 class C(A): pass
468 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000469
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000470 expected = (D, B, C, A, object)
471 got = inspect.getmro(D)
472 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000473
Christian Heimes3795b532007-11-08 13:48:53 +0000474 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
475 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000476 args, varargs, varkw, defaults = inspect.getargspec(routine)
477 self.assertEqual(args, args_e)
478 self.assertEqual(varargs, varargs_e)
479 self.assertEqual(varkw, varkw_e)
480 self.assertEqual(defaults, defaults_e)
481 if formatted is not None:
482 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
483 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000484
Christian Heimes3795b532007-11-08 13:48:53 +0000485 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
486 varkw_e=None, defaults_e=None,
487 kwonlyargs_e=[], kwonlydefaults_e=None,
488 ann_e={}, formatted=None):
489 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
490 inspect.getfullargspec(routine)
491 self.assertEqual(args, args_e)
492 self.assertEqual(varargs, varargs_e)
493 self.assertEqual(varkw, varkw_e)
494 self.assertEqual(defaults, defaults_e)
495 self.assertEqual(kwonlyargs, kwonlyargs_e)
496 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
497 self.assertEqual(ann, ann_e)
498 if formatted is not None:
499 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
500 kwonlyargs, kwonlydefaults, ann),
501 formatted)
502
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000503 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000504 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000505
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000506 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000507 ['a', 'b', 'c', 'd', 'e', 'f'],
508 'g', 'h', (3, 4, 5),
509 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000510
Christian Heimes3795b532007-11-08 13:48:53 +0000511 self.assertRaises(ValueError, self.assertArgSpecEquals,
512 mod2.keyworded, [])
513
514 self.assertRaises(ValueError, self.assertArgSpecEquals,
515 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000516 self.assertRaises(ValueError, self.assertArgSpecEquals,
517 mod2.keyword_only_arg, [])
518
Christian Heimes3795b532007-11-08 13:48:53 +0000519
520 def test_getfullargspec(self):
521 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
522 kwonlyargs_e=['arg2'],
523 kwonlydefaults_e={'arg2':1},
524 formatted='(*arg1, arg2=1)')
525
526 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000527 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000528 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000529 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
530 kwonlyargs_e=['arg'],
531 formatted='(*, arg)')
532
Christian Heimes3795b532007-11-08 13:48:53 +0000533
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000534 def test_getargspec_method(self):
535 class A(object):
536 def m(self):
537 pass
538 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000539
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000540 def test_classify_newstyle(self):
541 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000542
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000543 def s(): pass
544 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000545
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000546 def c(cls): pass
547 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000548
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000549 def getp(self): pass
550 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000551
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000552 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000553
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000554 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000555
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000556 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000557
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100558 dd = _BrokenDataDescriptor()
559 md = _BrokenMethodDescriptor()
560
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000561 attrs = attrs_wo_objs(A)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000562 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
563 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
564 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000565 self.assertIn(('m', 'method', A), attrs,
566 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000567 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
568 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100569 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
570 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000571
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000572 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000573
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000574 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000575
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000576 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000577 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
578 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
579 self.assertIn(('p', 'property', A), attrs, 'missing property')
580 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
581 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
582 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100583 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
584 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000585
586
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000587 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000588
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000589 def m(self): pass
590 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000591
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000592 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000593 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
594 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
595 self.assertIn(('p', 'property', A), attrs, 'missing property')
596 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
597 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
598 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100599 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
600 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000601
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000602 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000603
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000604 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000605
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000606 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000607 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
608 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
609 self.assertIn(('p', 'property', A), attrs, 'missing property')
610 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
611 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
612 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100613 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
614 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
615
616 def test_classify_builtin_types(self):
617 # Simple sanity check that all built-in types can have their
618 # attributes classified.
619 for name in dir(__builtins__):
620 builtin = getattr(__builtins__, name)
621 if isinstance(builtin, type):
622 inspect.classify_class_attrs(builtin)
623
624 def test_getmembers_descriptors(self):
625 class A(object):
626 dd = _BrokenDataDescriptor()
627 md = _BrokenMethodDescriptor()
628
629 def pred_wrapper(pred):
630 # A quick'n'dirty way to discard standard attributes of new-style
631 # classes.
632 class Empty(object):
633 pass
634 def wrapped(x):
635 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
636 return False
637 return pred(x)
638 return wrapped
639
640 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
641 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
642
643 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
644 [('md', A.__dict__['md'])])
645 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
646 [('dd', A.__dict__['dd'])])
647
648 class B(A):
649 pass
650
651 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
652 [('md', A.__dict__['md'])])
653 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
654 [('dd', A.__dict__['dd'])])
655
Antoine Pitrou0c603812012-01-18 17:40:18 +0100656 def test_getmembers_method(self):
657 class B:
658 def f(self):
659 pass
660
661 self.assertIn(('f', B.f), inspect.getmembers(B))
662 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
663 b = B()
664 self.assertIn(('f', b.f), inspect.getmembers(b))
665 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
666
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000667
Nick Coghlan2f92e542012-06-23 19:39:55 +1000668_global_ref = object()
669class TestGetClosureVars(unittest.TestCase):
670
671 def test_name_resolution(self):
672 # Basic test of the 4 different resolution mechanisms
673 def f(nonlocal_ref):
674 def g(local_ref):
675 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
676 return g
677 _arg = object()
678 nonlocal_vars = {"nonlocal_ref": _arg}
679 global_vars = {"_global_ref": _global_ref}
680 builtin_vars = {"print": print}
681 unbound_names = {"unbound_ref"}
682 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
683 builtin_vars, unbound_names)
684 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
685
686 def test_generator_closure(self):
687 def f(nonlocal_ref):
688 def g(local_ref):
689 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
690 yield
691 return g
692 _arg = object()
693 nonlocal_vars = {"nonlocal_ref": _arg}
694 global_vars = {"_global_ref": _global_ref}
695 builtin_vars = {"print": print}
696 unbound_names = {"unbound_ref"}
697 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
698 builtin_vars, unbound_names)
699 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
700
701 def test_method_closure(self):
702 class C:
703 def f(self, nonlocal_ref):
704 def g(local_ref):
705 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
706 return g
707 _arg = object()
708 nonlocal_vars = {"nonlocal_ref": _arg}
709 global_vars = {"_global_ref": _global_ref}
710 builtin_vars = {"print": print}
711 unbound_names = {"unbound_ref"}
712 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
713 builtin_vars, unbound_names)
714 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
715
716 def test_nonlocal_vars(self):
717 # More complex tests of nonlocal resolution
718 def _nonlocal_vars(f):
719 return inspect.getclosurevars(f).nonlocals
720
721 def make_adder(x):
722 def add(y):
723 return x + y
724 return add
725
726 def curry(func, arg1):
727 return lambda arg2: func(arg1, arg2)
728
729 def less_than(a, b):
730 return a < b
731
732 # The infamous Y combinator.
733 def Y(le):
734 def g(f):
735 return le(lambda x: f(f)(x))
736 Y.g_ref = g
737 return g(g)
738
739 def check_y_combinator(func):
740 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
741
742 inc = make_adder(1)
743 add_two = make_adder(2)
744 greater_than_five = curry(less_than, 5)
745
746 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
747 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
748 self.assertEqual(_nonlocal_vars(greater_than_five),
749 {'arg1': 5, 'func': less_than})
750 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
751 {'x': 3})
752 Y(check_y_combinator)
753
754 def test_getclosurevars_empty(self):
755 def foo(): pass
756 _empty = inspect.ClosureVars({}, {}, {}, set())
757 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
758 self.assertEqual(inspect.getclosurevars(foo), _empty)
759
760 def test_getclosurevars_error(self):
761 class T: pass
762 self.assertRaises(TypeError, inspect.getclosurevars, 1)
763 self.assertRaises(TypeError, inspect.getclosurevars, list)
764 self.assertRaises(TypeError, inspect.getclosurevars, {})
765
766
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000767class TestGetcallargsFunctions(unittest.TestCase):
768
769 def assertEqualCallArgs(self, func, call_params_string, locs=None):
770 locs = dict(locs or {}, func=func)
771 r1 = eval('func(%s)' % call_params_string, None, locs)
772 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
773 locs)
774 self.assertEqual(r1, r2)
775
776 def assertEqualException(self, func, call_param_string, locs=None):
777 locs = dict(locs or {}, func=func)
778 try:
779 eval('func(%s)' % call_param_string, None, locs)
780 except Exception as e:
781 ex1 = e
782 else:
783 self.fail('Exception not raised')
784 try:
785 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
786 locs)
787 except Exception as e:
788 ex2 = e
789 else:
790 self.fail('Exception not raised')
791 self.assertIs(type(ex1), type(ex2))
792 self.assertEqual(str(ex1), str(ex2))
793 del ex1, ex2
794
795 def makeCallable(self, signature):
796 """Create a function that returns its locals()"""
797 code = "lambda %s: locals()"
798 return eval(code % signature)
799
800 def test_plain(self):
801 f = self.makeCallable('a, b=1')
802 self.assertEqualCallArgs(f, '2')
803 self.assertEqualCallArgs(f, '2, 3')
804 self.assertEqualCallArgs(f, 'a=2')
805 self.assertEqualCallArgs(f, 'b=3, a=2')
806 self.assertEqualCallArgs(f, '2, b=3')
807 # expand *iterable / **mapping
808 self.assertEqualCallArgs(f, '*(2,)')
809 self.assertEqualCallArgs(f, '*[2]')
810 self.assertEqualCallArgs(f, '*(2, 3)')
811 self.assertEqualCallArgs(f, '*[2, 3]')
812 self.assertEqualCallArgs(f, '**{"a":2}')
813 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
814 self.assertEqualCallArgs(f, '2, **{"b":3}')
815 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
816 # expand UserList / UserDict
817 self.assertEqualCallArgs(f, '*collections.UserList([2])')
818 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
819 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
820 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
821 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
822
823 def test_varargs(self):
824 f = self.makeCallable('a, b=1, *c')
825 self.assertEqualCallArgs(f, '2')
826 self.assertEqualCallArgs(f, '2, 3')
827 self.assertEqualCallArgs(f, '2, 3, 4')
828 self.assertEqualCallArgs(f, '*(2,3,4)')
829 self.assertEqualCallArgs(f, '2, *[3,4]')
830 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
831
832 def test_varkw(self):
833 f = self.makeCallable('a, b=1, **c')
834 self.assertEqualCallArgs(f, 'a=2')
835 self.assertEqualCallArgs(f, '2, b=3, c=4')
836 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
837 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
838 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
839 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
840 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
841 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
842 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
843
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500844 def test_varkw_only(self):
845 # issue11256:
846 f = self.makeCallable('**c')
847 self.assertEqualCallArgs(f, '')
848 self.assertEqualCallArgs(f, 'a=1')
849 self.assertEqualCallArgs(f, 'a=1, b=2')
850 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
851 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
852 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
853
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000854 def test_keyword_only(self):
855 f = self.makeCallable('a=3, *, c, d=2')
856 self.assertEqualCallArgs(f, 'c=3')
857 self.assertEqualCallArgs(f, 'c=3, a=3')
858 self.assertEqualCallArgs(f, 'a=2, c=4')
859 self.assertEqualCallArgs(f, '4, c=4')
860 self.assertEqualException(f, '')
861 self.assertEqualException(f, '3')
862 self.assertEqualException(f, 'a=3')
863 self.assertEqualException(f, 'd=4')
864
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500865 f = self.makeCallable('*, c, d=2')
866 self.assertEqualCallArgs(f, 'c=3')
867 self.assertEqualCallArgs(f, 'c=3, d=4')
868 self.assertEqualCallArgs(f, 'd=4, c=3')
869
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000870 def test_multiple_features(self):
871 f = self.makeCallable('a, b=2, *f, **g')
872 self.assertEqualCallArgs(f, '2, 3, 7')
873 self.assertEqualCallArgs(f, '2, 3, x=8')
874 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
875 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
876 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
877 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
878 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
879 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
880 '(4,[5,6])]), **collections.UserDict('
881 'y=9, z=10)')
882
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500883 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
884 self.assertEqualCallArgs(f, '2, 3, x=8')
885 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
886 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
887 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
888 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
889 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
890 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
891 '(4,[5,6])]), q=0, **collections.UserDict('
892 'y=9, z=10)')
893
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000894 def test_errors(self):
895 f0 = self.makeCallable('')
896 f1 = self.makeCallable('a, b')
897 f2 = self.makeCallable('a, b=1')
898 # f0 takes no arguments
899 self.assertEqualException(f0, '1')
900 self.assertEqualException(f0, 'x=1')
901 self.assertEqualException(f0, '1,x=1')
902 # f1 takes exactly 2 arguments
903 self.assertEqualException(f1, '')
904 self.assertEqualException(f1, '1')
905 self.assertEqualException(f1, 'a=2')
906 self.assertEqualException(f1, 'b=3')
907 # f2 takes at least 1 argument
908 self.assertEqualException(f2, '')
909 self.assertEqualException(f2, 'b=3')
910 for f in f1, f2:
911 # f1/f2 takes exactly/at most 2 arguments
912 self.assertEqualException(f, '2, 3, 4')
913 self.assertEqualException(f, '1, 2, 3, a=1')
914 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +0100915 # XXX: success of this one depends on dict order
916 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000917 # f got an unexpected keyword argument
918 self.assertEqualException(f, 'c=2')
919 self.assertEqualException(f, '2, c=3')
920 self.assertEqualException(f, '2, 3, c=4')
921 self.assertEqualException(f, '2, c=4, b=3')
922 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
923 # f got multiple values for keyword argument
924 self.assertEqualException(f, '1, a=2')
925 self.assertEqualException(f, '1, **{"a":2}')
926 self.assertEqualException(f, '1, 2, b=3')
927 # XXX: Python inconsistency
928 # - for functions and bound methods: unexpected keyword 'c'
929 # - for unbound methods: multiple values for keyword 'a'
930 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500931 # issue11256:
932 f3 = self.makeCallable('**c')
933 self.assertEqualException(f3, '1, 2')
934 self.assertEqualException(f3, '1, 2, a=1, b=2')
935 f4 = self.makeCallable('*, a, b=0')
936 self.assertEqualException(f3, '1, 2')
937 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000938
939class TestGetcallargsMethods(TestGetcallargsFunctions):
940
941 def setUp(self):
942 class Foo(object):
943 pass
944 self.cls = Foo
945 self.inst = Foo()
946
947 def makeCallable(self, signature):
948 assert 'self' not in signature
949 mk = super(TestGetcallargsMethods, self).makeCallable
950 self.cls.method = mk('self, ' + signature)
951 return self.inst.method
952
953class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
954
955 def makeCallable(self, signature):
956 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
957 return self.cls.method
958
959 def assertEqualCallArgs(self, func, call_params_string, locs=None):
960 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
961 *self._getAssertEqualParams(func, call_params_string, locs))
962
963 def assertEqualException(self, func, call_params_string, locs=None):
964 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
965 *self._getAssertEqualParams(func, call_params_string, locs))
966
967 def _getAssertEqualParams(self, func, call_params_string, locs=None):
968 assert 'inst' not in call_params_string
969 locs = dict(locs or {}, inst=self.inst)
970 return (func, 'inst,' + call_params_string, locs)
971
Michael Foord95fc51d2010-11-20 15:07:30 +0000972
973class TestGetattrStatic(unittest.TestCase):
974
975 def test_basic(self):
976 class Thing(object):
977 x = object()
978
979 thing = Thing()
980 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
981 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
982 with self.assertRaises(AttributeError):
983 inspect.getattr_static(thing, 'y')
984
985 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
986
987 def test_inherited(self):
988 class Thing(object):
989 x = object()
990 class OtherThing(Thing):
991 pass
992
993 something = OtherThing()
994 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
995
996 def test_instance_attr(self):
997 class Thing(object):
998 x = 2
999 def __init__(self, x):
1000 self.x = x
1001 thing = Thing(3)
1002 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1003 del thing.x
1004 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1005
1006 def test_property(self):
1007 class Thing(object):
1008 @property
1009 def x(self):
1010 raise AttributeError("I'm pretending not to exist")
1011 thing = Thing()
1012 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1013
Ezio Melotti75cbd732011-04-28 00:59:29 +03001014 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001015 class descriptor(object):
1016 def __get__(*_):
1017 raise AttributeError("I'm pretending not to exist")
1018 desc = descriptor()
1019 class Thing(object):
1020 x = desc
1021 thing = Thing()
1022 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1023
1024 def test_classAttribute(self):
1025 class Thing(object):
1026 x = object()
1027
1028 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1029
1030 def test_inherited_classattribute(self):
1031 class Thing(object):
1032 x = object()
1033 class OtherThing(Thing):
1034 pass
1035
1036 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1037
1038 def test_slots(self):
1039 class Thing(object):
1040 y = 'bar'
1041 __slots__ = ['x']
1042 def __init__(self):
1043 self.x = 'foo'
1044 thing = Thing()
1045 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1046 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1047
1048 del thing.x
1049 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1050
1051 def test_metaclass(self):
1052 class meta(type):
1053 attr = 'foo'
1054 class Thing(object, metaclass=meta):
1055 pass
1056 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1057
1058 class sub(meta):
1059 pass
1060 class OtherThing(object, metaclass=sub):
1061 x = 3
1062 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1063
1064 class OtherOtherThing(OtherThing):
1065 pass
1066 # this test is odd, but it was added as it exposed a bug
1067 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1068
1069 def test_no_dict_no_slots(self):
1070 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1071 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1072
1073 def test_no_dict_no_slots_instance_member(self):
1074 # returns descriptor
1075 with open(__file__) as handle:
1076 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1077
1078 def test_inherited_slots(self):
1079 # returns descriptor
1080 class Thing(object):
1081 __slots__ = ['x']
1082 def __init__(self):
1083 self.x = 'foo'
1084
1085 class OtherThing(Thing):
1086 pass
1087 # it would be nice if this worked...
1088 # we get the descriptor instead of the instance attribute
1089 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1090
1091 def test_descriptor(self):
1092 class descriptor(object):
1093 def __get__(self, instance, owner):
1094 return 3
1095 class Foo(object):
1096 d = descriptor()
1097
1098 foo = Foo()
1099
1100 # for a non data descriptor we return the instance attribute
1101 foo.__dict__['d'] = 1
1102 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1103
1104 # if the descriptor is a data-desciptor we should return the
1105 # descriptor
1106 descriptor.__set__ = lambda s, i, v: None
1107 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1108
1109
1110 def test_metaclass_with_descriptor(self):
1111 class descriptor(object):
1112 def __get__(self, instance, owner):
1113 return 3
1114 class meta(type):
1115 d = descriptor()
1116 class Thing(object, metaclass=meta):
1117 pass
1118 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1119
1120
Michael Foordcc7ebb82010-11-20 16:20:16 +00001121 def test_class_as_property(self):
1122 class Base(object):
1123 foo = 3
1124
1125 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001126 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001127 @property
1128 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001129 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001130 return object
1131
Michael Foord35184ed2010-11-20 16:58:30 +00001132 instance = Something()
1133 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1134 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001135 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1136
Michael Foorde5162652010-11-20 16:40:44 +00001137 def test_mro_as_property(self):
1138 class Meta(type):
1139 @property
1140 def __mro__(self):
1141 return (object,)
1142
1143 class Base(object):
1144 foo = 3
1145
1146 class Something(Base, metaclass=Meta):
1147 pass
1148
1149 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1150 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1151
Michael Foorddcebe0f2011-03-15 19:20:44 -04001152 def test_dict_as_property(self):
1153 test = self
1154 test.called = False
1155
1156 class Foo(dict):
1157 a = 3
1158 @property
1159 def __dict__(self):
1160 test.called = True
1161 return {}
1162
1163 foo = Foo()
1164 foo.a = 4
1165 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1166 self.assertFalse(test.called)
1167
1168 def test_custom_object_dict(self):
1169 test = self
1170 test.called = False
1171
1172 class Custom(dict):
1173 def get(self, key, default=None):
1174 test.called = True
1175 super().get(key, default)
1176
1177 class Foo(object):
1178 a = 3
1179 foo = Foo()
1180 foo.__dict__ = Custom()
1181 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1182 self.assertFalse(test.called)
1183
1184 def test_metaclass_dict_as_property(self):
1185 class Meta(type):
1186 @property
1187 def __dict__(self):
1188 self.executed = True
1189
1190 class Thing(metaclass=Meta):
1191 executed = False
1192
1193 def __init__(self):
1194 self.spam = 42
1195
1196 instance = Thing()
1197 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1198 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001199
Michael Foorda51623b2011-12-18 22:01:40 +00001200 def test_module(self):
1201 sentinel = object()
1202 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1203 sentinel)
1204
Michael Foord3ba95f82011-12-22 01:13:37 +00001205 def test_metaclass_with_metaclass_with_dict_as_property(self):
1206 class MetaMeta(type):
1207 @property
1208 def __dict__(self):
1209 self.executed = True
1210 return dict(spam=42)
1211
1212 class Meta(type, metaclass=MetaMeta):
1213 executed = False
1214
1215 class Thing(metaclass=Meta):
1216 pass
1217
1218 with self.assertRaises(AttributeError):
1219 inspect.getattr_static(Thing, "spam")
1220 self.assertFalse(Thing.executed)
1221
Nick Coghlane0f04652010-11-21 03:44:04 +00001222class TestGetGeneratorState(unittest.TestCase):
1223
1224 def setUp(self):
1225 def number_generator():
1226 for number in range(5):
1227 yield number
1228 self.generator = number_generator()
1229
1230 def _generatorstate(self):
1231 return inspect.getgeneratorstate(self.generator)
1232
1233 def test_created(self):
1234 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1235
1236 def test_suspended(self):
1237 next(self.generator)
1238 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1239
1240 def test_closed_after_exhaustion(self):
1241 for i in self.generator:
1242 pass
1243 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1244
1245 def test_closed_after_immediate_exception(self):
1246 with self.assertRaises(RuntimeError):
1247 self.generator.throw(RuntimeError)
1248 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1249
1250 def test_running(self):
1251 # As mentioned on issue #10220, checking for the RUNNING state only
1252 # makes sense inside the generator itself.
1253 # The following generator checks for this by using the closure's
1254 # reference to self and the generator state checking helper method
1255 def running_check_generator():
1256 for number in range(5):
1257 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1258 yield number
1259 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1260 self.generator = running_check_generator()
1261 # Running up to the first yield
1262 next(self.generator)
1263 # Running after the first yield
1264 next(self.generator)
1265
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001266 def test_easy_debugging(self):
1267 # repr() and str() of a generator state should contain the state name
1268 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1269 for name in names:
1270 state = getattr(inspect, name)
1271 self.assertIn(name, repr(state))
1272 self.assertIn(name, str(state))
1273
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001274 def test_getgeneratorlocals(self):
1275 def each(lst, a=None):
1276 b=(1, 2, 3)
1277 for v in lst:
1278 if v == 3:
1279 c = 12
1280 yield v
1281
1282 numbers = each([1, 2, 3])
1283 self.assertEqual(inspect.getgeneratorlocals(numbers),
1284 {'a': None, 'lst': [1, 2, 3]})
1285 next(numbers)
1286 self.assertEqual(inspect.getgeneratorlocals(numbers),
1287 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1288 'b': (1, 2, 3)})
1289 next(numbers)
1290 self.assertEqual(inspect.getgeneratorlocals(numbers),
1291 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1292 'b': (1, 2, 3)})
1293 next(numbers)
1294 self.assertEqual(inspect.getgeneratorlocals(numbers),
1295 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1296 'b': (1, 2, 3), 'c': 12})
1297 try:
1298 next(numbers)
1299 except StopIteration:
1300 pass
1301 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1302
1303 def test_getgeneratorlocals_empty(self):
1304 def yield_one():
1305 yield 1
1306 one = yield_one()
1307 self.assertEqual(inspect.getgeneratorlocals(one), {})
1308 try:
1309 next(one)
1310 except StopIteration:
1311 pass
1312 self.assertEqual(inspect.getgeneratorlocals(one), {})
1313
1314 def test_getgeneratorlocals_error(self):
1315 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1316 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1317 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1318 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1319
Nick Coghlane0f04652010-11-21 03:44:04 +00001320
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001321class TestSignatureObject(unittest.TestCase):
1322 @staticmethod
1323 def signature(func):
1324 sig = inspect.signature(func)
1325 return (tuple((param.name,
1326 (... if param.default is param.empty else param.default),
1327 (... if param.annotation is param.empty
1328 else param.annotation),
1329 str(param.kind).lower())
1330 for param in sig.parameters.values()),
1331 (... if sig.return_annotation is sig.empty
1332 else sig.return_annotation))
1333
1334 def test_signature_object(self):
1335 S = inspect.Signature
1336 P = inspect.Parameter
1337
1338 self.assertEqual(str(S()), '()')
1339
1340 def test(po, pk, *args, ko, **kwargs):
1341 pass
1342 sig = inspect.signature(test)
1343 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
1344 pk = sig.parameters['pk']
1345 args = sig.parameters['args']
1346 ko = sig.parameters['ko']
1347 kwargs = sig.parameters['kwargs']
1348
1349 S((po, pk, args, ko, kwargs))
1350
1351 with self.assertRaisesRegexp(ValueError, 'wrong parameter order'):
1352 S((pk, po, args, ko, kwargs))
1353
1354 with self.assertRaisesRegexp(ValueError, 'wrong parameter order'):
1355 S((po, args, pk, ko, kwargs))
1356
1357 with self.assertRaisesRegexp(ValueError, 'wrong parameter order'):
1358 S((args, po, pk, ko, kwargs))
1359
1360 with self.assertRaisesRegexp(ValueError, 'wrong parameter order'):
1361 S((po, pk, args, kwargs, ko))
1362
1363 kwargs2 = kwargs.replace(name='args')
1364 with self.assertRaisesRegexp(ValueError, 'duplicate parameter name'):
1365 S((po, pk, args, kwargs2, ko))
1366
1367 def test_signature_immutability(self):
1368 def test(a):
1369 pass
1370 sig = inspect.signature(test)
1371
1372 with self.assertRaises(AttributeError):
1373 sig.foo = 'bar'
1374
1375 with self.assertRaises(TypeError):
1376 sig.parameters['a'] = None
1377
1378 def test_signature_on_noarg(self):
1379 def test():
1380 pass
1381 self.assertEqual(self.signature(test), ((), ...))
1382
1383 def test_signature_on_wargs(self):
1384 def test(a, b:'foo') -> 123:
1385 pass
1386 self.assertEqual(self.signature(test),
1387 ((('a', ..., ..., "positional_or_keyword"),
1388 ('b', ..., 'foo', "positional_or_keyword")),
1389 123))
1390
1391 def test_signature_on_wkwonly(self):
1392 def test(*, a:float, b:str) -> int:
1393 pass
1394 self.assertEqual(self.signature(test),
1395 ((('a', ..., float, "keyword_only"),
1396 ('b', ..., str, "keyword_only")),
1397 int))
1398
1399 def test_signature_on_complex_args(self):
1400 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1401 pass
1402 self.assertEqual(self.signature(test),
1403 ((('a', ..., ..., "positional_or_keyword"),
1404 ('b', 10, 'foo', "positional_or_keyword"),
1405 ('args', ..., 'bar', "var_positional"),
1406 ('spam', ..., 'baz', "keyword_only"),
1407 ('ham', 123, ..., "keyword_only"),
1408 ('kwargs', ..., int, "var_keyword")),
1409 ...))
1410
1411 def test_signature_on_builtin_function(self):
1412 with self.assertRaisesRegexp(ValueError, 'not supported by signature'):
1413 inspect.signature(type)
1414 with self.assertRaisesRegexp(ValueError, 'not supported by signature'):
1415 # support for 'wrapper_descriptor'
1416 inspect.signature(type.__call__)
1417 with self.assertRaisesRegexp(ValueError, 'not supported by signature'):
1418 # support for 'method-wrapper'
1419 inspect.signature(min.__call__)
1420 with self.assertRaisesRegexp(ValueError,
1421 'no signature found for builtin function'):
1422 # support for 'method-wrapper'
1423 inspect.signature(min)
1424
1425 def test_signature_on_non_function(self):
1426 with self.assertRaisesRegexp(TypeError, 'is not a callable object'):
1427 inspect.signature(42)
1428
1429 with self.assertRaisesRegexp(TypeError, 'is not a Python function'):
1430 inspect.Signature.from_function(42)
1431
1432 def test_signature_on_method(self):
1433 class Test:
1434 def foo(self, arg1, arg2=1) -> int:
1435 pass
1436
1437 meth = Test().foo
1438
1439 self.assertEqual(self.signature(meth),
1440 ((('arg1', ..., ..., "positional_or_keyword"),
1441 ('arg2', 1, ..., "positional_or_keyword")),
1442 int))
1443
1444 def test_signature_on_classmethod(self):
1445 class Test:
1446 @classmethod
1447 def foo(cls, arg1, *, arg2=1):
1448 pass
1449
1450 meth = Test().foo
1451 self.assertEqual(self.signature(meth),
1452 ((('arg1', ..., ..., "positional_or_keyword"),
1453 ('arg2', 1, ..., "keyword_only")),
1454 ...))
1455
1456 meth = Test.foo
1457 self.assertEqual(self.signature(meth),
1458 ((('arg1', ..., ..., "positional_or_keyword"),
1459 ('arg2', 1, ..., "keyword_only")),
1460 ...))
1461
1462 def test_signature_on_staticmethod(self):
1463 class Test:
1464 @staticmethod
1465 def foo(cls, *, arg):
1466 pass
1467
1468 meth = Test().foo
1469 self.assertEqual(self.signature(meth),
1470 ((('cls', ..., ..., "positional_or_keyword"),
1471 ('arg', ..., ..., "keyword_only")),
1472 ...))
1473
1474 meth = Test.foo
1475 self.assertEqual(self.signature(meth),
1476 ((('cls', ..., ..., "positional_or_keyword"),
1477 ('arg', ..., ..., "keyword_only")),
1478 ...))
1479
1480 def test_signature_on_partial(self):
1481 from functools import partial
1482
1483 def test():
1484 pass
1485
1486 self.assertEqual(self.signature(partial(test)), ((), ...))
1487
1488 with self.assertRaisesRegexp(ValueError, "has incorrect arguments"):
1489 inspect.signature(partial(test, 1))
1490
1491 with self.assertRaisesRegexp(ValueError, "has incorrect arguments"):
1492 inspect.signature(partial(test, a=1))
1493
1494 def test(a, b, *, c, d):
1495 pass
1496
1497 self.assertEqual(self.signature(partial(test)),
1498 ((('a', ..., ..., "positional_or_keyword"),
1499 ('b', ..., ..., "positional_or_keyword"),
1500 ('c', ..., ..., "keyword_only"),
1501 ('d', ..., ..., "keyword_only")),
1502 ...))
1503
1504 self.assertEqual(self.signature(partial(test, 1)),
1505 ((('b', ..., ..., "positional_or_keyword"),
1506 ('c', ..., ..., "keyword_only"),
1507 ('d', ..., ..., "keyword_only")),
1508 ...))
1509
1510 self.assertEqual(self.signature(partial(test, 1, c=2)),
1511 ((('b', ..., ..., "positional_or_keyword"),
1512 ('c', 2, ..., "keyword_only"),
1513 ('d', ..., ..., "keyword_only")),
1514 ...))
1515
1516 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1517 ((('a', ..., ..., "positional_or_keyword"),
1518 ('b', 1, ..., "positional_or_keyword"),
1519 ('c', 2, ..., "keyword_only"),
1520 ('d', ..., ..., "keyword_only")),
1521 ...))
1522
1523 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
1524 ((('b', 1, ..., "positional_or_keyword"),
1525 ('c', 2, ..., "keyword_only"),
1526 ('d', ..., ..., "keyword_only"),),
1527 ...))
1528
1529 def test(a, *args, b, **kwargs):
1530 pass
1531
1532 self.assertEqual(self.signature(partial(test, 1)),
1533 ((('args', ..., ..., "var_positional"),
1534 ('b', ..., ..., "keyword_only"),
1535 ('kwargs', ..., ..., "var_keyword")),
1536 ...))
1537
1538 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
1539 ((('args', ..., ..., "var_positional"),
1540 ('b', ..., ..., "keyword_only"),
1541 ('kwargs', ..., ..., "var_keyword")),
1542 ...))
1543
1544
1545 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
1546 ((('args', ..., ..., "var_positional"),
1547 ('b', ..., ..., "keyword_only"),
1548 ('kwargs', ..., ..., "var_keyword")),
1549 ...))
1550
1551 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
1552 ((('args', ..., ..., "var_positional"),
1553 ('b', 0, ..., "keyword_only"),
1554 ('kwargs', ..., ..., "var_keyword")),
1555 ...))
1556
1557 self.assertEqual(self.signature(partial(test, b=0)),
1558 ((('a', ..., ..., "positional_or_keyword"),
1559 ('args', ..., ..., "var_positional"),
1560 ('b', 0, ..., "keyword_only"),
1561 ('kwargs', ..., ..., "var_keyword")),
1562 ...))
1563
1564 self.assertEqual(self.signature(partial(test, b=0, test=1)),
1565 ((('a', ..., ..., "positional_or_keyword"),
1566 ('args', ..., ..., "var_positional"),
1567 ('b', 0, ..., "keyword_only"),
1568 ('kwargs', ..., ..., "var_keyword")),
1569 ...))
1570
1571 def test(a, b, c:int) -> 42:
1572 pass
1573
1574 sig = test.__signature__ = inspect.signature(test)
1575
1576 self.assertEqual(self.signature(partial(partial(test, 1))),
1577 ((('b', ..., ..., "positional_or_keyword"),
1578 ('c', ..., int, "positional_or_keyword")),
1579 42))
1580
1581 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
1582 ((('c', ..., int, "positional_or_keyword"),),
1583 42))
1584
1585 psig = inspect.signature(partial(partial(test, 1), 2))
1586
1587 def foo(a):
1588 return a
1589 _foo = partial(partial(foo, a=10), a=20)
1590 self.assertEqual(self.signature(_foo),
1591 ((('a', 20, ..., "positional_or_keyword"),),
1592 ...))
1593 # check that we don't have any side-effects in signature(),
1594 # and the partial object is still functioning
1595 self.assertEqual(_foo(), 20)
1596
1597 def foo(a, b, c):
1598 return a, b, c
1599 _foo = partial(partial(foo, 1, b=20), b=30)
1600 self.assertEqual(self.signature(_foo),
1601 ((('b', 30, ..., "positional_or_keyword"),
1602 ('c', ..., ..., "positional_or_keyword")),
1603 ...))
1604 self.assertEqual(_foo(c=10), (1, 30, 10))
1605 _foo = partial(_foo, 2) # now 'b' has two values -
1606 # positional and keyword
1607 with self.assertRaisesRegexp(ValueError, "has incorrect arguments"):
1608 inspect.signature(_foo)
1609
1610 def foo(a, b, c, *, d):
1611 return a, b, c, d
1612 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
1613 self.assertEqual(self.signature(_foo),
1614 ((('a', ..., ..., "positional_or_keyword"),
1615 ('b', 10, ..., "positional_or_keyword"),
1616 ('c', 20, ..., "positional_or_keyword"),
1617 ('d', 30, ..., "keyword_only")),
1618 ...))
1619 ba = inspect.signature(_foo).bind(a=200, b=11)
1620 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
1621
1622 def foo(a=1, b=2, c=3):
1623 return a, b, c
1624 _foo = partial(foo, a=10, c=13)
1625 ba = inspect.signature(_foo).bind(11)
1626 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
1627 ba = inspect.signature(_foo).bind(11, 12)
1628 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1629 ba = inspect.signature(_foo).bind(11, b=12)
1630 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1631 ba = inspect.signature(_foo).bind(b=12)
1632 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
1633 _foo = partial(_foo, b=10)
1634 ba = inspect.signature(_foo).bind(12, 14)
1635 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
1636
1637 def test_signature_on_decorated(self):
1638 import functools
1639
1640 def decorator(func):
1641 @functools.wraps(func)
1642 def wrapper(*args, **kwargs) -> int:
1643 return func(*args, **kwargs)
1644 return wrapper
1645
1646 class Foo:
1647 @decorator
1648 def bar(self, a, b):
1649 pass
1650
1651 self.assertEqual(self.signature(Foo.bar),
1652 ((('self', ..., ..., "positional_or_keyword"),
1653 ('a', ..., ..., "positional_or_keyword"),
1654 ('b', ..., ..., "positional_or_keyword")),
1655 ...))
1656
1657 self.assertEqual(self.signature(Foo().bar),
1658 ((('a', ..., ..., "positional_or_keyword"),
1659 ('b', ..., ..., "positional_or_keyword")),
1660 ...))
1661
1662 # Test that we handle method wrappers correctly
1663 def decorator(func):
1664 @functools.wraps(func)
1665 def wrapper(*args, **kwargs) -> int:
1666 return func(42, *args, **kwargs)
1667 sig = inspect.signature(func)
1668 new_params = tuple(sig.parameters.values())[1:]
1669 wrapper.__signature__ = sig.replace(parameters=new_params)
1670 return wrapper
1671
1672 class Foo:
1673 @decorator
1674 def __call__(self, a, b):
1675 pass
1676
1677 self.assertEqual(self.signature(Foo.__call__),
1678 ((('a', ..., ..., "positional_or_keyword"),
1679 ('b', ..., ..., "positional_or_keyword")),
1680 ...))
1681
1682 self.assertEqual(self.signature(Foo().__call__),
1683 ((('b', ..., ..., "positional_or_keyword"),),
1684 ...))
1685
1686 def test_signature_on_class(self):
1687 class C:
1688 def __init__(self, a):
1689 pass
1690
1691 self.assertEqual(self.signature(C),
1692 ((('a', ..., ..., "positional_or_keyword"),),
1693 ...))
1694
1695 class CM(type):
1696 def __call__(cls, a):
1697 pass
1698 class C(metaclass=CM):
1699 def __init__(self, b):
1700 pass
1701
1702 self.assertEqual(self.signature(C),
1703 ((('a', ..., ..., "positional_or_keyword"),),
1704 ...))
1705
1706 class CM(type):
1707 def __new__(mcls, name, bases, dct, *, foo=1):
1708 return super().__new__(mcls, name, bases, dct)
1709 class C(metaclass=CM):
1710 def __init__(self, b):
1711 pass
1712
1713 self.assertEqual(self.signature(C),
1714 ((('b', ..., ..., "positional_or_keyword"),),
1715 ...))
1716
1717 self.assertEqual(self.signature(CM),
1718 ((('name', ..., ..., "positional_or_keyword"),
1719 ('bases', ..., ..., "positional_or_keyword"),
1720 ('dct', ..., ..., "positional_or_keyword"),
1721 ('foo', 1, ..., "keyword_only")),
1722 ...))
1723
1724 class CMM(type):
1725 def __new__(mcls, name, bases, dct, *, foo=1):
1726 return super().__new__(mcls, name, bases, dct)
1727 def __call__(cls, nm, bs, dt):
1728 return type(nm, bs, dt)
1729 class CM(type, metaclass=CMM):
1730 def __new__(mcls, name, bases, dct, *, bar=2):
1731 return super().__new__(mcls, name, bases, dct)
1732 class C(metaclass=CM):
1733 def __init__(self, b):
1734 pass
1735
1736 self.assertEqual(self.signature(CMM),
1737 ((('name', ..., ..., "positional_or_keyword"),
1738 ('bases', ..., ..., "positional_or_keyword"),
1739 ('dct', ..., ..., "positional_or_keyword"),
1740 ('foo', 1, ..., "keyword_only")),
1741 ...))
1742
1743 self.assertEqual(self.signature(CM),
1744 ((('nm', ..., ..., "positional_or_keyword"),
1745 ('bs', ..., ..., "positional_or_keyword"),
1746 ('dt', ..., ..., "positional_or_keyword")),
1747 ...))
1748
1749 self.assertEqual(self.signature(C),
1750 ((('b', ..., ..., "positional_or_keyword"),),
1751 ...))
1752
1753 class CM(type):
1754 def __init__(cls, name, bases, dct, *, bar=2):
1755 return super().__init__(name, bases, dct)
1756 class C(metaclass=CM):
1757 def __init__(self, b):
1758 pass
1759
1760 self.assertEqual(self.signature(CM),
1761 ((('name', ..., ..., "positional_or_keyword"),
1762 ('bases', ..., ..., "positional_or_keyword"),
1763 ('dct', ..., ..., "positional_or_keyword"),
1764 ('bar', 2, ..., "keyword_only")),
1765 ...))
1766
1767 def test_signature_on_callable_objects(self):
1768 class Foo:
1769 def __call__(self, a):
1770 pass
1771
1772 self.assertEqual(self.signature(Foo()),
1773 ((('a', ..., ..., "positional_or_keyword"),),
1774 ...))
1775
1776 class Spam:
1777 pass
1778 with self.assertRaisesRegexp(TypeError, "is not a callable object"):
1779 inspect.signature(Spam())
1780
1781 class Bar(Spam, Foo):
1782 pass
1783
1784 self.assertEqual(self.signature(Bar()),
1785 ((('a', ..., ..., "positional_or_keyword"),),
1786 ...))
1787
1788 class ToFail:
1789 __call__ = type
1790 with self.assertRaisesRegexp(ValueError, "not supported by signature"):
1791 inspect.signature(ToFail())
1792
1793
1794 class Wrapped:
1795 pass
1796 Wrapped.__wrapped__ = lambda a: None
1797 self.assertEqual(self.signature(Wrapped),
1798 ((('a', ..., ..., "positional_or_keyword"),),
1799 ...))
1800
1801 def test_signature_on_lambdas(self):
1802 self.assertEqual(self.signature((lambda a=10: a)),
1803 ((('a', 10, ..., "positional_or_keyword"),),
1804 ...))
1805
1806 def test_signature_equality(self):
1807 def foo(a, *, b:int) -> float: pass
1808 self.assertNotEqual(inspect.signature(foo), 42)
1809
1810 def bar(a, *, b:int) -> float: pass
1811 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1812
1813 def bar(a, *, b:int) -> int: pass
1814 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1815
1816 def bar(a, *, b:int): pass
1817 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1818
1819 def bar(a, *, b:int=42) -> float: pass
1820 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1821
1822 def bar(a, *, c) -> float: pass
1823 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1824
1825 def bar(a, b:int) -> float: pass
1826 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1827 def spam(b:int, a) -> float: pass
1828 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
1829
1830 def foo(*, a, b, c): pass
1831 def bar(*, c, b, a): pass
1832 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1833
1834 def foo(*, a=1, b, c): pass
1835 def bar(*, c, b, a=1): pass
1836 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1837
1838 def foo(pos, *, a=1, b, c): pass
1839 def bar(pos, *, c, b, a=1): pass
1840 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1841
1842 def foo(pos, *, a, b, c): pass
1843 def bar(pos, *, c, b, a=1): pass
1844 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1845
1846 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
1847 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
1848 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1849
1850 def test_signature_unhashable(self):
1851 def foo(a): pass
1852 sig = inspect.signature(foo)
1853 with self.assertRaisesRegexp(TypeError, 'unhashable type'):
1854 hash(sig)
1855
1856 def test_signature_str(self):
1857 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
1858 pass
1859 self.assertEqual(str(inspect.signature(foo)),
1860 '(a:int=1, *, b, c=None, **kwargs) -> 42')
1861
1862 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
1863 pass
1864 self.assertEqual(str(inspect.signature(foo)),
1865 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
1866
1867 def foo():
1868 pass
1869 self.assertEqual(str(inspect.signature(foo)), '()')
1870
1871 def test_signature_str_positional_only(self):
1872 P = inspect.Parameter
1873
1874 def test(a_po, *, b, **kwargs):
1875 return a_po, kwargs
1876
1877 sig = inspect.signature(test)
1878 new_params = list(sig.parameters.values())
1879 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
1880 test.__signature__ = sig.replace(parameters=new_params)
1881
1882 self.assertEqual(str(inspect.signature(test)),
1883 '(<a_po>, *, b, **kwargs)')
1884
1885 sig = inspect.signature(test)
1886 new_params = list(sig.parameters.values())
1887 new_params[0] = new_params[0].replace(name=None)
1888 test.__signature__ = sig.replace(parameters=new_params)
1889 self.assertEqual(str(inspect.signature(test)),
1890 '(<0>, *, b, **kwargs)')
1891
1892 def test_signature_replace_anno(self):
1893 def test() -> 42:
1894 pass
1895
1896 sig = inspect.signature(test)
1897 sig = sig.replace(return_annotation=None)
1898 self.assertIs(sig.return_annotation, None)
1899 sig = sig.replace(return_annotation=sig.empty)
1900 self.assertIs(sig.return_annotation, sig.empty)
1901 sig = sig.replace(return_annotation=42)
1902 self.assertEqual(sig.return_annotation, 42)
1903 self.assertEqual(sig, inspect.signature(test))
1904
1905
1906class TestParameterObject(unittest.TestCase):
1907 def test_signature_parameter_kinds(self):
1908 P = inspect.Parameter
1909 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
1910 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
1911
1912 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
1913 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
1914
1915 def test_signature_parameter_object(self):
1916 p = inspect.Parameter('foo', default=10,
1917 kind=inspect.Parameter.POSITIONAL_ONLY)
1918 self.assertEqual(p.name, 'foo')
1919 self.assertEqual(p.default, 10)
1920 self.assertIs(p.annotation, p.empty)
1921 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
1922
1923 with self.assertRaisesRegexp(ValueError, 'invalid value'):
1924 inspect.Parameter('foo', default=10, kind='123')
1925
1926 with self.assertRaisesRegexp(ValueError, 'not a valid parameter name'):
1927 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
1928
1929 with self.assertRaisesRegexp(ValueError,
1930 'non-positional-only parameter'):
1931 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
1932
1933 with self.assertRaisesRegexp(ValueError, 'cannot have default values'):
1934 inspect.Parameter('a', default=42,
1935 kind=inspect.Parameter.VAR_KEYWORD)
1936
1937 with self.assertRaisesRegexp(ValueError, 'cannot have default values'):
1938 inspect.Parameter('a', default=42,
1939 kind=inspect.Parameter.VAR_POSITIONAL)
1940
1941 p = inspect.Parameter('a', default=42,
1942 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
1943 with self.assertRaisesRegexp(ValueError, 'cannot have default values'):
1944 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
1945
1946 self.assertTrue(repr(p).startswith('<Parameter'))
1947
1948 def test_signature_parameter_equality(self):
1949 P = inspect.Parameter
1950 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
1951
1952 self.assertEqual(p, p)
1953 self.assertNotEqual(p, 42)
1954
1955 self.assertEqual(p, P('foo', default=42,
1956 kind=inspect.Parameter.KEYWORD_ONLY))
1957
1958 def test_signature_parameter_unhashable(self):
1959 p = inspect.Parameter('foo', default=42,
1960 kind=inspect.Parameter.KEYWORD_ONLY)
1961
1962 with self.assertRaisesRegexp(TypeError, 'unhashable type'):
1963 hash(p)
1964
1965 def test_signature_parameter_replace(self):
1966 p = inspect.Parameter('foo', default=42,
1967 kind=inspect.Parameter.KEYWORD_ONLY)
1968
1969 self.assertIsNot(p, p.replace())
1970 self.assertEqual(p, p.replace())
1971
1972 p2 = p.replace(annotation=1)
1973 self.assertEqual(p2.annotation, 1)
1974 p2 = p2.replace(annotation=p2.empty)
1975 self.assertEqual(p, p2)
1976
1977 p2 = p2.replace(name='bar')
1978 self.assertEqual(p2.name, 'bar')
1979 self.assertNotEqual(p2, p)
1980
1981 with self.assertRaisesRegexp(ValueError, 'not a valid parameter name'):
1982 p2 = p2.replace(name=p2.empty)
1983
1984 p2 = p2.replace(name='foo', default=None)
1985 self.assertIs(p2.default, None)
1986 self.assertNotEqual(p2, p)
1987
1988 p2 = p2.replace(name='foo', default=p2.empty)
1989 self.assertIs(p2.default, p2.empty)
1990
1991
1992 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
1993 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
1994 self.assertNotEqual(p2, p)
1995
1996 with self.assertRaisesRegexp(ValueError, 'invalid value for'):
1997 p2 = p2.replace(kind=p2.empty)
1998
1999 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2000 self.assertEqual(p2, p)
2001
2002 def test_signature_parameter_positional_only(self):
2003 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2004 self.assertEqual(str(p), '<>')
2005
2006 p = p.replace(name='1')
2007 self.assertEqual(str(p), '<1>')
2008
2009 def test_signature_parameter_immutability(self):
2010 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2011
2012 with self.assertRaises(AttributeError):
2013 p.foo = 'bar'
2014
2015 with self.assertRaises(AttributeError):
2016 p.kind = 123
2017
2018
2019class TestSignatureBind(unittest.TestCase):
2020 @staticmethod
2021 def call(func, *args, **kwargs):
2022 sig = inspect.signature(func)
2023 ba = sig.bind(*args, **kwargs)
2024 return func(*ba.args, **ba.kwargs)
2025
2026 def test_signature_bind_empty(self):
2027 def test():
2028 return 42
2029
2030 self.assertEqual(self.call(test), 42)
2031 with self.assertRaisesRegexp(TypeError, 'too many positional arguments'):
2032 self.call(test, 1)
2033 with self.assertRaisesRegexp(TypeError, 'too many positional arguments'):
2034 self.call(test, 1, spam=10)
2035 with self.assertRaisesRegexp(TypeError, 'too many keyword arguments'):
2036 self.call(test, spam=1)
2037
2038 def test_signature_bind_var(self):
2039 def test(*args, **kwargs):
2040 return args, kwargs
2041
2042 self.assertEqual(self.call(test), ((), {}))
2043 self.assertEqual(self.call(test, 1), ((1,), {}))
2044 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2045 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2046 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2047 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2048 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2049 ((1, 2), {'foo': 'bar'}))
2050
2051 def test_signature_bind_just_args(self):
2052 def test(a, b, c):
2053 return a, b, c
2054
2055 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2056
2057 with self.assertRaisesRegexp(TypeError, 'too many positional arguments'):
2058 self.call(test, 1, 2, 3, 4)
2059
2060 with self.assertRaisesRegexp(TypeError, "'b' parameter lacking default"):
2061 self.call(test, 1)
2062
2063 with self.assertRaisesRegexp(TypeError, "'a' parameter lacking default"):
2064 self.call(test)
2065
2066 def test(a, b, c=10):
2067 return a, b, c
2068 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2069 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2070
2071 def test(a=1, b=2, c=3):
2072 return a, b, c
2073 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2074 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2075 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2076
2077 def test_signature_bind_varargs_order(self):
2078 def test(*args):
2079 return args
2080
2081 self.assertEqual(self.call(test), ())
2082 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2083
2084 def test_signature_bind_args_and_varargs(self):
2085 def test(a, b, c=3, *args):
2086 return a, b, c, args
2087
2088 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2089 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2090 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2091 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2092
2093 with self.assertRaisesRegexp(TypeError,
2094 "multiple values for argument 'c'"):
2095 self.call(test, 1, 2, 3, c=4)
2096
2097 def test_signature_bind_just_kwargs(self):
2098 def test(**kwargs):
2099 return kwargs
2100
2101 self.assertEqual(self.call(test), {})
2102 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2103 {'foo': 'bar', 'spam': 'ham'})
2104
2105 def test_signature_bind_args_and_kwargs(self):
2106 def test(a, b, c=3, **kwargs):
2107 return a, b, c, kwargs
2108
2109 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2110 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2111 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2112 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2113 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2114 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2115 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2116 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2117 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2118 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2119 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2120 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2121 (1, 2, 4, {'foo': 'bar'}))
2122 self.assertEqual(self.call(test, c=5, a=4, b=3),
2123 (4, 3, 5, {}))
2124
2125 def test_signature_bind_kwonly(self):
2126 def test(*, foo):
2127 return foo
2128 with self.assertRaisesRegexp(TypeError,
2129 'too many positional arguments'):
2130 self.call(test, 1)
2131 self.assertEqual(self.call(test, foo=1), 1)
2132
2133 def test(a, *, foo=1, bar):
2134 return foo
2135 with self.assertRaisesRegexp(TypeError,
2136 "'bar' parameter lacking default value"):
2137 self.call(test, 1)
2138
2139 def test(foo, *, bar):
2140 return foo, bar
2141 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2142 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2143
2144 with self.assertRaisesRegexp(TypeError,
2145 'too many keyword arguments'):
2146 self.call(test, bar=2, foo=1, spam=10)
2147
2148 with self.assertRaisesRegexp(TypeError,
2149 'too many positional arguments'):
2150 self.call(test, 1, 2)
2151
2152 with self.assertRaisesRegexp(TypeError,
2153 'too many positional arguments'):
2154 self.call(test, 1, 2, bar=2)
2155
2156 with self.assertRaisesRegexp(TypeError,
2157 'too many keyword arguments'):
2158 self.call(test, 1, bar=2, spam='ham')
2159
2160 with self.assertRaisesRegexp(TypeError,
2161 "'bar' parameter lacking default value"):
2162 self.call(test, 1)
2163
2164 def test(foo, *, bar, **bin):
2165 return foo, bar, bin
2166 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2167 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2168 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2169 (1, 2, {'spam': 'ham'}))
2170 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2171 (1, 2, {'spam': 'ham'}))
2172 with self.assertRaisesRegexp(TypeError,
2173 "'foo' parameter lacking default value"):
2174 self.call(test, spam='ham', bar=2)
2175 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2176 (1, 2, {'bin': 1, 'spam': 10}))
2177
2178 def test_signature_bind_arguments(self):
2179 def test(a, *args, b, z=100, **kwargs):
2180 pass
2181 sig = inspect.signature(test)
2182 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2183 # we won't have 'z' argument in the bound arguments object, as we didn't
2184 # pass it to the 'bind'
2185 self.assertEqual(tuple(ba.arguments.items()),
2186 (('a', 10), ('args', (20,)), ('b', 30),
2187 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2188 self.assertEqual(ba.kwargs,
2189 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2190 self.assertEqual(ba.args, (10, 20))
2191
2192 def test_signature_bind_positional_only(self):
2193 P = inspect.Parameter
2194
2195 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2196 return a_po, b_po, c_po, foo, bar, kwargs
2197
2198 sig = inspect.signature(test)
2199 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2200 for name in ('a_po', 'b_po', 'c_po'):
2201 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2202 new_sig = sig.replace(parameters=new_params.values())
2203 test.__signature__ = new_sig
2204
2205 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2206 (1, 2, 4, 5, 6, {}))
2207
2208 with self.assertRaisesRegexp(TypeError, "parameter is positional only"):
2209 self.call(test, 1, 2, c_po=4)
2210
2211 with self.assertRaisesRegexp(TypeError, "parameter is positional only"):
2212 self.call(test, a_po=1, b_po=2)
2213
2214
2215class TestBoundArguments(unittest.TestCase):
2216 def test_signature_bound_arguments_unhashable(self):
2217 def foo(a): pass
2218 ba = inspect.signature(foo).bind(1)
2219
2220 with self.assertRaisesRegexp(TypeError, 'unhashable type'):
2221 hash(ba)
2222
2223 def test_signature_bound_arguments_equality(self):
2224 def foo(a): pass
2225 ba = inspect.signature(foo).bind(1)
2226 self.assertEqual(ba, ba)
2227
2228 ba2 = inspect.signature(foo).bind(1)
2229 self.assertEqual(ba, ba2)
2230
2231 ba3 = inspect.signature(foo).bind(2)
2232 self.assertNotEqual(ba, ba3)
2233 ba3.arguments['a'] = 1
2234 self.assertEqual(ba, ba3)
2235
2236 def bar(b): pass
2237 ba4 = inspect.signature(bar).bind(1)
2238 self.assertNotEqual(ba, ba4)
2239
2240
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002241def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00002242 run_unittest(
2243 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
2244 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
2245 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00002246 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002247 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan2f92e542012-06-23 19:39:55 +10002248 TestBoundArguments, TestGetClosureVars
Michael Foord95fc51d2010-11-20 15:07:30 +00002249 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00002250
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002251if __name__ == "__main__":
2252 test_main()