blob: 6e3f04e68a0d37a019e9a2768fdb0472d69d4887 [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
Alexander Belopolskyf546e702010-12-02 00:10:11 +0000419class TestNoEOL(GetSourceBase):
420 def __init__(self, *args, **kwargs):
421 self.tempdir = TESTFN + '_dir'
422 os.mkdir(self.tempdir)
423 with open(os.path.join(self.tempdir,
424 'inspect_fodder3%spy' % os.extsep), 'w') as f:
425 f.write("class X:\n pass # No EOL")
426 with DirsOnSysPath(self.tempdir):
427 import inspect_fodder3 as mod3
428 self.fodderModule = mod3
429 GetSourceBase.__init__(self, *args, **kwargs)
430
431 def tearDown(self):
432 shutil.rmtree(self.tempdir)
433
434 def test_class(self):
435 self.assertSourceEqual(self.fodderModule.X, 1, 2)
436
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100437
438class _BrokenDataDescriptor(object):
439 """
440 A broken data descriptor. See bug #1785.
441 """
442 def __get__(*args):
443 raise AssertionError("should not __get__ data descriptors")
444
445 def __set__(*args):
446 raise RuntimeError
447
448 def __getattr__(*args):
449 raise AssertionError("should not __getattr__ data descriptors")
450
451
452class _BrokenMethodDescriptor(object):
453 """
454 A broken method descriptor. See bug #1785.
455 """
456 def __get__(*args):
457 raise AssertionError("should not __get__ method descriptors")
458
459 def __getattr__(*args):
460 raise AssertionError("should not __getattr__ method descriptors")
461
462
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000463# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000464def attrs_wo_objs(cls):
465 return [t[:3] for t in inspect.classify_class_attrs(cls)]
466
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100467
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000468class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000469 def test_newstyle_mro(self):
470 # The same w/ new-class MRO.
471 class A(object): pass
472 class B(A): pass
473 class C(A): pass
474 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000475
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000476 expected = (D, B, C, A, object)
477 got = inspect.getmro(D)
478 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000479
Christian Heimes3795b532007-11-08 13:48:53 +0000480 def assertArgSpecEquals(self, routine, args_e, varargs_e=None,
481 varkw_e=None, defaults_e=None, formatted=None):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000482 args, varargs, varkw, defaults = inspect.getargspec(routine)
483 self.assertEqual(args, args_e)
484 self.assertEqual(varargs, varargs_e)
485 self.assertEqual(varkw, varkw_e)
486 self.assertEqual(defaults, defaults_e)
487 if formatted is not None:
488 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
489 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000490
Christian Heimes3795b532007-11-08 13:48:53 +0000491 def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
492 varkw_e=None, defaults_e=None,
493 kwonlyargs_e=[], kwonlydefaults_e=None,
494 ann_e={}, formatted=None):
495 args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
496 inspect.getfullargspec(routine)
497 self.assertEqual(args, args_e)
498 self.assertEqual(varargs, varargs_e)
499 self.assertEqual(varkw, varkw_e)
500 self.assertEqual(defaults, defaults_e)
501 self.assertEqual(kwonlyargs, kwonlyargs_e)
502 self.assertEqual(kwonlydefaults, kwonlydefaults_e)
503 self.assertEqual(ann, ann_e)
504 if formatted is not None:
505 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults,
506 kwonlyargs, kwonlydefaults, ann),
507 formatted)
508
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000509 def test_getargspec(self):
Christian Heimes3795b532007-11-08 13:48:53 +0000510 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted='(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000511
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000512 self.assertArgSpecEquals(mod.spam,
Guido van Rossum1bc535d2007-05-15 18:46:22 +0000513 ['a', 'b', 'c', 'd', 'e', 'f'],
514 'g', 'h', (3, 4, 5),
515 '(a, b, c, d=3, e=4, f=5, *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000516
Christian Heimes3795b532007-11-08 13:48:53 +0000517 self.assertRaises(ValueError, self.assertArgSpecEquals,
518 mod2.keyworded, [])
519
520 self.assertRaises(ValueError, self.assertArgSpecEquals,
521 mod2.annotated, [])
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000522 self.assertRaises(ValueError, self.assertArgSpecEquals,
523 mod2.keyword_only_arg, [])
524
Christian Heimes3795b532007-11-08 13:48:53 +0000525
526 def test_getfullargspec(self):
527 self.assertFullArgSpecEquals(mod2.keyworded, [], varargs_e='arg1',
528 kwonlyargs_e=['arg2'],
529 kwonlydefaults_e={'arg2':1},
530 formatted='(*arg1, arg2=1)')
531
532 self.assertFullArgSpecEquals(mod2.annotated, ['arg1'],
Christian Heimesc9543e42007-11-28 08:28:28 +0000533 ann_e={'arg1' : list},
Christian Heimes3795b532007-11-08 13:48:53 +0000534 formatted='(arg1: list)')
Benjamin Peterson9953a8d2009-01-17 04:15:01 +0000535 self.assertFullArgSpecEquals(mod2.keyword_only_arg, [],
536 kwonlyargs_e=['arg'],
537 formatted='(*, arg)')
538
Christian Heimes3795b532007-11-08 13:48:53 +0000539
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000540 def test_getargspec_method(self):
541 class A(object):
542 def m(self):
543 pass
544 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000545
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000546 def test_classify_newstyle(self):
547 class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000548
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000549 def s(): pass
550 s = staticmethod(s)
Tim Peters13b49d32001-09-23 02:00:29 +0000551
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000552 def c(cls): pass
553 c = classmethod(c)
Tim Peters13b49d32001-09-23 02:00:29 +0000554
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000555 def getp(self): pass
556 p = property(getp)
Tim Peters13b49d32001-09-23 02:00:29 +0000557
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000558 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000559
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000560 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000561
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000562 datablob = '1'
Tim Peters13b49d32001-09-23 02:00:29 +0000563
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100564 dd = _BrokenDataDescriptor()
565 md = _BrokenMethodDescriptor()
566
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000567 attrs = attrs_wo_objs(A)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000568 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
569 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
570 self.assertIn(('p', 'property', A), attrs, 'missing property')
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000571 self.assertIn(('m', 'method', A), attrs,
572 'missing plain method: %r' % attrs)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000573 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
574 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100575 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
576 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000577
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000578 class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000579
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000580 def m(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000581
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000582 attrs = attrs_wo_objs(B)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000583 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
584 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
585 self.assertIn(('p', 'property', A), attrs, 'missing property')
586 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
587 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
588 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100589 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
590 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000591
592
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000593 class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000594
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000595 def m(self): pass
596 def c(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000597
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000598 attrs = attrs_wo_objs(C)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000599 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
600 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
601 self.assertIn(('p', 'property', A), attrs, 'missing property')
602 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
603 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
604 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100605 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
606 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
Tim Peters13b49d32001-09-23 02:00:29 +0000607
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000608 class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000609
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000610 def m1(self): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000611
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000612 attrs = attrs_wo_objs(D)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000613 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
614 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
615 self.assertIn(('p', 'property', A), attrs, 'missing property')
616 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
617 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
618 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
Antoine Pitrou86a8a9a2011-12-21 09:57:40 +0100619 self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
620 self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
621
622 def test_classify_builtin_types(self):
623 # Simple sanity check that all built-in types can have their
624 # attributes classified.
625 for name in dir(__builtins__):
626 builtin = getattr(__builtins__, name)
627 if isinstance(builtin, type):
628 inspect.classify_class_attrs(builtin)
629
630 def test_getmembers_descriptors(self):
631 class A(object):
632 dd = _BrokenDataDescriptor()
633 md = _BrokenMethodDescriptor()
634
635 def pred_wrapper(pred):
636 # A quick'n'dirty way to discard standard attributes of new-style
637 # classes.
638 class Empty(object):
639 pass
640 def wrapped(x):
641 if '__name__' in dir(x) and hasattr(Empty, x.__name__):
642 return False
643 return pred(x)
644 return wrapped
645
646 ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
647 isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
648
649 self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
650 [('md', A.__dict__['md'])])
651 self.assertEqual(inspect.getmembers(A, isdatadescriptor),
652 [('dd', A.__dict__['dd'])])
653
654 class B(A):
655 pass
656
657 self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
658 [('md', A.__dict__['md'])])
659 self.assertEqual(inspect.getmembers(B, isdatadescriptor),
660 [('dd', A.__dict__['dd'])])
661
Antoine Pitrou0c603812012-01-18 17:40:18 +0100662 def test_getmembers_method(self):
663 class B:
664 def f(self):
665 pass
666
667 self.assertIn(('f', B.f), inspect.getmembers(B))
668 self.assertNotIn(('f', B.f), inspect.getmembers(B, inspect.ismethod))
669 b = B()
670 self.assertIn(('f', b.f), inspect.getmembers(b))
671 self.assertIn(('f', b.f), inspect.getmembers(b, inspect.ismethod))
672
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000673
Nick Coghlan2f92e542012-06-23 19:39:55 +1000674_global_ref = object()
675class TestGetClosureVars(unittest.TestCase):
676
677 def test_name_resolution(self):
678 # Basic test of the 4 different resolution mechanisms
679 def f(nonlocal_ref):
680 def g(local_ref):
681 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
682 return g
683 _arg = object()
684 nonlocal_vars = {"nonlocal_ref": _arg}
685 global_vars = {"_global_ref": _global_ref}
686 builtin_vars = {"print": print}
687 unbound_names = {"unbound_ref"}
688 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
689 builtin_vars, unbound_names)
690 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
691
692 def test_generator_closure(self):
693 def f(nonlocal_ref):
694 def g(local_ref):
695 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
696 yield
697 return g
698 _arg = object()
699 nonlocal_vars = {"nonlocal_ref": _arg}
700 global_vars = {"_global_ref": _global_ref}
701 builtin_vars = {"print": print}
702 unbound_names = {"unbound_ref"}
703 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
704 builtin_vars, unbound_names)
705 self.assertEqual(inspect.getclosurevars(f(_arg)), expected)
706
707 def test_method_closure(self):
708 class C:
709 def f(self, nonlocal_ref):
710 def g(local_ref):
711 print(local_ref, nonlocal_ref, _global_ref, unbound_ref)
712 return g
713 _arg = object()
714 nonlocal_vars = {"nonlocal_ref": _arg}
715 global_vars = {"_global_ref": _global_ref}
716 builtin_vars = {"print": print}
717 unbound_names = {"unbound_ref"}
718 expected = inspect.ClosureVars(nonlocal_vars, global_vars,
719 builtin_vars, unbound_names)
720 self.assertEqual(inspect.getclosurevars(C().f(_arg)), expected)
721
722 def test_nonlocal_vars(self):
723 # More complex tests of nonlocal resolution
724 def _nonlocal_vars(f):
725 return inspect.getclosurevars(f).nonlocals
726
727 def make_adder(x):
728 def add(y):
729 return x + y
730 return add
731
732 def curry(func, arg1):
733 return lambda arg2: func(arg1, arg2)
734
735 def less_than(a, b):
736 return a < b
737
738 # The infamous Y combinator.
739 def Y(le):
740 def g(f):
741 return le(lambda x: f(f)(x))
742 Y.g_ref = g
743 return g(g)
744
745 def check_y_combinator(func):
746 self.assertEqual(_nonlocal_vars(func), {'f': Y.g_ref})
747
748 inc = make_adder(1)
749 add_two = make_adder(2)
750 greater_than_five = curry(less_than, 5)
751
752 self.assertEqual(_nonlocal_vars(inc), {'x': 1})
753 self.assertEqual(_nonlocal_vars(add_two), {'x': 2})
754 self.assertEqual(_nonlocal_vars(greater_than_five),
755 {'arg1': 5, 'func': less_than})
756 self.assertEqual(_nonlocal_vars((lambda x: lambda y: x + y)(3)),
757 {'x': 3})
758 Y(check_y_combinator)
759
760 def test_getclosurevars_empty(self):
761 def foo(): pass
762 _empty = inspect.ClosureVars({}, {}, {}, set())
763 self.assertEqual(inspect.getclosurevars(lambda: True), _empty)
764 self.assertEqual(inspect.getclosurevars(foo), _empty)
765
766 def test_getclosurevars_error(self):
767 class T: pass
768 self.assertRaises(TypeError, inspect.getclosurevars, 1)
769 self.assertRaises(TypeError, inspect.getclosurevars, list)
770 self.assertRaises(TypeError, inspect.getclosurevars, {})
771
Nick Coghlan6c6e2542012-06-23 20:07:39 +1000772 def _private_globals(self):
773 code = """def f(): print(path)"""
774 ns = {}
775 exec(code, ns)
776 return ns["f"], ns
777
778 def test_builtins_fallback(self):
779 f, ns = self._private_globals()
780 ns.pop("__builtins__", None)
781 expected = inspect.ClosureVars({}, {}, {"print":print}, {"path"})
782 self.assertEqual(inspect.getclosurevars(f), expected)
783
784 def test_builtins_as_dict(self):
785 f, ns = self._private_globals()
786 ns["__builtins__"] = {"path":1}
787 expected = inspect.ClosureVars({}, {}, {"path":1}, {"print"})
788 self.assertEqual(inspect.getclosurevars(f), expected)
789
790 def test_builtins_as_module(self):
791 f, ns = self._private_globals()
792 ns["__builtins__"] = os
793 expected = inspect.ClosureVars({}, {}, {"path":os.path}, {"print"})
794 self.assertEqual(inspect.getclosurevars(f), expected)
795
Nick Coghlan2f92e542012-06-23 19:39:55 +1000796
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000797class TestGetcallargsFunctions(unittest.TestCase):
798
799 def assertEqualCallArgs(self, func, call_params_string, locs=None):
800 locs = dict(locs or {}, func=func)
801 r1 = eval('func(%s)' % call_params_string, None, locs)
802 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
803 locs)
804 self.assertEqual(r1, r2)
805
806 def assertEqualException(self, func, call_param_string, locs=None):
807 locs = dict(locs or {}, func=func)
808 try:
809 eval('func(%s)' % call_param_string, None, locs)
810 except Exception as e:
811 ex1 = e
812 else:
813 self.fail('Exception not raised')
814 try:
815 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
816 locs)
817 except Exception as e:
818 ex2 = e
819 else:
820 self.fail('Exception not raised')
821 self.assertIs(type(ex1), type(ex2))
822 self.assertEqual(str(ex1), str(ex2))
823 del ex1, ex2
824
825 def makeCallable(self, signature):
826 """Create a function that returns its locals()"""
827 code = "lambda %s: locals()"
828 return eval(code % signature)
829
830 def test_plain(self):
831 f = self.makeCallable('a, b=1')
832 self.assertEqualCallArgs(f, '2')
833 self.assertEqualCallArgs(f, '2, 3')
834 self.assertEqualCallArgs(f, 'a=2')
835 self.assertEqualCallArgs(f, 'b=3, a=2')
836 self.assertEqualCallArgs(f, '2, b=3')
837 # expand *iterable / **mapping
838 self.assertEqualCallArgs(f, '*(2,)')
839 self.assertEqualCallArgs(f, '*[2]')
840 self.assertEqualCallArgs(f, '*(2, 3)')
841 self.assertEqualCallArgs(f, '*[2, 3]')
842 self.assertEqualCallArgs(f, '**{"a":2}')
843 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
844 self.assertEqualCallArgs(f, '2, **{"b":3}')
845 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
846 # expand UserList / UserDict
847 self.assertEqualCallArgs(f, '*collections.UserList([2])')
848 self.assertEqualCallArgs(f, '*collections.UserList([2, 3])')
849 self.assertEqualCallArgs(f, '**collections.UserDict(a=2)')
850 self.assertEqualCallArgs(f, '2, **collections.UserDict(b=3)')
851 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3)')
852
853 def test_varargs(self):
854 f = self.makeCallable('a, b=1, *c')
855 self.assertEqualCallArgs(f, '2')
856 self.assertEqualCallArgs(f, '2, 3')
857 self.assertEqualCallArgs(f, '2, 3, 4')
858 self.assertEqualCallArgs(f, '*(2,3,4)')
859 self.assertEqualCallArgs(f, '2, *[3,4]')
860 self.assertEqualCallArgs(f, '2, 3, *collections.UserList([4])')
861
862 def test_varkw(self):
863 f = self.makeCallable('a, b=1, **c')
864 self.assertEqualCallArgs(f, 'a=2')
865 self.assertEqualCallArgs(f, '2, b=3, c=4')
866 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
867 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
868 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
869 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
870 self.assertEqualCallArgs(f, '**collections.UserDict(a=2, b=3, c=4)')
871 self.assertEqualCallArgs(f, '2, c=4, **collections.UserDict(b=3)')
872 self.assertEqualCallArgs(f, 'b=2, **collections.UserDict(a=3, c=4)')
873
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500874 def test_varkw_only(self):
875 # issue11256:
876 f = self.makeCallable('**c')
877 self.assertEqualCallArgs(f, '')
878 self.assertEqualCallArgs(f, 'a=1')
879 self.assertEqualCallArgs(f, 'a=1, b=2')
880 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
881 self.assertEqualCallArgs(f, '**collections.UserDict(a=1, b=2)')
882 self.assertEqualCallArgs(f, 'c=3, **collections.UserDict(a=1, b=2)')
883
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000884 def test_keyword_only(self):
885 f = self.makeCallable('a=3, *, c, d=2')
886 self.assertEqualCallArgs(f, 'c=3')
887 self.assertEqualCallArgs(f, 'c=3, a=3')
888 self.assertEqualCallArgs(f, 'a=2, c=4')
889 self.assertEqualCallArgs(f, '4, c=4')
890 self.assertEqualException(f, '')
891 self.assertEqualException(f, '3')
892 self.assertEqualException(f, 'a=3')
893 self.assertEqualException(f, 'd=4')
894
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500895 f = self.makeCallable('*, c, d=2')
896 self.assertEqualCallArgs(f, 'c=3')
897 self.assertEqualCallArgs(f, 'c=3, d=4')
898 self.assertEqualCallArgs(f, 'd=4, c=3')
899
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000900 def test_multiple_features(self):
901 f = self.makeCallable('a, b=2, *f, **g')
902 self.assertEqualCallArgs(f, '2, 3, 7')
903 self.assertEqualCallArgs(f, '2, 3, x=8')
904 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
905 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
906 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
907 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
908 '[2, 3, (4,[5,6])]), **{"y":9, "z":10}')
909 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
910 '(4,[5,6])]), **collections.UserDict('
911 'y=9, z=10)')
912
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500913 f = self.makeCallable('a, b=2, *f, x, y=99, **g')
914 self.assertEqualCallArgs(f, '2, 3, x=8')
915 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
916 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9, z=10')
917 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9, z=10')
918 self.assertEqualCallArgs(f, 'x=8, *collections.UserList('
919 '[2, 3, (4,[5,6])]), q=0, **{"y":9, "z":10}')
920 self.assertEqualCallArgs(f, '2, x=8, *collections.UserList([3, '
921 '(4,[5,6])]), q=0, **collections.UserDict('
922 'y=9, z=10)')
923
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000924 def test_errors(self):
925 f0 = self.makeCallable('')
926 f1 = self.makeCallable('a, b')
927 f2 = self.makeCallable('a, b=1')
928 # f0 takes no arguments
929 self.assertEqualException(f0, '1')
930 self.assertEqualException(f0, 'x=1')
931 self.assertEqualException(f0, '1,x=1')
932 # f1 takes exactly 2 arguments
933 self.assertEqualException(f1, '')
934 self.assertEqualException(f1, '1')
935 self.assertEqualException(f1, 'a=2')
936 self.assertEqualException(f1, 'b=3')
937 # f2 takes at least 1 argument
938 self.assertEqualException(f2, '')
939 self.assertEqualException(f2, 'b=3')
940 for f in f1, f2:
941 # f1/f2 takes exactly/at most 2 arguments
942 self.assertEqualException(f, '2, 3, 4')
943 self.assertEqualException(f, '1, 2, 3, a=1')
944 self.assertEqualException(f, '2, 3, 4, c=5')
Georg Brandl178e5ea2012-02-21 00:32:36 +0100945 # XXX: success of this one depends on dict order
946 ## self.assertEqualException(f, '2, 3, 4, a=1, c=5')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000947 # f got an unexpected keyword argument
948 self.assertEqualException(f, 'c=2')
949 self.assertEqualException(f, '2, c=3')
950 self.assertEqualException(f, '2, 3, c=4')
951 self.assertEqualException(f, '2, c=4, b=3')
952 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
953 # f got multiple values for keyword argument
954 self.assertEqualException(f, '1, a=2')
955 self.assertEqualException(f, '1, **{"a":2}')
956 self.assertEqualException(f, '1, 2, b=3')
957 # XXX: Python inconsistency
958 # - for functions and bound methods: unexpected keyword 'c'
959 # - for unbound methods: multiple values for keyword 'a'
960 #self.assertEqualException(f, '1, c=3, a=2')
Benjamin Peterson6a2638b2011-03-28 17:32:31 -0500961 # issue11256:
962 f3 = self.makeCallable('**c')
963 self.assertEqualException(f3, '1, 2')
964 self.assertEqualException(f3, '1, 2, a=1, b=2')
965 f4 = self.makeCallable('*, a, b=0')
966 self.assertEqualException(f3, '1, 2')
967 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +0000968
969class TestGetcallargsMethods(TestGetcallargsFunctions):
970
971 def setUp(self):
972 class Foo(object):
973 pass
974 self.cls = Foo
975 self.inst = Foo()
976
977 def makeCallable(self, signature):
978 assert 'self' not in signature
979 mk = super(TestGetcallargsMethods, self).makeCallable
980 self.cls.method = mk('self, ' + signature)
981 return self.inst.method
982
983class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
984
985 def makeCallable(self, signature):
986 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
987 return self.cls.method
988
989 def assertEqualCallArgs(self, func, call_params_string, locs=None):
990 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
991 *self._getAssertEqualParams(func, call_params_string, locs))
992
993 def assertEqualException(self, func, call_params_string, locs=None):
994 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
995 *self._getAssertEqualParams(func, call_params_string, locs))
996
997 def _getAssertEqualParams(self, func, call_params_string, locs=None):
998 assert 'inst' not in call_params_string
999 locs = dict(locs or {}, inst=self.inst)
1000 return (func, 'inst,' + call_params_string, locs)
1001
Michael Foord95fc51d2010-11-20 15:07:30 +00001002
1003class TestGetattrStatic(unittest.TestCase):
1004
1005 def test_basic(self):
1006 class Thing(object):
1007 x = object()
1008
1009 thing = Thing()
1010 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1011 self.assertEqual(inspect.getattr_static(thing, 'x', None), Thing.x)
1012 with self.assertRaises(AttributeError):
1013 inspect.getattr_static(thing, 'y')
1014
1015 self.assertEqual(inspect.getattr_static(thing, 'y', 3), 3)
1016
1017 def test_inherited(self):
1018 class Thing(object):
1019 x = object()
1020 class OtherThing(Thing):
1021 pass
1022
1023 something = OtherThing()
1024 self.assertEqual(inspect.getattr_static(something, 'x'), Thing.x)
1025
1026 def test_instance_attr(self):
1027 class Thing(object):
1028 x = 2
1029 def __init__(self, x):
1030 self.x = x
1031 thing = Thing(3)
1032 self.assertEqual(inspect.getattr_static(thing, 'x'), 3)
1033 del thing.x
1034 self.assertEqual(inspect.getattr_static(thing, 'x'), 2)
1035
1036 def test_property(self):
1037 class Thing(object):
1038 @property
1039 def x(self):
1040 raise AttributeError("I'm pretending not to exist")
1041 thing = Thing()
1042 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1043
Ezio Melotti75cbd732011-04-28 00:59:29 +03001044 def test_descriptor_raises_AttributeError(self):
Michael Foord95fc51d2010-11-20 15:07:30 +00001045 class descriptor(object):
1046 def __get__(*_):
1047 raise AttributeError("I'm pretending not to exist")
1048 desc = descriptor()
1049 class Thing(object):
1050 x = desc
1051 thing = Thing()
1052 self.assertEqual(inspect.getattr_static(thing, 'x'), desc)
1053
1054 def test_classAttribute(self):
1055 class Thing(object):
1056 x = object()
1057
1058 self.assertEqual(inspect.getattr_static(Thing, 'x'), Thing.x)
1059
1060 def test_inherited_classattribute(self):
1061 class Thing(object):
1062 x = object()
1063 class OtherThing(Thing):
1064 pass
1065
1066 self.assertEqual(inspect.getattr_static(OtherThing, 'x'), Thing.x)
1067
1068 def test_slots(self):
1069 class Thing(object):
1070 y = 'bar'
1071 __slots__ = ['x']
1072 def __init__(self):
1073 self.x = 'foo'
1074 thing = Thing()
1075 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1076 self.assertEqual(inspect.getattr_static(thing, 'y'), 'bar')
1077
1078 del thing.x
1079 self.assertEqual(inspect.getattr_static(thing, 'x'), Thing.x)
1080
1081 def test_metaclass(self):
1082 class meta(type):
1083 attr = 'foo'
1084 class Thing(object, metaclass=meta):
1085 pass
1086 self.assertEqual(inspect.getattr_static(Thing, 'attr'), 'foo')
1087
1088 class sub(meta):
1089 pass
1090 class OtherThing(object, metaclass=sub):
1091 x = 3
1092 self.assertEqual(inspect.getattr_static(OtherThing, 'attr'), 'foo')
1093
1094 class OtherOtherThing(OtherThing):
1095 pass
1096 # this test is odd, but it was added as it exposed a bug
1097 self.assertEqual(inspect.getattr_static(OtherOtherThing, 'x'), 3)
1098
1099 def test_no_dict_no_slots(self):
1100 self.assertEqual(inspect.getattr_static(1, 'foo', None), None)
1101 self.assertNotEqual(inspect.getattr_static('foo', 'lower'), None)
1102
1103 def test_no_dict_no_slots_instance_member(self):
1104 # returns descriptor
1105 with open(__file__) as handle:
1106 self.assertEqual(inspect.getattr_static(handle, 'name'), type(handle).name)
1107
1108 def test_inherited_slots(self):
1109 # returns descriptor
1110 class Thing(object):
1111 __slots__ = ['x']
1112 def __init__(self):
1113 self.x = 'foo'
1114
1115 class OtherThing(Thing):
1116 pass
1117 # it would be nice if this worked...
1118 # we get the descriptor instead of the instance attribute
1119 self.assertEqual(inspect.getattr_static(OtherThing(), 'x'), Thing.x)
1120
1121 def test_descriptor(self):
1122 class descriptor(object):
1123 def __get__(self, instance, owner):
1124 return 3
1125 class Foo(object):
1126 d = descriptor()
1127
1128 foo = Foo()
1129
1130 # for a non data descriptor we return the instance attribute
1131 foo.__dict__['d'] = 1
1132 self.assertEqual(inspect.getattr_static(foo, 'd'), 1)
1133
1134 # if the descriptor is a data-desciptor we should return the
1135 # descriptor
1136 descriptor.__set__ = lambda s, i, v: None
1137 self.assertEqual(inspect.getattr_static(foo, 'd'), Foo.__dict__['d'])
1138
1139
1140 def test_metaclass_with_descriptor(self):
1141 class descriptor(object):
1142 def __get__(self, instance, owner):
1143 return 3
1144 class meta(type):
1145 d = descriptor()
1146 class Thing(object, metaclass=meta):
1147 pass
1148 self.assertEqual(inspect.getattr_static(Thing, 'd'), meta.__dict__['d'])
1149
1150
Michael Foordcc7ebb82010-11-20 16:20:16 +00001151 def test_class_as_property(self):
1152 class Base(object):
1153 foo = 3
1154
1155 class Something(Base):
Michael Foord35184ed2010-11-20 16:58:30 +00001156 executed = False
Michael Foordcc7ebb82010-11-20 16:20:16 +00001157 @property
1158 def __class__(self):
Michael Foord35184ed2010-11-20 16:58:30 +00001159 self.executed = True
Michael Foordcc7ebb82010-11-20 16:20:16 +00001160 return object
1161
Michael Foord35184ed2010-11-20 16:58:30 +00001162 instance = Something()
1163 self.assertEqual(inspect.getattr_static(instance, 'foo'), 3)
1164 self.assertFalse(instance.executed)
Michael Foordcc7ebb82010-11-20 16:20:16 +00001165 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1166
Michael Foorde5162652010-11-20 16:40:44 +00001167 def test_mro_as_property(self):
1168 class Meta(type):
1169 @property
1170 def __mro__(self):
1171 return (object,)
1172
1173 class Base(object):
1174 foo = 3
1175
1176 class Something(Base, metaclass=Meta):
1177 pass
1178
1179 self.assertEqual(inspect.getattr_static(Something(), 'foo'), 3)
1180 self.assertEqual(inspect.getattr_static(Something, 'foo'), 3)
1181
Michael Foorddcebe0f2011-03-15 19:20:44 -04001182 def test_dict_as_property(self):
1183 test = self
1184 test.called = False
1185
1186 class Foo(dict):
1187 a = 3
1188 @property
1189 def __dict__(self):
1190 test.called = True
1191 return {}
1192
1193 foo = Foo()
1194 foo.a = 4
1195 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1196 self.assertFalse(test.called)
1197
1198 def test_custom_object_dict(self):
1199 test = self
1200 test.called = False
1201
1202 class Custom(dict):
1203 def get(self, key, default=None):
1204 test.called = True
1205 super().get(key, default)
1206
1207 class Foo(object):
1208 a = 3
1209 foo = Foo()
1210 foo.__dict__ = Custom()
1211 self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
1212 self.assertFalse(test.called)
1213
1214 def test_metaclass_dict_as_property(self):
1215 class Meta(type):
1216 @property
1217 def __dict__(self):
1218 self.executed = True
1219
1220 class Thing(metaclass=Meta):
1221 executed = False
1222
1223 def __init__(self):
1224 self.spam = 42
1225
1226 instance = Thing()
1227 self.assertEqual(inspect.getattr_static(instance, "spam"), 42)
1228 self.assertFalse(Thing.executed)
Michael Foorde5162652010-11-20 16:40:44 +00001229
Michael Foorda51623b2011-12-18 22:01:40 +00001230 def test_module(self):
1231 sentinel = object()
1232 self.assertIsNot(inspect.getattr_static(sys, "version", sentinel),
1233 sentinel)
1234
Michael Foord3ba95f82011-12-22 01:13:37 +00001235 def test_metaclass_with_metaclass_with_dict_as_property(self):
1236 class MetaMeta(type):
1237 @property
1238 def __dict__(self):
1239 self.executed = True
1240 return dict(spam=42)
1241
1242 class Meta(type, metaclass=MetaMeta):
1243 executed = False
1244
1245 class Thing(metaclass=Meta):
1246 pass
1247
1248 with self.assertRaises(AttributeError):
1249 inspect.getattr_static(Thing, "spam")
1250 self.assertFalse(Thing.executed)
1251
Nick Coghlane0f04652010-11-21 03:44:04 +00001252class TestGetGeneratorState(unittest.TestCase):
1253
1254 def setUp(self):
1255 def number_generator():
1256 for number in range(5):
1257 yield number
1258 self.generator = number_generator()
1259
1260 def _generatorstate(self):
1261 return inspect.getgeneratorstate(self.generator)
1262
1263 def test_created(self):
1264 self.assertEqual(self._generatorstate(), inspect.GEN_CREATED)
1265
1266 def test_suspended(self):
1267 next(self.generator)
1268 self.assertEqual(self._generatorstate(), inspect.GEN_SUSPENDED)
1269
1270 def test_closed_after_exhaustion(self):
1271 for i in self.generator:
1272 pass
1273 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1274
1275 def test_closed_after_immediate_exception(self):
1276 with self.assertRaises(RuntimeError):
1277 self.generator.throw(RuntimeError)
1278 self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
1279
1280 def test_running(self):
1281 # As mentioned on issue #10220, checking for the RUNNING state only
1282 # makes sense inside the generator itself.
1283 # The following generator checks for this by using the closure's
1284 # reference to self and the generator state checking helper method
1285 def running_check_generator():
1286 for number in range(5):
1287 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1288 yield number
1289 self.assertEqual(self._generatorstate(), inspect.GEN_RUNNING)
1290 self.generator = running_check_generator()
1291 # Running up to the first yield
1292 next(self.generator)
1293 # Running after the first yield
1294 next(self.generator)
1295
Nick Coghlan7921b9f2010-11-30 06:36:04 +00001296 def test_easy_debugging(self):
1297 # repr() and str() of a generator state should contain the state name
1298 names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
1299 for name in names:
1300 state = getattr(inspect, name)
1301 self.assertIn(name, repr(state))
1302 self.assertIn(name, str(state))
1303
Nick Coghlan04e2e3f2012-06-23 19:52:05 +10001304 def test_getgeneratorlocals(self):
1305 def each(lst, a=None):
1306 b=(1, 2, 3)
1307 for v in lst:
1308 if v == 3:
1309 c = 12
1310 yield v
1311
1312 numbers = each([1, 2, 3])
1313 self.assertEqual(inspect.getgeneratorlocals(numbers),
1314 {'a': None, 'lst': [1, 2, 3]})
1315 next(numbers)
1316 self.assertEqual(inspect.getgeneratorlocals(numbers),
1317 {'a': None, 'lst': [1, 2, 3], 'v': 1,
1318 'b': (1, 2, 3)})
1319 next(numbers)
1320 self.assertEqual(inspect.getgeneratorlocals(numbers),
1321 {'a': None, 'lst': [1, 2, 3], 'v': 2,
1322 'b': (1, 2, 3)})
1323 next(numbers)
1324 self.assertEqual(inspect.getgeneratorlocals(numbers),
1325 {'a': None, 'lst': [1, 2, 3], 'v': 3,
1326 'b': (1, 2, 3), 'c': 12})
1327 try:
1328 next(numbers)
1329 except StopIteration:
1330 pass
1331 self.assertEqual(inspect.getgeneratorlocals(numbers), {})
1332
1333 def test_getgeneratorlocals_empty(self):
1334 def yield_one():
1335 yield 1
1336 one = yield_one()
1337 self.assertEqual(inspect.getgeneratorlocals(one), {})
1338 try:
1339 next(one)
1340 except StopIteration:
1341 pass
1342 self.assertEqual(inspect.getgeneratorlocals(one), {})
1343
1344 def test_getgeneratorlocals_error(self):
1345 self.assertRaises(TypeError, inspect.getgeneratorlocals, 1)
1346 self.assertRaises(TypeError, inspect.getgeneratorlocals, lambda x: True)
1347 self.assertRaises(TypeError, inspect.getgeneratorlocals, set)
1348 self.assertRaises(TypeError, inspect.getgeneratorlocals, (2,3))
1349
Nick Coghlane0f04652010-11-21 03:44:04 +00001350
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001351class TestSignatureObject(unittest.TestCase):
1352 @staticmethod
1353 def signature(func):
1354 sig = inspect.signature(func)
1355 return (tuple((param.name,
1356 (... if param.default is param.empty else param.default),
1357 (... if param.annotation is param.empty
1358 else param.annotation),
1359 str(param.kind).lower())
1360 for param in sig.parameters.values()),
1361 (... if sig.return_annotation is sig.empty
1362 else sig.return_annotation))
1363
1364 def test_signature_object(self):
1365 S = inspect.Signature
1366 P = inspect.Parameter
1367
1368 self.assertEqual(str(S()), '()')
1369
1370 def test(po, pk, *args, ko, **kwargs):
1371 pass
1372 sig = inspect.signature(test)
1373 po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
1374 pk = sig.parameters['pk']
1375 args = sig.parameters['args']
1376 ko = sig.parameters['ko']
1377 kwargs = sig.parameters['kwargs']
1378
1379 S((po, pk, args, ko, kwargs))
1380
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001381 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001382 S((pk, po, args, ko, kwargs))
1383
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001384 with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001385 S((po, args, pk, 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((args, po, pk, 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, pk, args, kwargs, ko))
1392
1393 kwargs2 = kwargs.replace(name='args')
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001394 with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001395 S((po, pk, args, kwargs2, ko))
1396
1397 def test_signature_immutability(self):
1398 def test(a):
1399 pass
1400 sig = inspect.signature(test)
1401
1402 with self.assertRaises(AttributeError):
1403 sig.foo = 'bar'
1404
1405 with self.assertRaises(TypeError):
1406 sig.parameters['a'] = None
1407
1408 def test_signature_on_noarg(self):
1409 def test():
1410 pass
1411 self.assertEqual(self.signature(test), ((), ...))
1412
1413 def test_signature_on_wargs(self):
1414 def test(a, b:'foo') -> 123:
1415 pass
1416 self.assertEqual(self.signature(test),
1417 ((('a', ..., ..., "positional_or_keyword"),
1418 ('b', ..., 'foo', "positional_or_keyword")),
1419 123))
1420
1421 def test_signature_on_wkwonly(self):
1422 def test(*, a:float, b:str) -> int:
1423 pass
1424 self.assertEqual(self.signature(test),
1425 ((('a', ..., float, "keyword_only"),
1426 ('b', ..., str, "keyword_only")),
1427 int))
1428
1429 def test_signature_on_complex_args(self):
1430 def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
1431 pass
1432 self.assertEqual(self.signature(test),
1433 ((('a', ..., ..., "positional_or_keyword"),
1434 ('b', 10, 'foo', "positional_or_keyword"),
1435 ('args', ..., 'bar', "var_positional"),
1436 ('spam', ..., 'baz', "keyword_only"),
1437 ('ham', 123, ..., "keyword_only"),
1438 ('kwargs', ..., int, "var_keyword")),
1439 ...))
1440
1441 def test_signature_on_builtin_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001442 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001443 inspect.signature(type)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001444 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001445 # support for 'wrapper_descriptor'
1446 inspect.signature(type.__call__)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001447 with self.assertRaisesRegex(ValueError, 'not supported by signature'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001448 # support for 'method-wrapper'
1449 inspect.signature(min.__call__)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001450 with self.assertRaisesRegex(ValueError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001451 'no signature found for builtin function'):
1452 # support for 'method-wrapper'
1453 inspect.signature(min)
1454
1455 def test_signature_on_non_function(self):
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001456 with self.assertRaisesRegex(TypeError, 'is not a callable object'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001457 inspect.signature(42)
1458
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001459 with self.assertRaisesRegex(TypeError, 'is not a Python function'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001460 inspect.Signature.from_function(42)
1461
1462 def test_signature_on_method(self):
1463 class Test:
1464 def foo(self, arg1, arg2=1) -> int:
1465 pass
1466
1467 meth = Test().foo
1468
1469 self.assertEqual(self.signature(meth),
1470 ((('arg1', ..., ..., "positional_or_keyword"),
1471 ('arg2', 1, ..., "positional_or_keyword")),
1472 int))
1473
1474 def test_signature_on_classmethod(self):
1475 class Test:
1476 @classmethod
1477 def foo(cls, arg1, *, arg2=1):
1478 pass
1479
1480 meth = Test().foo
1481 self.assertEqual(self.signature(meth),
1482 ((('arg1', ..., ..., "positional_or_keyword"),
1483 ('arg2', 1, ..., "keyword_only")),
1484 ...))
1485
1486 meth = Test.foo
1487 self.assertEqual(self.signature(meth),
1488 ((('arg1', ..., ..., "positional_or_keyword"),
1489 ('arg2', 1, ..., "keyword_only")),
1490 ...))
1491
1492 def test_signature_on_staticmethod(self):
1493 class Test:
1494 @staticmethod
1495 def foo(cls, *, arg):
1496 pass
1497
1498 meth = Test().foo
1499 self.assertEqual(self.signature(meth),
1500 ((('cls', ..., ..., "positional_or_keyword"),
1501 ('arg', ..., ..., "keyword_only")),
1502 ...))
1503
1504 meth = Test.foo
1505 self.assertEqual(self.signature(meth),
1506 ((('cls', ..., ..., "positional_or_keyword"),
1507 ('arg', ..., ..., "keyword_only")),
1508 ...))
1509
1510 def test_signature_on_partial(self):
1511 from functools import partial
1512
1513 def test():
1514 pass
1515
1516 self.assertEqual(self.signature(partial(test)), ((), ...))
1517
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001518 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001519 inspect.signature(partial(test, 1))
1520
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001521 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001522 inspect.signature(partial(test, a=1))
1523
1524 def test(a, b, *, c, d):
1525 pass
1526
1527 self.assertEqual(self.signature(partial(test)),
1528 ((('a', ..., ..., "positional_or_keyword"),
1529 ('b', ..., ..., "positional_or_keyword"),
1530 ('c', ..., ..., "keyword_only"),
1531 ('d', ..., ..., "keyword_only")),
1532 ...))
1533
1534 self.assertEqual(self.signature(partial(test, 1)),
1535 ((('b', ..., ..., "positional_or_keyword"),
1536 ('c', ..., ..., "keyword_only"),
1537 ('d', ..., ..., "keyword_only")),
1538 ...))
1539
1540 self.assertEqual(self.signature(partial(test, 1, c=2)),
1541 ((('b', ..., ..., "positional_or_keyword"),
1542 ('c', 2, ..., "keyword_only"),
1543 ('d', ..., ..., "keyword_only")),
1544 ...))
1545
1546 self.assertEqual(self.signature(partial(test, b=1, c=2)),
1547 ((('a', ..., ..., "positional_or_keyword"),
1548 ('b', 1, ..., "positional_or_keyword"),
1549 ('c', 2, ..., "keyword_only"),
1550 ('d', ..., ..., "keyword_only")),
1551 ...))
1552
1553 self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
1554 ((('b', 1, ..., "positional_or_keyword"),
1555 ('c', 2, ..., "keyword_only"),
1556 ('d', ..., ..., "keyword_only"),),
1557 ...))
1558
1559 def test(a, *args, b, **kwargs):
1560 pass
1561
1562 self.assertEqual(self.signature(partial(test, 1)),
1563 ((('args', ..., ..., "var_positional"),
1564 ('b', ..., ..., "keyword_only"),
1565 ('kwargs', ..., ..., "var_keyword")),
1566 ...))
1567
1568 self.assertEqual(self.signature(partial(test, 1, 2, 3)),
1569 ((('args', ..., ..., "var_positional"),
1570 ('b', ..., ..., "keyword_only"),
1571 ('kwargs', ..., ..., "var_keyword")),
1572 ...))
1573
1574
1575 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
1576 ((('args', ..., ..., "var_positional"),
1577 ('b', ..., ..., "keyword_only"),
1578 ('kwargs', ..., ..., "var_keyword")),
1579 ...))
1580
1581 self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
1582 ((('args', ..., ..., "var_positional"),
1583 ('b', 0, ..., "keyword_only"),
1584 ('kwargs', ..., ..., "var_keyword")),
1585 ...))
1586
1587 self.assertEqual(self.signature(partial(test, b=0)),
1588 ((('a', ..., ..., "positional_or_keyword"),
1589 ('args', ..., ..., "var_positional"),
1590 ('b', 0, ..., "keyword_only"),
1591 ('kwargs', ..., ..., "var_keyword")),
1592 ...))
1593
1594 self.assertEqual(self.signature(partial(test, b=0, test=1)),
1595 ((('a', ..., ..., "positional_or_keyword"),
1596 ('args', ..., ..., "var_positional"),
1597 ('b', 0, ..., "keyword_only"),
1598 ('kwargs', ..., ..., "var_keyword")),
1599 ...))
1600
1601 def test(a, b, c:int) -> 42:
1602 pass
1603
1604 sig = test.__signature__ = inspect.signature(test)
1605
1606 self.assertEqual(self.signature(partial(partial(test, 1))),
1607 ((('b', ..., ..., "positional_or_keyword"),
1608 ('c', ..., int, "positional_or_keyword")),
1609 42))
1610
1611 self.assertEqual(self.signature(partial(partial(test, 1), 2)),
1612 ((('c', ..., int, "positional_or_keyword"),),
1613 42))
1614
1615 psig = inspect.signature(partial(partial(test, 1), 2))
1616
1617 def foo(a):
1618 return a
1619 _foo = partial(partial(foo, a=10), a=20)
1620 self.assertEqual(self.signature(_foo),
1621 ((('a', 20, ..., "positional_or_keyword"),),
1622 ...))
1623 # check that we don't have any side-effects in signature(),
1624 # and the partial object is still functioning
1625 self.assertEqual(_foo(), 20)
1626
1627 def foo(a, b, c):
1628 return a, b, c
1629 _foo = partial(partial(foo, 1, b=20), b=30)
1630 self.assertEqual(self.signature(_foo),
1631 ((('b', 30, ..., "positional_or_keyword"),
1632 ('c', ..., ..., "positional_or_keyword")),
1633 ...))
1634 self.assertEqual(_foo(c=10), (1, 30, 10))
1635 _foo = partial(_foo, 2) # now 'b' has two values -
1636 # positional and keyword
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001637 with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001638 inspect.signature(_foo)
1639
1640 def foo(a, b, c, *, d):
1641 return a, b, c, d
1642 _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
1643 self.assertEqual(self.signature(_foo),
1644 ((('a', ..., ..., "positional_or_keyword"),
1645 ('b', 10, ..., "positional_or_keyword"),
1646 ('c', 20, ..., "positional_or_keyword"),
1647 ('d', 30, ..., "keyword_only")),
1648 ...))
1649 ba = inspect.signature(_foo).bind(a=200, b=11)
1650 self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
1651
1652 def foo(a=1, b=2, c=3):
1653 return a, b, c
1654 _foo = partial(foo, a=10, c=13)
1655 ba = inspect.signature(_foo).bind(11)
1656 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
1657 ba = inspect.signature(_foo).bind(11, 12)
1658 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1659 ba = inspect.signature(_foo).bind(11, b=12)
1660 self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
1661 ba = inspect.signature(_foo).bind(b=12)
1662 self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
1663 _foo = partial(_foo, b=10)
1664 ba = inspect.signature(_foo).bind(12, 14)
1665 self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
1666
1667 def test_signature_on_decorated(self):
1668 import functools
1669
1670 def decorator(func):
1671 @functools.wraps(func)
1672 def wrapper(*args, **kwargs) -> int:
1673 return func(*args, **kwargs)
1674 return wrapper
1675
1676 class Foo:
1677 @decorator
1678 def bar(self, a, b):
1679 pass
1680
1681 self.assertEqual(self.signature(Foo.bar),
1682 ((('self', ..., ..., "positional_or_keyword"),
1683 ('a', ..., ..., "positional_or_keyword"),
1684 ('b', ..., ..., "positional_or_keyword")),
1685 ...))
1686
1687 self.assertEqual(self.signature(Foo().bar),
1688 ((('a', ..., ..., "positional_or_keyword"),
1689 ('b', ..., ..., "positional_or_keyword")),
1690 ...))
1691
1692 # Test that we handle method wrappers correctly
1693 def decorator(func):
1694 @functools.wraps(func)
1695 def wrapper(*args, **kwargs) -> int:
1696 return func(42, *args, **kwargs)
1697 sig = inspect.signature(func)
1698 new_params = tuple(sig.parameters.values())[1:]
1699 wrapper.__signature__ = sig.replace(parameters=new_params)
1700 return wrapper
1701
1702 class Foo:
1703 @decorator
1704 def __call__(self, a, b):
1705 pass
1706
1707 self.assertEqual(self.signature(Foo.__call__),
1708 ((('a', ..., ..., "positional_or_keyword"),
1709 ('b', ..., ..., "positional_or_keyword")),
1710 ...))
1711
1712 self.assertEqual(self.signature(Foo().__call__),
1713 ((('b', ..., ..., "positional_or_keyword"),),
1714 ...))
1715
1716 def test_signature_on_class(self):
1717 class C:
1718 def __init__(self, a):
1719 pass
1720
1721 self.assertEqual(self.signature(C),
1722 ((('a', ..., ..., "positional_or_keyword"),),
1723 ...))
1724
1725 class CM(type):
1726 def __call__(cls, a):
1727 pass
1728 class C(metaclass=CM):
1729 def __init__(self, b):
1730 pass
1731
1732 self.assertEqual(self.signature(C),
1733 ((('a', ..., ..., "positional_or_keyword"),),
1734 ...))
1735
1736 class CM(type):
1737 def __new__(mcls, name, bases, dct, *, foo=1):
1738 return super().__new__(mcls, name, bases, dct)
1739 class C(metaclass=CM):
1740 def __init__(self, b):
1741 pass
1742
1743 self.assertEqual(self.signature(C),
1744 ((('b', ..., ..., "positional_or_keyword"),),
1745 ...))
1746
1747 self.assertEqual(self.signature(CM),
1748 ((('name', ..., ..., "positional_or_keyword"),
1749 ('bases', ..., ..., "positional_or_keyword"),
1750 ('dct', ..., ..., "positional_or_keyword"),
1751 ('foo', 1, ..., "keyword_only")),
1752 ...))
1753
1754 class CMM(type):
1755 def __new__(mcls, name, bases, dct, *, foo=1):
1756 return super().__new__(mcls, name, bases, dct)
1757 def __call__(cls, nm, bs, dt):
1758 return type(nm, bs, dt)
1759 class CM(type, metaclass=CMM):
1760 def __new__(mcls, name, bases, dct, *, bar=2):
1761 return super().__new__(mcls, name, bases, dct)
1762 class C(metaclass=CM):
1763 def __init__(self, b):
1764 pass
1765
1766 self.assertEqual(self.signature(CMM),
1767 ((('name', ..., ..., "positional_or_keyword"),
1768 ('bases', ..., ..., "positional_or_keyword"),
1769 ('dct', ..., ..., "positional_or_keyword"),
1770 ('foo', 1, ..., "keyword_only")),
1771 ...))
1772
1773 self.assertEqual(self.signature(CM),
1774 ((('nm', ..., ..., "positional_or_keyword"),
1775 ('bs', ..., ..., "positional_or_keyword"),
1776 ('dt', ..., ..., "positional_or_keyword")),
1777 ...))
1778
1779 self.assertEqual(self.signature(C),
1780 ((('b', ..., ..., "positional_or_keyword"),),
1781 ...))
1782
1783 class CM(type):
1784 def __init__(cls, name, bases, dct, *, bar=2):
1785 return super().__init__(name, bases, dct)
1786 class C(metaclass=CM):
1787 def __init__(self, b):
1788 pass
1789
1790 self.assertEqual(self.signature(CM),
1791 ((('name', ..., ..., "positional_or_keyword"),
1792 ('bases', ..., ..., "positional_or_keyword"),
1793 ('dct', ..., ..., "positional_or_keyword"),
1794 ('bar', 2, ..., "keyword_only")),
1795 ...))
1796
1797 def test_signature_on_callable_objects(self):
1798 class Foo:
1799 def __call__(self, a):
1800 pass
1801
1802 self.assertEqual(self.signature(Foo()),
1803 ((('a', ..., ..., "positional_or_keyword"),),
1804 ...))
1805
1806 class Spam:
1807 pass
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001808 with self.assertRaisesRegex(TypeError, "is not a callable object"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001809 inspect.signature(Spam())
1810
1811 class Bar(Spam, Foo):
1812 pass
1813
1814 self.assertEqual(self.signature(Bar()),
1815 ((('a', ..., ..., "positional_or_keyword"),),
1816 ...))
1817
1818 class ToFail:
1819 __call__ = type
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001820 with self.assertRaisesRegex(ValueError, "not supported by signature"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001821 inspect.signature(ToFail())
1822
1823
1824 class Wrapped:
1825 pass
1826 Wrapped.__wrapped__ = lambda a: None
1827 self.assertEqual(self.signature(Wrapped),
1828 ((('a', ..., ..., "positional_or_keyword"),),
1829 ...))
1830
1831 def test_signature_on_lambdas(self):
1832 self.assertEqual(self.signature((lambda a=10: a)),
1833 ((('a', 10, ..., "positional_or_keyword"),),
1834 ...))
1835
1836 def test_signature_equality(self):
1837 def foo(a, *, b:int) -> float: pass
1838 self.assertNotEqual(inspect.signature(foo), 42)
1839
1840 def bar(a, *, b:int) -> float: pass
1841 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1842
1843 def bar(a, *, b:int) -> int: pass
1844 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1845
1846 def bar(a, *, b:int): pass
1847 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1848
1849 def bar(a, *, b:int=42) -> float: pass
1850 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1851
1852 def bar(a, *, c) -> float: pass
1853 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1854
1855 def bar(a, b:int) -> float: pass
1856 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1857 def spam(b:int, a) -> float: pass
1858 self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
1859
1860 def foo(*, a, b, c): pass
1861 def bar(*, c, b, a): pass
1862 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1863
1864 def foo(*, a=1, b, c): pass
1865 def bar(*, c, b, a=1): pass
1866 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1867
1868 def foo(pos, *, a=1, b, c): pass
1869 def bar(pos, *, c, b, a=1): pass
1870 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1871
1872 def foo(pos, *, a, b, c): pass
1873 def bar(pos, *, c, b, a=1): pass
1874 self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
1875
1876 def foo(pos, *args, a=42, b, c, **kwargs:int): pass
1877 def bar(pos, *args, c, b, a=42, **kwargs:int): pass
1878 self.assertEqual(inspect.signature(foo), inspect.signature(bar))
1879
1880 def test_signature_unhashable(self):
1881 def foo(a): pass
1882 sig = inspect.signature(foo)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001883 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001884 hash(sig)
1885
1886 def test_signature_str(self):
1887 def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
1888 pass
1889 self.assertEqual(str(inspect.signature(foo)),
1890 '(a:int=1, *, b, c=None, **kwargs) -> 42')
1891
1892 def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
1893 pass
1894 self.assertEqual(str(inspect.signature(foo)),
1895 '(a:int=1, *args, b, c=None, **kwargs) -> 42')
1896
1897 def foo():
1898 pass
1899 self.assertEqual(str(inspect.signature(foo)), '()')
1900
1901 def test_signature_str_positional_only(self):
1902 P = inspect.Parameter
1903
1904 def test(a_po, *, b, **kwargs):
1905 return a_po, kwargs
1906
1907 sig = inspect.signature(test)
1908 new_params = list(sig.parameters.values())
1909 new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
1910 test.__signature__ = sig.replace(parameters=new_params)
1911
1912 self.assertEqual(str(inspect.signature(test)),
1913 '(<a_po>, *, b, **kwargs)')
1914
1915 sig = inspect.signature(test)
1916 new_params = list(sig.parameters.values())
1917 new_params[0] = new_params[0].replace(name=None)
1918 test.__signature__ = sig.replace(parameters=new_params)
1919 self.assertEqual(str(inspect.signature(test)),
1920 '(<0>, *, b, **kwargs)')
1921
1922 def test_signature_replace_anno(self):
1923 def test() -> 42:
1924 pass
1925
1926 sig = inspect.signature(test)
1927 sig = sig.replace(return_annotation=None)
1928 self.assertIs(sig.return_annotation, None)
1929 sig = sig.replace(return_annotation=sig.empty)
1930 self.assertIs(sig.return_annotation, sig.empty)
1931 sig = sig.replace(return_annotation=42)
1932 self.assertEqual(sig.return_annotation, 42)
1933 self.assertEqual(sig, inspect.signature(test))
1934
1935
1936class TestParameterObject(unittest.TestCase):
1937 def test_signature_parameter_kinds(self):
1938 P = inspect.Parameter
1939 self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
1940 P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
1941
1942 self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
1943 self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
1944
1945 def test_signature_parameter_object(self):
1946 p = inspect.Parameter('foo', default=10,
1947 kind=inspect.Parameter.POSITIONAL_ONLY)
1948 self.assertEqual(p.name, 'foo')
1949 self.assertEqual(p.default, 10)
1950 self.assertIs(p.annotation, p.empty)
1951 self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
1952
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001953 with self.assertRaisesRegex(ValueError, 'invalid value'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001954 inspect.Parameter('foo', default=10, kind='123')
1955
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001956 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001957 inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
1958
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001959 with self.assertRaisesRegex(ValueError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001960 'non-positional-only parameter'):
1961 inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
1962
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001963 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001964 inspect.Parameter('a', default=42,
1965 kind=inspect.Parameter.VAR_KEYWORD)
1966
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001967 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001968 inspect.Parameter('a', default=42,
1969 kind=inspect.Parameter.VAR_POSITIONAL)
1970
1971 p = inspect.Parameter('a', default=42,
1972 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001973 with self.assertRaisesRegex(ValueError, 'cannot have default values'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001974 p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
1975
1976 self.assertTrue(repr(p).startswith('<Parameter'))
1977
1978 def test_signature_parameter_equality(self):
1979 P = inspect.Parameter
1980 p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
1981
1982 self.assertEqual(p, p)
1983 self.assertNotEqual(p, 42)
1984
1985 self.assertEqual(p, P('foo', default=42,
1986 kind=inspect.Parameter.KEYWORD_ONLY))
1987
1988 def test_signature_parameter_unhashable(self):
1989 p = inspect.Parameter('foo', default=42,
1990 kind=inspect.Parameter.KEYWORD_ONLY)
1991
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02001992 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07001993 hash(p)
1994
1995 def test_signature_parameter_replace(self):
1996 p = inspect.Parameter('foo', default=42,
1997 kind=inspect.Parameter.KEYWORD_ONLY)
1998
1999 self.assertIsNot(p, p.replace())
2000 self.assertEqual(p, p.replace())
2001
2002 p2 = p.replace(annotation=1)
2003 self.assertEqual(p2.annotation, 1)
2004 p2 = p2.replace(annotation=p2.empty)
2005 self.assertEqual(p, p2)
2006
2007 p2 = p2.replace(name='bar')
2008 self.assertEqual(p2.name, 'bar')
2009 self.assertNotEqual(p2, p)
2010
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002011 with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002012 p2 = p2.replace(name=p2.empty)
2013
2014 p2 = p2.replace(name='foo', default=None)
2015 self.assertIs(p2.default, None)
2016 self.assertNotEqual(p2, p)
2017
2018 p2 = p2.replace(name='foo', default=p2.empty)
2019 self.assertIs(p2.default, p2.empty)
2020
2021
2022 p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
2023 self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
2024 self.assertNotEqual(p2, p)
2025
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002026 with self.assertRaisesRegex(ValueError, 'invalid value for'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002027 p2 = p2.replace(kind=p2.empty)
2028
2029 p2 = p2.replace(kind=p2.KEYWORD_ONLY)
2030 self.assertEqual(p2, p)
2031
2032 def test_signature_parameter_positional_only(self):
2033 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2034 self.assertEqual(str(p), '<>')
2035
2036 p = p.replace(name='1')
2037 self.assertEqual(str(p), '<1>')
2038
2039 def test_signature_parameter_immutability(self):
2040 p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
2041
2042 with self.assertRaises(AttributeError):
2043 p.foo = 'bar'
2044
2045 with self.assertRaises(AttributeError):
2046 p.kind = 123
2047
2048
2049class TestSignatureBind(unittest.TestCase):
2050 @staticmethod
2051 def call(func, *args, **kwargs):
2052 sig = inspect.signature(func)
2053 ba = sig.bind(*args, **kwargs)
2054 return func(*ba.args, **ba.kwargs)
2055
2056 def test_signature_bind_empty(self):
2057 def test():
2058 return 42
2059
2060 self.assertEqual(self.call(test), 42)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002061 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002062 self.call(test, 1)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002063 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002064 self.call(test, 1, spam=10)
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002065 with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002066 self.call(test, spam=1)
2067
2068 def test_signature_bind_var(self):
2069 def test(*args, **kwargs):
2070 return args, kwargs
2071
2072 self.assertEqual(self.call(test), ((), {}))
2073 self.assertEqual(self.call(test, 1), ((1,), {}))
2074 self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
2075 self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
2076 self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
2077 self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
2078 self.assertEqual(self.call(test, 1, 2, foo='bar'),
2079 ((1, 2), {'foo': 'bar'}))
2080
2081 def test_signature_bind_just_args(self):
2082 def test(a, b, c):
2083 return a, b, c
2084
2085 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2086
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002087 with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002088 self.call(test, 1, 2, 3, 4)
2089
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002090 with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002091 self.call(test, 1)
2092
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002093 with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002094 self.call(test)
2095
2096 def test(a, b, c=10):
2097 return a, b, c
2098 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2099 self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
2100
2101 def test(a=1, b=2, c=3):
2102 return a, b, c
2103 self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
2104 self.assertEqual(self.call(test, a=10), (10, 2, 3))
2105 self.assertEqual(self.call(test, b=10), (1, 10, 3))
2106
2107 def test_signature_bind_varargs_order(self):
2108 def test(*args):
2109 return args
2110
2111 self.assertEqual(self.call(test), ())
2112 self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
2113
2114 def test_signature_bind_args_and_varargs(self):
2115 def test(a, b, c=3, *args):
2116 return a, b, c, args
2117
2118 self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
2119 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
2120 self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
2121 self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
2122
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002123 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002124 "multiple values for argument 'c'"):
2125 self.call(test, 1, 2, 3, c=4)
2126
2127 def test_signature_bind_just_kwargs(self):
2128 def test(**kwargs):
2129 return kwargs
2130
2131 self.assertEqual(self.call(test), {})
2132 self.assertEqual(self.call(test, foo='bar', spam='ham'),
2133 {'foo': 'bar', 'spam': 'ham'})
2134
2135 def test_signature_bind_args_and_kwargs(self):
2136 def test(a, b, c=3, **kwargs):
2137 return a, b, c, kwargs
2138
2139 self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
2140 self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
2141 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2142 self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
2143 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2144 self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
2145 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2146 self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
2147 (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
2148 self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
2149 (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
2150 self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
2151 (1, 2, 4, {'foo': 'bar'}))
2152 self.assertEqual(self.call(test, c=5, a=4, b=3),
2153 (4, 3, 5, {}))
2154
2155 def test_signature_bind_kwonly(self):
2156 def test(*, foo):
2157 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002158 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002159 'too many positional arguments'):
2160 self.call(test, 1)
2161 self.assertEqual(self.call(test, foo=1), 1)
2162
2163 def test(a, *, foo=1, bar):
2164 return foo
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002165 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002166 "'bar' parameter lacking default value"):
2167 self.call(test, 1)
2168
2169 def test(foo, *, bar):
2170 return foo, bar
2171 self.assertEqual(self.call(test, 1, bar=2), (1, 2))
2172 self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
2173
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002174 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002175 'too many keyword arguments'):
2176 self.call(test, bar=2, foo=1, spam=10)
2177
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002178 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002179 'too many positional arguments'):
2180 self.call(test, 1, 2)
2181
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002182 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002183 'too many positional arguments'):
2184 self.call(test, 1, 2, bar=2)
2185
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002186 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002187 'too many keyword arguments'):
2188 self.call(test, 1, bar=2, spam='ham')
2189
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002190 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002191 "'bar' parameter lacking default value"):
2192 self.call(test, 1)
2193
2194 def test(foo, *, bar, **bin):
2195 return foo, bar, bin
2196 self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
2197 self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
2198 self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
2199 (1, 2, {'spam': 'ham'}))
2200 self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
2201 (1, 2, {'spam': 'ham'}))
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002202 with self.assertRaisesRegex(TypeError,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002203 "'foo' parameter lacking default value"):
2204 self.call(test, spam='ham', bar=2)
2205 self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
2206 (1, 2, {'bin': 1, 'spam': 10}))
2207
2208 def test_signature_bind_arguments(self):
2209 def test(a, *args, b, z=100, **kwargs):
2210 pass
2211 sig = inspect.signature(test)
2212 ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
2213 # we won't have 'z' argument in the bound arguments object, as we didn't
2214 # pass it to the 'bind'
2215 self.assertEqual(tuple(ba.arguments.items()),
2216 (('a', 10), ('args', (20,)), ('b', 30),
2217 ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
2218 self.assertEqual(ba.kwargs,
2219 {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
2220 self.assertEqual(ba.args, (10, 20))
2221
2222 def test_signature_bind_positional_only(self):
2223 P = inspect.Parameter
2224
2225 def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
2226 return a_po, b_po, c_po, foo, bar, kwargs
2227
2228 sig = inspect.signature(test)
2229 new_params = collections.OrderedDict(tuple(sig.parameters.items()))
2230 for name in ('a_po', 'b_po', 'c_po'):
2231 new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
2232 new_sig = sig.replace(parameters=new_params.values())
2233 test.__signature__ = new_sig
2234
2235 self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
2236 (1, 2, 4, 5, 6, {}))
2237
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002238 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002239 self.call(test, 1, 2, c_po=4)
2240
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002241 with self.assertRaisesRegex(TypeError, "parameter is positional only"):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002242 self.call(test, a_po=1, b_po=2)
2243
Antoine Pitroubd41d1b2013-01-29 21:20:57 +01002244 def test_signature_bind_with_self_arg(self):
2245 # Issue #17071: one of the parameters is named "self
2246 def test(a, self, b):
2247 pass
2248 sig = inspect.signature(test)
2249 ba = sig.bind(1, 2, 3)
2250 self.assertEqual(ba.args, (1, 2, 3))
2251 ba = sig.bind(1, self=2, b=3)
2252 self.assertEqual(ba.args, (1, 2, 3))
2253
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002254
2255class TestBoundArguments(unittest.TestCase):
2256 def test_signature_bound_arguments_unhashable(self):
2257 def foo(a): pass
2258 ba = inspect.signature(foo).bind(1)
2259
Antoine Pitrou46cb1ef2012-06-23 18:11:59 +02002260 with self.assertRaisesRegex(TypeError, 'unhashable type'):
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002261 hash(ba)
2262
2263 def test_signature_bound_arguments_equality(self):
2264 def foo(a): pass
2265 ba = inspect.signature(foo).bind(1)
2266 self.assertEqual(ba, ba)
2267
2268 ba2 = inspect.signature(foo).bind(1)
2269 self.assertEqual(ba, ba2)
2270
2271 ba3 = inspect.signature(foo).bind(2)
2272 self.assertNotEqual(ba, ba3)
2273 ba3.arguments['a'] = 1
2274 self.assertEqual(ba, ba3)
2275
2276 def bar(b): pass
2277 ba4 = inspect.signature(bar).bind(1)
2278 self.assertNotEqual(ba, ba4)
2279
2280
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002281def test_main():
Benjamin Peterson25cd7eb2010-03-30 18:42:32 +00002282 run_unittest(
2283 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
2284 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
2285 TestGetcallargsFunctions, TestGetcallargsMethods,
Alexander Belopolskyf546e702010-12-02 00:10:11 +00002286 TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
Larry Hastings7c7cbfc2012-06-22 15:19:35 -07002287 TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
Nick Coghlan2f92e542012-06-23 19:39:55 +10002288 TestBoundArguments, TestGetClosureVars
Michael Foord95fc51d2010-11-20 15:07:30 +00002289 )
Martin v. Löwis893ffa42003-10-31 15:35:53 +00002290
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002291if __name__ == "__main__":
2292 test_main()