blob: 9f5e93b0c7fb4663847a970f360743d2149260a3 [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)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200288 try:
289 self.assertEqual(normcase(inspect.getsourcefile(co)), fn)
290 finally:
291 del linecache.cache[co.co_filename]
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000292
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000293 def test_getfile(self):
294 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000295
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000296 def test_getmodule_recursion(self):
Christian Heimes45f9af32007-11-27 21:50:00 +0000297 from types import ModuleType
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000298 name = '__inspect_dummy'
Christian Heimes45f9af32007-11-27 21:50:00 +0000299 m = sys.modules[name] = ModuleType(name)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000300 m.__file__ = "<string>" # hopefully not a real filename...
301 m.__loader__ = "dummy" # pretend the filename is understood by a loader
Georg Brandl7cae87c2006-09-06 06:51:57 +0000302 exec("def x(): pass", m.__dict__)
Neal Norwitz221085d2007-02-25 20:55:47 +0000303 self.assertEqual(inspect.getsourcefile(m.x.__code__), '<string>')
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000304 del sys.modules[name]
305 inspect.getmodule(compile('a=10','','single'))
306
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500307 def test_proceed_with_fake_filename(self):
308 '''doctest monkeypatches linecache to enable inspection'''
309 fn, source = '<test>', 'def x(): pass\n'
310 getlines = linecache.getlines
311 def monkey(filename, module_globals=None):
312 if filename == fn:
Ezio Melottid8b509b2011-09-28 17:37:55 +0300313 return source.splitlines(keepends=True)
Benjamin Peterson9620cc02011-06-11 15:53:11 -0500314 else:
315 return getlines(filename, module_globals)
316 linecache.getlines = monkey
317 try:
318 ns = {}
319 exec(compile(source, fn, 'single'), ns)
320 inspect.getsource(ns["x"])
321 finally:
322 linecache.getlines = getlines
323
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000324class TestDecorators(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000325 fodderModule = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000326
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000327 def test_wrapped_decorator(self):
Christian Heimes09aaa882008-02-23 15:01:06 +0000328 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000329
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000330 def test_replacing_decorator(self):
331 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000332
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000333class TestOneliners(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000334 fodderModule = mod2
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000335 def test_oneline_lambda(self):
336 # Test inspect.getsource with a one-line lambda function.
337 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000338
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000339 def test_threeline_lambda(self):
340 # Test inspect.getsource with a three-line lambda function,
341 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000342 self.assertSourceEqual(mod2.tll, 28, 30)
343
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000344 def test_twoline_indented_lambda(self):
345 # Test inspect.getsource with a two-line lambda function,
346 # where the second line _is_ indented.
347 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000348
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000349 def test_onelinefunc(self):
350 # Test inspect.getsource with a regular one-line function.
351 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000352
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000353 def test_manyargs(self):
354 # Test inspect.getsource with a regular function where
355 # the arguments are on two lines and _not_ indented and
356 # the body on the second line with the last arguments.
357 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000358
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000359 def test_twolinefunc(self):
360 # Test inspect.getsource with a regular function where
361 # the body is on two lines, following the argument list and
362 # continued on the next line by a \\.
363 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000364
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000365 def test_lambda_in_list(self):
366 # Test inspect.getsource with a one-line lambda function
367 # defined in a list, indented.
368 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000369
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000370 def test_anonymous(self):
371 # Test inspect.getsource with a lambda function defined
372 # as argument to another function.
373 self.assertSourceEqual(mod2.anonymous, 55, 55)
374
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000375class TestBuggyCases(GetSourceBase):
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000376 fodderModule = mod2
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000377
378 def test_with_comment(self):
379 self.assertSourceEqual(mod2.with_comment, 58, 59)
380
381 def test_multiline_sig(self):
382 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
383
Armin Rigodd5c0232005-09-25 11:45:45 +0000384 def test_nested_class(self):
385 self.assertSourceEqual(mod2.func69().func71, 71, 72)
386
387 def test_one_liner_followed_by_non_name(self):
388 self.assertSourceEqual(mod2.func77, 77, 77)
389
390 def test_one_liner_dedent_non_name(self):
391 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
392
393 def test_with_comment_instead_of_docstring(self):
394 self.assertSourceEqual(mod2.func88, 88, 90)
395
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000396 def test_method_in_dynamic_class(self):
397 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
398
R. David Murrayb5655772009-05-14 16:17:50 +0000399 @unittest.skipIf(
400 not hasattr(unicodedata, '__file__') or
401 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
402 "unicodedata is not an external binary module")
R. David Murray74b89242009-05-13 17:33:03 +0000403 def test_findsource_binary(self):
R. David Murrayb5655772009-05-14 16:17:50 +0000404 self.assertRaises(IOError, inspect.getsource, unicodedata)
405 self.assertRaises(IOError, inspect.findsource, unicodedata)
R. David Murray74b89242009-05-13 17:33:03 +0000406
R. David Murraya1b37402010-06-17 02:04:29 +0000407 def test_findsource_code_in_linecache(self):
408 lines = ["x=1"]
409 co = compile(lines[0], "_dynamically_created_file", "exec")
410 self.assertRaises(IOError, inspect.findsource, co)
411 self.assertRaises(IOError, inspect.getsource, co)
412 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Antoine Pitrou5d62a612012-07-08 13:48:46 +0200413 try:
414 self.assertEqual(inspect.findsource(co), (lines,0))
415 self.assertEqual(inspect.getsource(co), lines[0])
416 finally:
417 del linecache.cache[co.co_filename]
R. David Murraya1b37402010-06-17 02:04:29 +0000418
Ezio Melotti1b145922013-03-30 05:17:24 +0200419 def test_findsource_without_filename(self):
420 for fname in ['', '<string>']:
421 co = compile('x=1', fname, "exec")
422 self.assertRaises(IOError, inspect.findsource, co)
423 self.assertRaises(IOError, inspect.getsource, co)
424
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000425class TestNoEOL(GetSourceBase):
426 def __init__(self, *args, **kwargs):
427 self.tempdir = TESTFN + '_dir'
428 os.mkdir(self.tempdir)
429 with open(os.path.join(self.tempdir,
430 'inspect_fodder3%spy' % os.extsep), 'w') as f:
431 f.write("class X:\n pass # No EOL")
432 with DirsOnSysPath(self.tempdir):
433 import inspect_fodder3 as mod3
434 self.fodderModule = mod3
435 GetSourceBase.__init__(self, *args, **kwargs)
436
437 def tearDown(self):
438 shutil.rmtree(self.tempdir)
439
440 def test_class(self):
441 self.assertSourceEqual(self.fodderModule.X, 1, 2)
442
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100443
444class _BrokenDataDescriptor(object):
445 """
446 A broken data descriptor. See bug #1785.
447 """
448 def __get__(*args):
449 raise AssertionError("should not __get__ data descriptors")
450
451 def __set__(*args):
452 raise RuntimeError
453
454 def __getattr__(*args):
455 raise AssertionError("should not __getattr__ data descriptors")
456
457
458class _BrokenMethodDescriptor(object):
459 """
460 A broken method descriptor. See bug #1785.
461 """
462 def __get__(*args):
463 raise AssertionError("should not __get__ method descriptors")
464
465 def __getattr__(*args):
466 raise AssertionError("should not __getattr__ method descriptors")
467
468
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000469# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000470def attrs_wo_objs(cls):
471 return [t[:3] for t in inspect.classify_class_attrs(cls)]
472
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100473
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000474class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000475 def test_newstyle_mro(self):
476 # The same w/ new-class MRO.
477 class A(object): pass
478 class B(A): pass
479 class C(A): pass
480 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000481
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000482 expected = (D, B, C, A, object)
483 got = inspect.getmro(D)
484 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000485
Christian Heimes3795b532007-11-08 13:48:53 +0000486 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
487 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000488 args, varargs, varkw, defaults = inspect.getargspec(routine)
489 self.assertEqual(args, args_e)
490 self.assertEqual(varargs, varargs_e)
491 self.assertEqual(varkw, varkw_e)
492 self.assertEqual(defaults, defaults_e)
493 if formatted is not None:
494 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
495 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000496
Christian Heimes3795b532007-11-08 13:48:53 +0000497 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
498 varkw_e=None, defaults_e=None,
499 kwonlyargs_e=[], kwonlydefaults_e=None,
500 ann_e={}, formatted=None):
501 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
502 inspect.getfullargspec(routine)
503 self.assertEqual(args, args_e)
504 self.assertEqual(varargs, varargs_e)
505 self.assertEqual(varkw, varkw_e)
506 self.assertEqual(defaults, defaults_e)
507 self.assertEqual(kwonlyargs, kwonlyargs_e)
508 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
509 self.assertEqual(ann, ann_e)
510 if formatted is not None:
511 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
512 kwonlyargs, kwonlydefaults, ann),
513 formatted)
514
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000515 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000516 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000517
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000518 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000519 ['a', 'b', 'c', 'd', 'e', 'f'],
520 'g', 'h', (3, 4, 5),
521 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000522
Christian Heimes3795b532007-11-08 13:48:53 +0000523 self.assertRaises(ValueError, self.assertArgSpecEquals,
524 mod2.keyworded, [])
525
526 self.assertRaises(ValueError, self.assertArgSpecEquals,
527 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000528 self.assertRaises(ValueError, self.assertArgSpecEquals,
529 mod2.keyword_only_arg, [])
530
Christian Heimes3795b532007-11-08 13:48:53 +0000531
532 def test_getfullargspec(self):
533 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
534 kwonlyargs_e=['arg2'],
535 kwonlydefaults_e={'arg2':1},
536 formatted='(*arg1, arg2=1)')
537
538 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000539 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000540 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000541 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
542 kwonlyargs_e=['arg'],
543 formatted='(*, arg)')
544
Christian Heimes3795b532007-11-08 13:48:53 +0000545
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000546 def test_getargspec_method(self):
547 class A(object):
548 def m(self):
549 pass
550 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000551
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000552 def test_classify_newstyle(self):
553 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000554
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000555 def s(): pass
556 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000557
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000558 def c(cls): pass
559 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000560
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000561 def getp(self): pass
562 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000563
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000564 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000565
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000566 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000567
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000568 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000569
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100570 dd = _BrokenDataDescriptor()
571 md = _BrokenMethodDescriptor()
572
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000573 attrs = attrs_wo_objs(A)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000574 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
575 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
576 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000577 self.assertIn(('m', 'method', A), attrs,
578 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000579 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
580 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100581 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
582 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000583
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000584 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000585
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000586 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000587
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000588 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000589 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
590 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
591 self.assertIn(('p', 'property', A), attrs, 'missing property')
592 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
593 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
594 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100595 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
596 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000597
598
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000599 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000600
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000601 def m(self): pass
602 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000603
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000604 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000605 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
606 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
607 self.assertIn(('p', 'property', A), attrs, 'missing property')
608 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
609 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
610 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100611 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
612 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000613
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000614 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000615
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000616 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000617
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000618 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000619 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
620 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
621 self.assertIn(('p', 'property', A), attrs, 'missing property')
622 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
623 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
624 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100625 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
626 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
627
628 def test_classify_builtin_types(self):
629 # Simple sanity check that all built-in types can have their
630 # attributes classified.
631 for name in dir(__builtins__):
632 builtin = getattr(__builtins__, name)
633 if isinstance(builtin, type):
634 inspect.classify_class_attrs(builtin)
635
636 def test_getmembers_descriptors(self):
637 class A(object):
638 dd = _BrokenDataDescriptor()
639 md = _BrokenMethodDescriptor()
640
641 def pred_wrapper(pred):
642 # A quick'n'dirty way to discard standard attributes of new-style
643 # classes.
644 class Empty(object):
645 pass
646 def wrapped(x):
647 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
648 return False
649 return pred(x)
650 return wrapped
651
652 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
653 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
654
655 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
656 [('md', A.__dict__['md'])])
657 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
658 [('dd', A.__dict__['dd'])])
659
660 class B(A):
661 pass
662
663 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
664 [('md', A.__dict__['md'])])
665 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
666 [('dd', A.__dict__['dd'])])
667
Antoine Pitrou0c603812012-01-18 17:40:18 +0100668 def test_getmembers_method(self):
669 class B:
670 def f(self):
671 pass
672
673 self.assertIn(('f', B.f), inspect.getmembers(B))
674 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
675 b = B()
676 self.assertIn(('f', b.f), inspect.getmembers(b))
677 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
678
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000679
Nick Coghlan2f92e542012-06-23 19:39:55 +1000680_global_ref = object()
681class TestGetClosureVars(unittest.TestCase):
682
683 def test_name_resolution(self):
684 # Basic test of the 4 different resolution mechanisms
685 def f(nonlocal_ref):
686 def g(local_ref):
687 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
688 return g
689 _arg = object()
690 nonlocal_vars = {"nonlocal_ref": _arg}
691 global_vars = {"_global_ref": _global_ref}
692 builtin_vars = {"print": print}
693 unbound_names = {"unbound_ref"}
694 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
695 builtin_vars, unbound_names)
696 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
697
698 def test_generator_closure(self):
699 def f(nonlocal_ref):
700 def g(local_ref):
701 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
702 yield
703 return g
704 _arg = object()
705 nonlocal_vars = {"nonlocal_ref": _arg}
706 global_vars = {"_global_ref": _global_ref}
707 builtin_vars = {"print": print}
708 unbound_names = {"unbound_ref"}
709 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
710 builtin_vars, unbound_names)
711 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
712
713 def test_method_closure(self):
714 class C:
715 def f(self, nonlocal_ref):
716 def g(local_ref):
717 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
718 return g
719 _arg = object()
720 nonlocal_vars = {"nonlocal_ref": _arg}
721 global_vars = {"_global_ref": _global_ref}
722 builtin_vars = {"print": print}
723 unbound_names = {"unbound_ref"}
724 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
725 builtin_vars, unbound_names)
726 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
727
728 def test_nonlocal_vars(self):
729 # More complex tests of nonlocal resolution
730 def _nonlocal_vars(f):
731 return inspect.getclosurevars(f).nonlocals
732
733 def make_adder(x):
734 def add(y):
735 return x + y
736 return add
737
738 def curry(func, arg1):
739 return lambda arg2: func(arg1, arg2)
740
741 def less_than(a, b):
742 return a < b
743
744 # The infamous Y combinator.
745 def Y(le):
746 def g(f):
747 return le(lambda x: f(f)(x))
748 Y.g_ref = g
749 return g(g)
750
751 def check_y_combinator(func):
752 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
753
754 inc = make_adder(1)
755 add_two = make_adder(2)
756 greater_than_five = curry(less_than, 5)
757
758 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
759 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
760 self.assertEqual(_nonlocal_vars(greater_than_five),
761 {'arg1': 5, 'func': less_than})
762 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
763 {'x': 3})
764 Y(check_y_combinator)
765
766 def test_getclosurevars_empty(self):
767 def foo(): pass
768 _empty = inspect.ClosureVars({}, {}, {}, set())
769 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
770 self.assertEqual(inspect.getclosurevars(foo), _empty)
771
772 def test_getclosurevars_error(self):
773 class T: pass
774 self.assertRaises(TypeError, inspect.getclosurevars, 1)
775 self.assertRaises(TypeError, inspect.getclosurevars, list)
776 self.assertRaises(TypeError, inspect.getclosurevars, {})
777
Nick Coghlan6c6e2542012-06-23 20:07:39 +1000778 def _private_globals(self):
779 code = """def f(): print(path)"""
780 ns = {}
781 exec(code, ns)
782 return ns["f"], ns
783
784 def test_builtins_fallback(self):
785 f, ns = self._private_globals()
786 ns.pop("__builtins__", None)
787 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
788 self.assertEqual(inspect.getclosurevars(f), expected)
789
790 def test_builtins_as_dict(self):
791 f, ns = self._private_globals()
792 ns["__builtins__"] = {"path":1}
793 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
794 self.assertEqual(inspect.getclosurevars(f), expected)
795
796 def test_builtins_as_module(self):
797 f, ns = self._private_globals()
798 ns["__builtins__"] = os
799 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
800 self.assertEqual(inspect.getclosurevars(f), expected)
801
Nick Coghlan2f92e542012-06-23 19:39:55 +1000802
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000803class TestGetcallargsFunctions(unittest.TestCase):
804
805 def assertEqualCallArgs(self, func, call_params_string, locs=None):
806 locs = dict(locs or {}, func=func)
807 r1 = eval('func(%s)' % call_params_string, None, locs)
808 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
809 locs)
810 self.assertEqual(r1, r2)
811
812 def assertEqualException(self, func, call_param_string, locs=None):
813 locs = dict(locs or {}, func=func)
814 try:
815 eval('func(%s)' % call_param_string, None, locs)
816 except Exception as e:
817 ex1 = e
818 else:
819 self.fail('Exception not raised')
820 try:
821 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
822 locs)
823 except Exception as e:
824 ex2 = e
825 else:
826 self.fail('Exception not raised')
827 self.assertIs(type(ex1), type(ex2))
828 self.assertEqual(str(ex1), str(ex2))
829 del ex1, ex2
830
831 def makeCallable(self, signature):
832 """Create a function that returns its locals()"""
833 code = "lambda %s: locals()"
834 return eval(code % signature)
835
836 def test_plain(self):
837 f = self.makeCallable('a, b=1')
838 self.assertEqualCallArgs(f, '2')
839 self.assertEqualCallArgs(f, '2, 3')
840 self.assertEqualCallArgs(f, 'a=2')
841 self.assertEqualCallArgs(f, 'b=3, a=2')
842 self.assertEqualCallArgs(f, '2, b=3')
843 # expand *iterable / **mapping
844 self.assertEqualCallArgs(f, '*(2,)')
845 self.assertEqualCallArgs(f, '*[2]')
846 self.assertEqualCallArgs(f, '*(2, 3)')
847 self.assertEqualCallArgs(f, '*[2, 3]')
848 self.assertEqualCallArgs(f, '**{"a":2}')
849 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
850 self.assertEqualCallArgs(f, '2, **{"b":3}')
851 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
852 # expand UserList / UserDict
853 self.assertEqualCallArgs(f, '*collections.UserList([2])')
854 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
855 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
856 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
857 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
858
859 def test_varargs(self):
860 f = self.makeCallable('a, b=1, *c')
861 self.assertEqualCallArgs(f, '2')
862 self.assertEqualCallArgs(f, '2, 3')
863 self.assertEqualCallArgs(f, '2, 3, 4')
864 self.assertEqualCallArgs(f, '*(2,3,4)')
865 self.assertEqualCallArgs(f, '2, *[3,4]')
866 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
867
868 def test_varkw(self):
869 f = self.makeCallable('a, b=1, **c')
870 self.assertEqualCallArgs(f, 'a=2')
871 self.assertEqualCallArgs(f, '2, b=3, c=4')
872 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
873 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
874 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
875 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
876 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
877 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
878 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
879
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500880 def test_varkw_only(self):
881 # issue11256:
882 f = self.makeCallable('**c')
883 self.assertEqualCallArgs(f, '')
884 self.assertEqualCallArgs(f, 'a=1')
885 self.assertEqualCallArgs(f, 'a=1, b=2')
886 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
887 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
888 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
889
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000890 def test_keyword_only(self):
891 f = self.makeCallable('a=3, *, c, d=2')
892 self.assertEqualCallArgs(f, 'c=3')
893 self.assertEqualCallArgs(f, 'c=3, a=3')
894 self.assertEqualCallArgs(f, 'a=2, c=4')
895 self.assertEqualCallArgs(f, '4, c=4')
896 self.assertEqualException(f, '')
897 self.assertEqualException(f, '3')
898 self.assertEqualException(f, 'a=3')
899 self.assertEqualException(f, 'd=4')
900
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500901 f = self.makeCallable('*, c, d=2')
902 self.assertEqualCallArgs(f, 'c=3')
903 self.assertEqualCallArgs(f, 'c=3, d=4')
904 self.assertEqualCallArgs(f, 'd=4, c=3')
905
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000906 def test_multiple_features(self):
907 f = self.makeCallable('a, b=2, *f, **g')
908 self.assertEqualCallArgs(f, '2, 3, 7')
909 self.assertEqualCallArgs(f, '2, 3, x=8')
910 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
911 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
912 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
913 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
914 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
915 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
916 '(4,[5,6])]), **collections.UserDict('
917 'y=9, z=10)')
918
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500919 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
920 self.assertEqualCallArgs(f, '2, 3, x=8')
921 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
922 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
923 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
924 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
925 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
926 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
927 '(4,[5,6])]), q=0, **collections.UserDict('
928 'y=9, z=10)')
929
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000930 def test_errors(self):
931 f0 = self.makeCallable('')
932 f1 = self.makeCallable('a, b')
933 f2 = self.makeCallable('a, b=1')
934 # f0 takes no arguments
935 self.assertEqualException(f0, '1')
936 self.assertEqualException(f0, 'x=1')
937 self.assertEqualException(f0, '1,x=1')
938 # f1 takes exactly 2 arguments
939 self.assertEqualException(f1, '')
940 self.assertEqualException(f1, '1')
941 self.assertEqualException(f1, 'a=2')
942 self.assertEqualException(f1, 'b=3')
943 # f2 takes at least 1 argument
944 self.assertEqualException(f2, '')
945 self.assertEqualException(f2, 'b=3')
946 for f in f1, f2:
947 # f1/f2 takes exactly/at most 2 arguments
948 self.assertEqualException(f, '2, 3, 4')
949 self.assertEqualException(f, '1, 2, 3, a=1')
950 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +0100951 # XXX: success of this one depends on dict order
952 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000953 # f got an unexpected keyword argument
954 self.assertEqualException(f, 'c=2')
955 self.assertEqualException(f, '2, c=3')
956 self.assertEqualException(f, '2, 3, c=4')
957 self.assertEqualException(f, '2, c=4, b=3')
958 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
959 # f got multiple values for keyword argument
960 self.assertEqualException(f, '1, a=2')
961 self.assertEqualException(f, '1, **{"a":2}')
962 self.assertEqualException(f, '1, 2, b=3')
963 # XXX: Python inconsistency
964 # - for functions and bound methods: unexpected keyword 'c'
965 # - for unbound methods: multiple values for keyword 'a'
966 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500967 # issue11256:
968 f3 = self.makeCallable('**c')
969 self.assertEqualException(f3, '1, 2')
970 self.assertEqualException(f3, '1, 2, a=1, b=2')
971 f4 = self.makeCallable('*, a, b=0')
972 self.assertEqualException(f3, '1, 2')
973 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000974
975class TestGetcallargsMethods(TestGetcallargsFunctions):
976
977 def setUp(self):
978 class Foo(object):
979 pass
980 self.cls = Foo
981 self.inst = Foo()
982
983 def makeCallable(self, signature):
984 assert 'self' not in signature
985 mk = super(TestGetcallargsMethods, self).makeCallable
986 self.cls.method = mk('self, ' + signature)
987 return self.inst.method
988
989class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
990
991 def makeCallable(self, signature):
992 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
993 return self.cls.method
994
995 def assertEqualCallArgs(self, func, call_params_string, locs=None):
996 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
997 *self._getAssertEqualParams(func, call_params_string, locs))
998
999 def assertEqualException(self, func, call_params_string, locs=None):
1000 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
1001 *self._getAssertEqualParams(func, call_params_string, locs))
1002
1003 def _getAssertEqualParams(self, func, call_params_string, locs=None):
1004 assert 'inst' not in call_params_string
1005 locs = dict(locs or {}, inst=self.inst)
1006 return (func, 'inst,' + call_params_string, locs)
1007
Michael Foord95fc51d2010-11-20 15:07:30 +00001008
1009class TestGetattrStatic(unittest.TestCase):
1010
1011 def test_basic(self):
1012 class Thing(object):
1013 x = object()
1014
1015 thing = Thing()
1016 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1017 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1018 with self.assertRaises(AttributeError):
1019 inspect.getattr_static(thing, 'y')
1020
1021 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1022
1023 def test_inherited(self):
1024 class Thing(object):
1025 x = object()
1026 class OtherThing(Thing):
1027 pass
1028
1029 something = OtherThing()
1030 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1031
1032 def test_instance_attr(self):
1033 class Thing(object):
1034 x = 2
1035 def __init__(self, x):
1036 self.x = x
1037 thing = Thing(3)
1038 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1039 del thing.x
1040 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1041
1042 def test_property(self):
1043 class Thing(object):
1044 @property
1045 def x(self):
1046 raise AttributeError("I'm pretending not to exist")
1047 thing = Thing()
1048 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1049
Ezio Melotti75cbd732011-04-28 00:59:29 +03001050 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001051 class descriptor(object):
1052 def __get__(*_):
1053 raise AttributeError("I'm pretending not to exist")
1054 desc = descriptor()
1055 class Thing(object):
1056 x = desc
1057 thing = Thing()
1058 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1059
1060 def test_classAttribute(self):
1061 class Thing(object):
1062 x = object()
1063
1064 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1065
1066 def test_inherited_classattribute(self):
1067 class Thing(object):
1068 x = object()
1069 class OtherThing(Thing):
1070 pass
1071
1072 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1073
1074 def test_slots(self):
1075 class Thing(object):
1076 y = 'bar'
1077 __slots__ = ['x']
1078 def __init__(self):
1079 self.x = 'foo'
1080 thing = Thing()
1081 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1082 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1083
1084 del thing.x
1085 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1086
1087 def test_metaclass(self):
1088 class meta(type):
1089 attr = 'foo'
1090 class Thing(object, metaclass=meta):
1091 pass
1092 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1093
1094 class sub(meta):
1095 pass
1096 class OtherThing(object, metaclass=sub):
1097 x = 3
1098 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1099
1100 class OtherOtherThing(OtherThing):
1101 pass
1102 # this test is odd, but it was added as it exposed a bug
1103 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1104
1105 def test_no_dict_no_slots(self):
1106 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1107 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1108
1109 def test_no_dict_no_slots_instance_member(self):
1110 # returns descriptor
1111 with open(__file__) as handle:
1112 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1113
1114 def test_inherited_slots(self):
1115 # returns descriptor
1116 class Thing(object):
1117 __slots__ = ['x']
1118 def __init__(self):
1119 self.x = 'foo'
1120
1121 class OtherThing(Thing):
1122 pass
1123 # it would be nice if this worked...
1124 # we get the descriptor instead of the instance attribute
1125 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1126
1127 def test_descriptor(self):
1128 class descriptor(object):
1129 def __get__(self, instance, owner):
1130 return 3
1131 class Foo(object):
1132 d = descriptor()
1133
1134 foo = Foo()
1135
1136 # for a non data descriptor we return the instance attribute
1137 foo.__dict__['d'] = 1
1138 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1139
1140 # if the descriptor is a data-desciptor we should return the
1141 # descriptor
1142 descriptor.__set__ = lambda s, i, v: None
1143 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1144
1145
1146 def test_metaclass_with_descriptor(self):
1147 class descriptor(object):
1148 def __get__(self, instance, owner):
1149 return 3
1150 class meta(type):
1151 d = descriptor()
1152 class Thing(object, metaclass=meta):
1153 pass
1154 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1155
1156
Michael Foordcc7ebb82010-11-20 16:20:16 +00001157 def test_class_as_property(self):
1158 class Base(object):
1159 foo = 3
1160
1161 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001162 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001163 @property
1164 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001165 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001166 return object
1167
Michael Foord35184ed2010-11-20 16:58:30 +00001168 instance = Something()
1169 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1170 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001171 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1172
Michael Foorde5162652010-11-20 16:40:44 +00001173 def test_mro_as_property(self):
1174 class Meta(type):
1175 @property
1176 def __mro__(self):
1177 return (object,)
1178
1179 class Base(object):
1180 foo = 3
1181
1182 class Something(Base, metaclass=Meta):
1183 pass
1184
1185 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1186 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1187
Michael Foorddcebe0f2011-03-15 19:20:44 -04001188 def test_dict_as_property(self):
1189 test = self
1190 test.called = False
1191
1192 class Foo(dict):
1193 a = 3
1194 @property
1195 def __dict__(self):
1196 test.called = True
1197 return {}
1198
1199 foo = Foo()
1200 foo.a = 4
1201 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1202 self.assertFalse(test.called)
1203
1204 def test_custom_object_dict(self):
1205 test = self
1206 test.called = False
1207
1208 class Custom(dict):
1209 def get(self, key, default=None):
1210 test.called = True
1211 super().get(key, default)
1212
1213 class Foo(object):
1214 a = 3
1215 foo = Foo()
1216 foo.__dict__ = Custom()
1217 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1218 self.assertFalse(test.called)
1219
1220 def test_metaclass_dict_as_property(self):
1221 class Meta(type):
1222 @property
1223 def __dict__(self):
1224 self.executed = True
1225
1226 class Thing(metaclass=Meta):
1227 executed = False
1228
1229 def __init__(self):
1230 self.spam = 42
1231
1232 instance = Thing()
1233 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1234 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001235
Michael Foorda51623b2011-12-18 22:01:40 +00001236 def test_module(self):
1237 sentinel = object()
1238 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1239 sentinel)
1240
Michael Foord3ba95f82011-12-22 01:13:37 +00001241 def test_metaclass_with_metaclass_with_dict_as_property(self):
1242 class MetaMeta(type):
1243 @property
1244 def __dict__(self):
1245 self.executed = True
1246 return dict(spam=42)
1247
1248 class Meta(type, metaclass=MetaMeta):
1249 executed = False
1250
1251 class Thing(metaclass=Meta):
1252 pass
1253
1254 with self.assertRaises(AttributeError):
1255 inspect.getattr_static(Thing, "spam")
1256 self.assertFalse(Thing.executed)
1257
Nick Coghlane0f04652010-11-21 03:44:04 +00001258class TestGetGeneratorState(unittest.TestCase):
1259
1260 def setUp(self):
1261 def number_generator():
1262 for number in range(5):
1263 yield number
1264 self.generator = number_generator()
1265
1266 def _generatorstate(self):
1267 return inspect.getgeneratorstate(self.generator)
1268
1269 def test_created(self):
1270 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1271
1272 def test_suspended(self):
1273 next(self.generator)
1274 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1275
1276 def test_closed_after_exhaustion(self):
1277 for i in self.generator:
1278 pass
1279 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1280
1281 def test_closed_after_immediate_exception(self):
1282 with self.assertRaises(RuntimeError):
1283 self.generator.throw(RuntimeError)
1284 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1285
1286 def test_running(self):
1287 # As mentioned on issue #10220, checking for the RUNNING state only
1288 # makes sense inside the generator itself.
1289 # The following generator checks for this by using the closure's
1290 # reference to self and the generator state checking helper method
1291 def running_check_generator():
1292 for number in range(5):
1293 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1294 yield number
1295 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1296 self.generator = running_check_generator()
1297 # Running up to the first yield
1298 next(self.generator)
1299 # Running after the first yield
1300 next(self.generator)
1301
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001302 def test_easy_debugging(self):
1303 # repr() and str() of a generator state should contain the state name
1304 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1305 for name in names:
1306 state = getattr(inspect, name)
1307 self.assertIn(name, repr(state))
1308 self.assertIn(name, str(state))
1309
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001310 def test_getgeneratorlocals(self):
1311 def each(lst, a=None):
1312 b=(1, 2, 3)
1313 for v in lst:
1314 if v == 3:
1315 c = 12
1316 yield v
1317
1318 numbers = each([1, 2, 3])
1319 self.assertEqual(inspect.getgeneratorlocals(numbers),
1320 {'a': None, 'lst': [1, 2, 3]})
1321 next(numbers)
1322 self.assertEqual(inspect.getgeneratorlocals(numbers),
1323 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1324 'b': (1, 2, 3)})
1325 next(numbers)
1326 self.assertEqual(inspect.getgeneratorlocals(numbers),
1327 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1328 'b': (1, 2, 3)})
1329 next(numbers)
1330 self.assertEqual(inspect.getgeneratorlocals(numbers),
1331 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1332 'b': (1, 2, 3), 'c': 12})
1333 try:
1334 next(numbers)
1335 except StopIteration:
1336 pass
1337 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1338
1339 def test_getgeneratorlocals_empty(self):
1340 def yield_one():
1341 yield 1
1342 one = yield_one()
1343 self.assertEqual(inspect.getgeneratorlocals(one), {})
1344 try:
1345 next(one)
1346 except StopIteration:
1347 pass
1348 self.assertEqual(inspect.getgeneratorlocals(one), {})
1349
1350 def test_getgeneratorlocals_error(self):
1351 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1352 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1353 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1354 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1355
Nick Coghlane0f04652010-11-21 03:44:04 +00001356
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001357class TestSignatureObject(unittest.TestCase):
1358 @staticmethod
1359 def signature(func):
1360 sig = inspect.signature(func)
1361 return (tuple((param.name,
1362 (... if param.default is param.empty else param.default),
1363 (... if param.annotation is param.empty
1364 else param.annotation),
1365 str(param.kind).lower())
1366 for param in sig.parameters.values()),
1367 (... if sig.return_annotation is sig.empty
1368 else sig.return_annotation))
1369
1370 def test_signature_object(self):
1371 S = inspect.Signature
1372 P = inspect.Parameter
1373
1374 self.assertEqual(str(S()), '()')
1375
1376 def test(po, pk, *args, ko, **kwargs):
1377 pass
1378 sig = inspect.signature(test)
1379 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
1380 pk = sig.parameters['pk']
1381 args = sig.parameters['args']
1382 ko = sig.parameters['ko']
1383 kwargs = sig.parameters['kwargs']
1384
1385 S((po, pk, args, ko, kwargs))
1386
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001387 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001388 S((pk, po, args, ko, kwargs))
1389
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001390 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001391 S((po, args, pk, ko, kwargs))
1392
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001393 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001394 S((args, po, pk, ko, kwargs))
1395
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001396 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001397 S((po, pk, args, kwargs, ko))
1398
1399 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001400 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001401 S((po, pk, args, kwargs2, ko))
1402
1403 def test_signature_immutability(self):
1404 def test(a):
1405 pass
1406 sig = inspect.signature(test)
1407
1408 with self.assertRaises(AttributeError):
1409 sig.foo = 'bar'
1410
1411 with self.assertRaises(TypeError):
1412 sig.parameters['a'] = None
1413
1414 def test_signature_on_noarg(self):
1415 def test():
1416 pass
1417 self.assertEqual(self.signature(test), ((), ...))
1418
1419 def test_signature_on_wargs(self):
1420 def test(a, b:'foo') -> 123:
1421 pass
1422 self.assertEqual(self.signature(test),
1423 ((('a', ..., ..., "positional_or_keyword"),
1424 ('b', ..., 'foo', "positional_or_keyword")),
1425 123))
1426
1427 def test_signature_on_wkwonly(self):
1428 def test(*, a:float, b:str) -> int:
1429 pass
1430 self.assertEqual(self.signature(test),
1431 ((('a', ..., float, "keyword_only"),
1432 ('b', ..., str, "keyword_only")),
1433 int))
1434
1435 def test_signature_on_complex_args(self):
1436 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1437 pass
1438 self.assertEqual(self.signature(test),
1439 ((('a', ..., ..., "positional_or_keyword"),
1440 ('b', 10, 'foo', "positional_or_keyword"),
1441 ('args', ..., 'bar', "var_positional"),
1442 ('spam', ..., 'baz', "keyword_only"),
1443 ('ham', 123, ..., "keyword_only"),
1444 ('kwargs', ..., int, "var_keyword")),
1445 ...))
1446
1447 def test_signature_on_builtin_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001448 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001449 inspect.signature(type)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001450 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001451 # support for 'wrapper_descriptor'
1452 inspect.signature(type.__call__)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001453 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001454 # support for 'method-wrapper'
1455 inspect.signature(min.__call__)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001456 with self.assertRaisesRegex(ValueError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001457 'no signature found for builtin function'):
1458 # support for 'method-wrapper'
1459 inspect.signature(min)
1460
1461 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001462 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001463 inspect.signature(42)
1464
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001465 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001466 inspect.Signature.from_function(42)
1467
1468 def test_signature_on_method(self):
1469 class Test:
1470 def foo(self, arg1, arg2=1) -> int:
1471 pass
1472
1473 meth = Test().foo
1474
1475 self.assertEqual(self.signature(meth),
1476 ((('arg1', ..., ..., "positional_or_keyword"),
1477 ('arg2', 1, ..., "positional_or_keyword")),
1478 int))
1479
1480 def test_signature_on_classmethod(self):
1481 class Test:
1482 @classmethod
1483 def foo(cls, arg1, *, arg2=1):
1484 pass
1485
1486 meth = Test().foo
1487 self.assertEqual(self.signature(meth),
1488 ((('arg1', ..., ..., "positional_or_keyword"),
1489 ('arg2', 1, ..., "keyword_only")),
1490 ...))
1491
1492 meth = Test.foo
1493 self.assertEqual(self.signature(meth),
1494 ((('arg1', ..., ..., "positional_or_keyword"),
1495 ('arg2', 1, ..., "keyword_only")),
1496 ...))
1497
1498 def test_signature_on_staticmethod(self):
1499 class Test:
1500 @staticmethod
1501 def foo(cls, *, arg):
1502 pass
1503
1504 meth = Test().foo
1505 self.assertEqual(self.signature(meth),
1506 ((('cls', ..., ..., "positional_or_keyword"),
1507 ('arg', ..., ..., "keyword_only")),
1508 ...))
1509
1510 meth = Test.foo
1511 self.assertEqual(self.signature(meth),
1512 ((('cls', ..., ..., "positional_or_keyword"),
1513 ('arg', ..., ..., "keyword_only")),
1514 ...))
1515
1516 def test_signature_on_partial(self):
1517 from functools import partial
1518
1519 def test():
1520 pass
1521
1522 self.assertEqual(self.signature(partial(test)), ((), ...))
1523
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001524 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001525 inspect.signature(partial(test, 1))
1526
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001527 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001528 inspect.signature(partial(test, a=1))
1529
1530 def test(a, b, *, c, d):
1531 pass
1532
1533 self.assertEqual(self.signature(partial(test)),
1534 ((('a', ..., ..., "positional_or_keyword"),
1535 ('b', ..., ..., "positional_or_keyword"),
1536 ('c', ..., ..., "keyword_only"),
1537 ('d', ..., ..., "keyword_only")),
1538 ...))
1539
1540 self.assertEqual(self.signature(partial(test, 1)),
1541 ((('b', ..., ..., "positional_or_keyword"),
1542 ('c', ..., ..., "keyword_only"),
1543 ('d', ..., ..., "keyword_only")),
1544 ...))
1545
1546 self.assertEqual(self.signature(partial(test, 1, c=2)),
1547 ((('b', ..., ..., "positional_or_keyword"),
1548 ('c', 2, ..., "keyword_only"),
1549 ('d', ..., ..., "keyword_only")),
1550 ...))
1551
1552 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1553 ((('a', ..., ..., "positional_or_keyword"),
1554 ('b', 1, ..., "positional_or_keyword"),
1555 ('c', 2, ..., "keyword_only"),
1556 ('d', ..., ..., "keyword_only")),
1557 ...))
1558
1559 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
1560 ((('b', 1, ..., "positional_or_keyword"),
1561 ('c', 2, ..., "keyword_only"),
1562 ('d', ..., ..., "keyword_only"),),
1563 ...))
1564
1565 def test(a, *args, b, **kwargs):
1566 pass
1567
1568 self.assertEqual(self.signature(partial(test, 1)),
1569 ((('args', ..., ..., "var_positional"),
1570 ('b', ..., ..., "keyword_only"),
1571 ('kwargs', ..., ..., "var_keyword")),
1572 ...))
1573
1574 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
1575 ((('args', ..., ..., "var_positional"),
1576 ('b', ..., ..., "keyword_only"),
1577 ('kwargs', ..., ..., "var_keyword")),
1578 ...))
1579
1580
1581 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
1582 ((('args', ..., ..., "var_positional"),
1583 ('b', ..., ..., "keyword_only"),
1584 ('kwargs', ..., ..., "var_keyword")),
1585 ...))
1586
1587 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
1588 ((('args', ..., ..., "var_positional"),
1589 ('b', 0, ..., "keyword_only"),
1590 ('kwargs', ..., ..., "var_keyword")),
1591 ...))
1592
1593 self.assertEqual(self.signature(partial(test, b=0)),
1594 ((('a', ..., ..., "positional_or_keyword"),
1595 ('args', ..., ..., "var_positional"),
1596 ('b', 0, ..., "keyword_only"),
1597 ('kwargs', ..., ..., "var_keyword")),
1598 ...))
1599
1600 self.assertEqual(self.signature(partial(test, b=0, test=1)),
1601 ((('a', ..., ..., "positional_or_keyword"),
1602 ('args', ..., ..., "var_positional"),
1603 ('b', 0, ..., "keyword_only"),
1604 ('kwargs', ..., ..., "var_keyword")),
1605 ...))
1606
1607 def test(a, b, c:int) -> 42:
1608 pass
1609
1610 sig = test.__signature__ = inspect.signature(test)
1611
1612 self.assertEqual(self.signature(partial(partial(test, 1))),
1613 ((('b', ..., ..., "positional_or_keyword"),
1614 ('c', ..., int, "positional_or_keyword")),
1615 42))
1616
1617 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
1618 ((('c', ..., int, "positional_or_keyword"),),
1619 42))
1620
1621 psig = inspect.signature(partial(partial(test, 1), 2))
1622
1623 def foo(a):
1624 return a
1625 _foo = partial(partial(foo, a=10), a=20)
1626 self.assertEqual(self.signature(_foo),
1627 ((('a', 20, ..., "positional_or_keyword"),),
1628 ...))
1629 # check that we don't have any side-effects in signature(),
1630 # and the partial object is still functioning
1631 self.assertEqual(_foo(), 20)
1632
1633 def foo(a, b, c):
1634 return a, b, c
1635 _foo = partial(partial(foo, 1, b=20), b=30)
1636 self.assertEqual(self.signature(_foo),
1637 ((('b', 30, ..., "positional_or_keyword"),
1638 ('c', ..., ..., "positional_or_keyword")),
1639 ...))
1640 self.assertEqual(_foo(c=10), (1, 30, 10))
1641 _foo = partial(_foo, 2) # now 'b' has two values -
1642 # positional and keyword
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001643 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001644 inspect.signature(_foo)
1645
1646 def foo(a, b, c, *, d):
1647 return a, b, c, d
1648 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
1649 self.assertEqual(self.signature(_foo),
1650 ((('a', ..., ..., "positional_or_keyword"),
1651 ('b', 10, ..., "positional_or_keyword"),
1652 ('c', 20, ..., "positional_or_keyword"),
1653 ('d', 30, ..., "keyword_only")),
1654 ...))
1655 ba = inspect.signature(_foo).bind(a=200, b=11)
1656 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
1657
1658 def foo(a=1, b=2, c=3):
1659 return a, b, c
1660 _foo = partial(foo, a=10, c=13)
1661 ba = inspect.signature(_foo).bind(11)
1662 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
1663 ba = inspect.signature(_foo).bind(11, 12)
1664 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1665 ba = inspect.signature(_foo).bind(11, b=12)
1666 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1667 ba = inspect.signature(_foo).bind(b=12)
1668 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
1669 _foo = partial(_foo, b=10)
1670 ba = inspect.signature(_foo).bind(12, 14)
1671 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
1672
1673 def test_signature_on_decorated(self):
1674 import functools
1675
1676 def decorator(func):
1677 @functools.wraps(func)
1678 def wrapper(*args, **kwargs) -> int:
1679 return func(*args, **kwargs)
1680 return wrapper
1681
1682 class Foo:
1683 @decorator
1684 def bar(self, a, b):
1685 pass
1686
1687 self.assertEqual(self.signature(Foo.bar),
1688 ((('self', ..., ..., "positional_or_keyword"),
1689 ('a', ..., ..., "positional_or_keyword"),
1690 ('b', ..., ..., "positional_or_keyword")),
1691 ...))
1692
1693 self.assertEqual(self.signature(Foo().bar),
1694 ((('a', ..., ..., "positional_or_keyword"),
1695 ('b', ..., ..., "positional_or_keyword")),
1696 ...))
1697
1698 # Test that we handle method wrappers correctly
1699 def decorator(func):
1700 @functools.wraps(func)
1701 def wrapper(*args, **kwargs) -> int:
1702 return func(42, *args, **kwargs)
1703 sig = inspect.signature(func)
1704 new_params = tuple(sig.parameters.values())[1:]
1705 wrapper.__signature__ = sig.replace(parameters=new_params)
1706 return wrapper
1707
1708 class Foo:
1709 @decorator
1710 def __call__(self, a, b):
1711 pass
1712
1713 self.assertEqual(self.signature(Foo.__call__),
1714 ((('a', ..., ..., "positional_or_keyword"),
1715 ('b', ..., ..., "positional_or_keyword")),
1716 ...))
1717
1718 self.assertEqual(self.signature(Foo().__call__),
1719 ((('b', ..., ..., "positional_or_keyword"),),
1720 ...))
1721
1722 def test_signature_on_class(self):
1723 class C:
1724 def __init__(self, a):
1725 pass
1726
1727 self.assertEqual(self.signature(C),
1728 ((('a', ..., ..., "positional_or_keyword"),),
1729 ...))
1730
1731 class CM(type):
1732 def __call__(cls, a):
1733 pass
1734 class C(metaclass=CM):
1735 def __init__(self, b):
1736 pass
1737
1738 self.assertEqual(self.signature(C),
1739 ((('a', ..., ..., "positional_or_keyword"),),
1740 ...))
1741
1742 class CM(type):
1743 def __new__(mcls, name, bases, dct, *, foo=1):
1744 return super().__new__(mcls, name, bases, dct)
1745 class C(metaclass=CM):
1746 def __init__(self, b):
1747 pass
1748
1749 self.assertEqual(self.signature(C),
1750 ((('b', ..., ..., "positional_or_keyword"),),
1751 ...))
1752
1753 self.assertEqual(self.signature(CM),
1754 ((('name', ..., ..., "positional_or_keyword"),
1755 ('bases', ..., ..., "positional_or_keyword"),
1756 ('dct', ..., ..., "positional_or_keyword"),
1757 ('foo', 1, ..., "keyword_only")),
1758 ...))
1759
1760 class CMM(type):
1761 def __new__(mcls, name, bases, dct, *, foo=1):
1762 return super().__new__(mcls, name, bases, dct)
1763 def __call__(cls, nm, bs, dt):
1764 return type(nm, bs, dt)
1765 class CM(type, metaclass=CMM):
1766 def __new__(mcls, name, bases, dct, *, bar=2):
1767 return super().__new__(mcls, name, bases, dct)
1768 class C(metaclass=CM):
1769 def __init__(self, b):
1770 pass
1771
1772 self.assertEqual(self.signature(CMM),
1773 ((('name', ..., ..., "positional_or_keyword"),
1774 ('bases', ..., ..., "positional_or_keyword"),
1775 ('dct', ..., ..., "positional_or_keyword"),
1776 ('foo', 1, ..., "keyword_only")),
1777 ...))
1778
1779 self.assertEqual(self.signature(CM),
1780 ((('nm', ..., ..., "positional_or_keyword"),
1781 ('bs', ..., ..., "positional_or_keyword"),
1782 ('dt', ..., ..., "positional_or_keyword")),
1783 ...))
1784
1785 self.assertEqual(self.signature(C),
1786 ((('b', ..., ..., "positional_or_keyword"),),
1787 ...))
1788
1789 class CM(type):
1790 def __init__(cls, name, bases, dct, *, bar=2):
1791 return super().__init__(name, bases, dct)
1792 class C(metaclass=CM):
1793 def __init__(self, b):
1794 pass
1795
1796 self.assertEqual(self.signature(CM),
1797 ((('name', ..., ..., "positional_or_keyword"),
1798 ('bases', ..., ..., "positional_or_keyword"),
1799 ('dct', ..., ..., "positional_or_keyword"),
1800 ('bar', 2, ..., "keyword_only")),
1801 ...))
1802
1803 def test_signature_on_callable_objects(self):
1804 class Foo:
1805 def __call__(self, a):
1806 pass
1807
1808 self.assertEqual(self.signature(Foo()),
1809 ((('a', ..., ..., "positional_or_keyword"),),
1810 ...))
1811
1812 class Spam:
1813 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001814 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001815 inspect.signature(Spam())
1816
1817 class Bar(Spam, Foo):
1818 pass
1819
1820 self.assertEqual(self.signature(Bar()),
1821 ((('a', ..., ..., "positional_or_keyword"),),
1822 ...))
1823
1824 class ToFail:
1825 __call__ = type
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001826 with self.assertRaisesRegex(ValueError, "not supported by signature"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001827 inspect.signature(ToFail())
1828
1829
1830 class Wrapped:
1831 pass
1832 Wrapped.__wrapped__ = lambda a: None
1833 self.assertEqual(self.signature(Wrapped),
1834 ((('a', ..., ..., "positional_or_keyword"),),
1835 ...))
1836
1837 def test_signature_on_lambdas(self):
1838 self.assertEqual(self.signature((lambda a=10: a)),
1839 ((('a', 10, ..., "positional_or_keyword"),),
1840 ...))
1841
1842 def test_signature_equality(self):
1843 def foo(a, *, b:int) -> float: pass
1844 self.assertNotEqual(inspect.signature(foo), 42)
1845
1846 def bar(a, *, b:int) -> float: pass
1847 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1848
1849 def bar(a, *, b:int) -> int: pass
1850 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1851
1852 def bar(a, *, b:int): pass
1853 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1854
1855 def bar(a, *, b:int=42) -> float: pass
1856 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1857
1858 def bar(a, *, c) -> float: pass
1859 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1860
1861 def bar(a, b:int) -> float: pass
1862 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1863 def spam(b:int, a) -> float: pass
1864 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
1865
1866 def foo(*, a, b, c): pass
1867 def bar(*, c, b, a): pass
1868 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1869
1870 def foo(*, a=1, b, c): pass
1871 def bar(*, c, b, a=1): pass
1872 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1873
1874 def foo(pos, *, a=1, b, c): pass
1875 def bar(pos, *, c, b, a=1): pass
1876 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1877
1878 def foo(pos, *, a, b, c): pass
1879 def bar(pos, *, c, b, a=1): pass
1880 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1881
1882 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
1883 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
1884 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1885
1886 def test_signature_unhashable(self):
1887 def foo(a): pass
1888 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001889 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001890 hash(sig)
1891
1892 def test_signature_str(self):
1893 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
1894 pass
1895 self.assertEqual(str(inspect.signature(foo)),
1896 '(a:int=1, *, b, c=None, **kwargs) -> 42')
1897
1898 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
1899 pass
1900 self.assertEqual(str(inspect.signature(foo)),
1901 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
1902
1903 def foo():
1904 pass
1905 self.assertEqual(str(inspect.signature(foo)), '()')
1906
1907 def test_signature_str_positional_only(self):
1908 P = inspect.Parameter
1909
1910 def test(a_po, *, b, **kwargs):
1911 return a_po, kwargs
1912
1913 sig = inspect.signature(test)
1914 new_params = list(sig.parameters.values())
1915 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
1916 test.__signature__ = sig.replace(parameters=new_params)
1917
1918 self.assertEqual(str(inspect.signature(test)),
1919 '(<a_po>, *, b, **kwargs)')
1920
1921 sig = inspect.signature(test)
1922 new_params = list(sig.parameters.values())
1923 new_params[0] = new_params[0].replace(name=None)
1924 test.__signature__ = sig.replace(parameters=new_params)
1925 self.assertEqual(str(inspect.signature(test)),
1926 '(<0>, *, b, **kwargs)')
1927
1928 def test_signature_replace_anno(self):
1929 def test() -> 42:
1930 pass
1931
1932 sig = inspect.signature(test)
1933 sig = sig.replace(return_annotation=None)
1934 self.assertIs(sig.return_annotation, None)
1935 sig = sig.replace(return_annotation=sig.empty)
1936 self.assertIs(sig.return_annotation, sig.empty)
1937 sig = sig.replace(return_annotation=42)
1938 self.assertEqual(sig.return_annotation, 42)
1939 self.assertEqual(sig, inspect.signature(test))
1940
1941
1942class TestParameterObject(unittest.TestCase):
1943 def test_signature_parameter_kinds(self):
1944 P = inspect.Parameter
1945 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
1946 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
1947
1948 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
1949 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
1950
1951 def test_signature_parameter_object(self):
1952 p = inspect.Parameter('foo', default=10,
1953 kind=inspect.Parameter.POSITIONAL_ONLY)
1954 self.assertEqual(p.name, 'foo')
1955 self.assertEqual(p.default, 10)
1956 self.assertIs(p.annotation, p.empty)
1957 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
1958
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001959 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001960 inspect.Parameter('foo', default=10, kind='123')
1961
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001962 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001963 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
1964
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001965 with self.assertRaisesRegex(ValueError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001966 'non-positional-only parameter'):
1967 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
1968
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001969 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001970 inspect.Parameter('a', default=42,
1971 kind=inspect.Parameter.VAR_KEYWORD)
1972
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001973 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001974 inspect.Parameter('a', default=42,
1975 kind=inspect.Parameter.VAR_POSITIONAL)
1976
1977 p = inspect.Parameter('a', default=42,
1978 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001979 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001980 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
1981
1982 self.assertTrue(repr(p).startswith('<Parameter'))
1983
1984 def test_signature_parameter_equality(self):
1985 P = inspect.Parameter
1986 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
1987
1988 self.assertEqual(p, p)
1989 self.assertNotEqual(p, 42)
1990
1991 self.assertEqual(p, P('foo', default=42,
1992 kind=inspect.Parameter.KEYWORD_ONLY))
1993
1994 def test_signature_parameter_unhashable(self):
1995 p = inspect.Parameter('foo', default=42,
1996 kind=inspect.Parameter.KEYWORD_ONLY)
1997
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001998 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001999 hash(p)
2000
2001 def test_signature_parameter_replace(self):
2002 p = inspect.Parameter('foo', default=42,
2003 kind=inspect.Parameter.KEYWORD_ONLY)
2004
2005 self.assertIsNot(p, p.replace())
2006 self.assertEqual(p, p.replace())
2007
2008 p2 = p.replace(annotation=1)
2009 self.assertEqual(p2.annotation, 1)
2010 p2 = p2.replace(annotation=p2.empty)
2011 self.assertEqual(p, p2)
2012
2013 p2 = p2.replace(name='bar')
2014 self.assertEqual(p2.name, 'bar')
2015 self.assertNotEqual(p2, p)
2016
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002017 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002018 p2 = p2.replace(name=p2.empty)
2019
2020 p2 = p2.replace(name='foo', default=None)
2021 self.assertIs(p2.default, None)
2022 self.assertNotEqual(p2, p)
2023
2024 p2 = p2.replace(name='foo', default=p2.empty)
2025 self.assertIs(p2.default, p2.empty)
2026
2027
2028 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2029 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2030 self.assertNotEqual(p2, p)
2031
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002032 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002033 p2 = p2.replace(kind=p2.empty)
2034
2035 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2036 self.assertEqual(p2, p)
2037
2038 def test_signature_parameter_positional_only(self):
2039 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2040 self.assertEqual(str(p), '<>')
2041
2042 p = p.replace(name='1')
2043 self.assertEqual(str(p), '<1>')
2044
2045 def test_signature_parameter_immutability(self):
2046 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2047
2048 with self.assertRaises(AttributeError):
2049 p.foo = 'bar'
2050
2051 with self.assertRaises(AttributeError):
2052 p.kind = 123
2053
2054
2055class TestSignatureBind(unittest.TestCase):
2056 @staticmethod
2057 def call(func, *args, **kwargs):
2058 sig = inspect.signature(func)
2059 ba = sig.bind(*args, **kwargs)
2060 return func(*ba.args, **ba.kwargs)
2061
2062 def test_signature_bind_empty(self):
2063 def test():
2064 return 42
2065
2066 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002067 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002068 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002069 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002070 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002071 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002072 self.call(test, spam=1)
2073
2074 def test_signature_bind_var(self):
2075 def test(*args, **kwargs):
2076 return args, kwargs
2077
2078 self.assertEqual(self.call(test), ((), {}))
2079 self.assertEqual(self.call(test, 1), ((1,), {}))
2080 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2081 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2082 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2083 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2084 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2085 ((1, 2), {'foo': 'bar'}))
2086
2087 def test_signature_bind_just_args(self):
2088 def test(a, b, c):
2089 return a, b, c
2090
2091 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2092
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002093 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002094 self.call(test, 1, 2, 3, 4)
2095
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002096 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002097 self.call(test, 1)
2098
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002099 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002100 self.call(test)
2101
2102 def test(a, b, c=10):
2103 return a, b, c
2104 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2105 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2106
2107 def test(a=1, b=2, c=3):
2108 return a, b, c
2109 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2110 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2111 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2112
2113 def test_signature_bind_varargs_order(self):
2114 def test(*args):
2115 return args
2116
2117 self.assertEqual(self.call(test), ())
2118 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2119
2120 def test_signature_bind_args_and_varargs(self):
2121 def test(a, b, c=3, *args):
2122 return a, b, c, args
2123
2124 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2125 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2126 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2127 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2128
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002129 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002130 "multiple values for argument 'c'"):
2131 self.call(test, 1, 2, 3, c=4)
2132
2133 def test_signature_bind_just_kwargs(self):
2134 def test(**kwargs):
2135 return kwargs
2136
2137 self.assertEqual(self.call(test), {})
2138 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2139 {'foo': 'bar', 'spam': 'ham'})
2140
2141 def test_signature_bind_args_and_kwargs(self):
2142 def test(a, b, c=3, **kwargs):
2143 return a, b, c, kwargs
2144
2145 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2146 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2147 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2148 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2149 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2150 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2151 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2152 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2153 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2154 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2155 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2156 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2157 (1, 2, 4, {'foo': 'bar'}))
2158 self.assertEqual(self.call(test, c=5, a=4, b=3),
2159 (4, 3, 5, {}))
2160
2161 def test_signature_bind_kwonly(self):
2162 def test(*, foo):
2163 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002164 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002165 'too many positional arguments'):
2166 self.call(test, 1)
2167 self.assertEqual(self.call(test, foo=1), 1)
2168
2169 def test(a, *, foo=1, bar):
2170 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002171 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002172 "'bar' parameter lacking default value"):
2173 self.call(test, 1)
2174
2175 def test(foo, *, bar):
2176 return foo, bar
2177 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2178 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2179
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002180 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002181 'too many keyword arguments'):
2182 self.call(test, bar=2, foo=1, spam=10)
2183
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002184 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002185 'too many positional arguments'):
2186 self.call(test, 1, 2)
2187
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002188 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002189 'too many positional arguments'):
2190 self.call(test, 1, 2, bar=2)
2191
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002192 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002193 'too many keyword arguments'):
2194 self.call(test, 1, bar=2, spam='ham')
2195
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002196 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002197 "'bar' parameter lacking default value"):
2198 self.call(test, 1)
2199
2200 def test(foo, *, bar, **bin):
2201 return foo, bar, bin
2202 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2203 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2204 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2205 (1, 2, {'spam': 'ham'}))
2206 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2207 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002208 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002209 "'foo' parameter lacking default value"):
2210 self.call(test, spam='ham', bar=2)
2211 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2212 (1, 2, {'bin': 1, 'spam': 10}))
2213
2214 def test_signature_bind_arguments(self):
2215 def test(a, *args, b, z=100, **kwargs):
2216 pass
2217 sig = inspect.signature(test)
2218 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2219 # we won't have 'z' argument in the bound arguments object, as we didn't
2220 # pass it to the 'bind'
2221 self.assertEqual(tuple(ba.arguments.items()),
2222 (('a', 10), ('args', (20,)), ('b', 30),
2223 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2224 self.assertEqual(ba.kwargs,
2225 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2226 self.assertEqual(ba.args, (10, 20))
2227
2228 def test_signature_bind_positional_only(self):
2229 P = inspect.Parameter
2230
2231 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2232 return a_po, b_po, c_po, foo, bar, kwargs
2233
2234 sig = inspect.signature(test)
2235 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2236 for name in ('a_po', 'b_po', 'c_po'):
2237 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2238 new_sig = sig.replace(parameters=new_params.values())
2239 test.__signature__ = new_sig
2240
2241 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2242 (1, 2, 4, 5, 6, {}))
2243
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002244 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002245 self.call(test, 1, 2, c_po=4)
2246
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002247 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002248 self.call(test, a_po=1, b_po=2)
2249
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002250 def test_signature_bind_with_self_arg(self):
2251 # Issue #17071: one of the parameters is named "self
2252 def test(a, self, b):
2253 pass
2254 sig = inspect.signature(test)
2255 ba = sig.bind(1, 2, 3)
2256 self.assertEqual(ba.args, (1, 2, 3))
2257 ba = sig.bind(1, self=2, b=3)
2258 self.assertEqual(ba.args, (1, 2, 3))
2259
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002260
2261class TestBoundArguments(unittest.TestCase):
2262 def test_signature_bound_arguments_unhashable(self):
2263 def foo(a): pass
2264 ba = inspect.signature(foo).bind(1)
2265
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002266 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002267 hash(ba)
2268
2269 def test_signature_bound_arguments_equality(self):
2270 def foo(a): pass
2271 ba = inspect.signature(foo).bind(1)
2272 self.assertEqual(ba, ba)
2273
2274 ba2 = inspect.signature(foo).bind(1)
2275 self.assertEqual(ba, ba2)
2276
2277 ba3 = inspect.signature(foo).bind(2)
2278 self.assertNotEqual(ba, ba3)
2279 ba3.arguments['a'] = 1
2280 self.assertEqual(ba, ba3)
2281
2282 def bar(b): pass
2283 ba4 = inspect.signature(bar).bind(1)
2284 self.assertNotEqual(ba, ba4)
2285
2286
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002287def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00002288 run_unittest(
2289 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
2290 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
2291 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00002292 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002293 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan2f92e542012-06-23 19:39:55 +10002294 TestBoundArguments, TestGetClosureVars
Michael Foord95fc51d2010-11-20 15:07:30 +00002295 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00002296
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002297if __name__ == "__main__":
2298 test_main()