blob: b8c9a1803c96a97ae5319f91c01f92d8d003df4f [file] [log] [blame]
Benjamin Peterson7e213252010-03-30 17:58:13 +00001import re
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00002import sys
Barry Warsaw00decd72006-07-27 23:43:15 +00003import types
Johannes Gijsberscb9015d2004-12-12 16:20:22 +00004import unittest
5import inspect
R. David Murraydf1cf302010-06-17 01:36:52 +00006import linecache
Barry Warsaw00decd72006-07-27 23:43:15 +00007import datetime
Benjamin Peterson7e213252010-03-30 17:58:13 +00008from UserList import UserList
9from UserDict import UserDict
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000010
Florent Xicluna07627882010-03-21 01:14:24 +000011from test.test_support import run_unittest, check_py3k_warnings
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000012
Florent Xicluna07627882010-03-21 01:14:24 +000013with check_py3k_warnings(
14 ("tuple parameter unpacking has been removed", SyntaxWarning),
15 quiet=True):
16 from test import inspect_fodder as mod
17 from test import inspect_fodder2 as mod2
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000018
R. David Murray996ba022009-05-13 17:14:11 +000019# C module for test_findsource_binary
R. David Murray87855542009-05-14 16:12:57 +000020import unicodedata
R. David Murray996ba022009-05-13 17:14:11 +000021
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000022# Functions tested in this suite:
23# ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
Facundo Batista759bfc62008-02-18 03:43:43 +000024# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
25# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
26# getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
27# currentframe, stack, trace, isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000028
Nick Coghlana2053472008-12-14 10:54:50 +000029# NOTE: There are some additional tests relating to interaction with
30# zipimport in the test_zipimport_support test module.
31
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000032modfile = mod.__file__
Georg Brandlb2afe852006-06-09 20:43:48 +000033if modfile.endswith(('c', 'o')):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000034 modfile = modfile[:-1]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000035
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000036import __builtin__
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000037
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000038try:
Florent Xicluna07627882010-03-21 01:14:24 +000039 1 // 0
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000040except:
41 tb = sys.exc_traceback
42
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000043git = mod.StupidGit()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000044
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000045class IsTestBase(unittest.TestCase):
46 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
47 inspect.isframe, inspect.isfunction, inspect.ismethod,
Facundo Batista759bfc62008-02-18 03:43:43 +000048 inspect.ismodule, inspect.istraceback,
49 inspect.isgenerator, inspect.isgeneratorfunction])
Tim Peters5a9fb3c2005-01-07 16:01:32 +000050
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000051 def istest(self, predicate, exp):
52 obj = eval(exp)
Benjamin Peterson5c8da862009-06-30 22:57:08 +000053 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
Tim Peters5a9fb3c2005-01-07 16:01:32 +000054
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000055 for other in self.predicates - set([predicate]):
Facundo Batista759bfc62008-02-18 03:43:43 +000056 if predicate == inspect.isgeneratorfunction and\
57 other == inspect.isfunction:
58 continue
Benjamin Peterson5c8da862009-06-30 22:57:08 +000059 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000060
Facundo Batista759bfc62008-02-18 03:43:43 +000061def generator_function_example(self):
62 for i in xrange(2):
63 yield i
64
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000065class TestPredicates(IsTestBase):
Christian Heimes728bee82008-03-03 20:30:29 +000066 def test_sixteen(self):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000067 count = len(filter(lambda x:x.startswith('is'), dir(inspect)))
Facundo Batista759bfc62008-02-18 03:43:43 +000068 # This test is here for remember you to update Doc/library/inspect.rst
Georg Brandl26bc1772008-03-03 20:39:00 +000069 # which claims there are 16 such functions
Christian Heimes728bee82008-03-03 20:30:29 +000070 expected = 16
Neal Norwitzdf80af72006-07-28 04:22:34 +000071 err_msg = "There are %d (not %d) is* functions" % (count, expected)
72 self.assertEqual(count, expected, err_msg)
Tim Peters5a9fb3c2005-01-07 16:01:32 +000073
Facundo Batista759bfc62008-02-18 03:43:43 +000074
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000075 def test_excluding_predicates(self):
76 self.istest(inspect.isbuiltin, 'sys.exit')
77 self.istest(inspect.isbuiltin, '[].append')
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000078 self.istest(inspect.iscode, 'mod.spam.func_code')
79 self.istest(inspect.isframe, 'tb.tb_frame')
80 self.istest(inspect.isfunction, 'mod.spam')
81 self.istest(inspect.ismethod, 'mod.StupidGit.abuse')
82 self.istest(inspect.ismethod, 'git.argue')
83 self.istest(inspect.ismodule, 'mod')
84 self.istest(inspect.istraceback, 'tb')
85 self.istest(inspect.isdatadescriptor, '__builtin__.file.closed')
86 self.istest(inspect.isdatadescriptor, '__builtin__.file.softspace')
Facundo Batista759bfc62008-02-18 03:43:43 +000087 self.istest(inspect.isgenerator, '(x for x in xrange(2))')
88 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
Barry Warsaw00decd72006-07-27 23:43:15 +000089 if hasattr(types, 'GetSetDescriptorType'):
90 self.istest(inspect.isgetsetdescriptor,
91 'type(tb.tb_frame).f_locals')
92 else:
Benjamin Peterson5c8da862009-06-30 22:57:08 +000093 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
Barry Warsaw00decd72006-07-27 23:43:15 +000094 if hasattr(types, 'MemberDescriptorType'):
95 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
96 else:
Benjamin Peterson5c8da862009-06-30 22:57:08 +000097 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000098
Johannes Gijsberscb9015d2004-12-12 16:20:22 +000099 def test_isroutine(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000100 self.assertTrue(inspect.isroutine(mod.spam))
101 self.assertTrue(inspect.isroutine([].count))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000102
Benjamin Peterson5e5fbb62009-01-17 22:27:54 +0000103 def test_isclass(self):
104 self.istest(inspect.isclass, 'mod.StupidGit')
105 self.assertTrue(inspect.isclass(list))
106
107 class newstyle(object): pass
108 self.assertTrue(inspect.isclass(newstyle))
109
110 class CustomGetattr(object):
111 def __getattr__(self, attr):
112 return None
113 self.assertFalse(inspect.isclass(CustomGetattr()))
114
Amaury Forgeot d'Arcb54447f2009-01-13 23:39:22 +0000115 def test_get_slot_members(self):
116 class C(object):
117 __slots__ = ("a", "b")
118
119 x = C()
120 x.a = 42
121 members = dict(inspect.getmembers(x))
Ezio Melottiaa980582010-01-23 23:04:36 +0000122 self.assertIn('a', members)
123 self.assertNotIn('b', members)
Amaury Forgeot d'Arcb54447f2009-01-13 23:39:22 +0000124
Benjamin Petersonc63457b2009-10-15 03:06:55 +0000125 def test_isabstract(self):
126 from abc import ABCMeta, abstractmethod
127
128 class AbstractClassExample(object):
129 __metaclass__ = ABCMeta
130
131 @abstractmethod
132 def foo(self):
133 pass
134
135 class ClassExample(AbstractClassExample):
136 def foo(self):
137 pass
138
139 a = ClassExample()
140
141 # Test general behaviour.
142 self.assertTrue(inspect.isabstract(AbstractClassExample))
143 self.assertFalse(inspect.isabstract(ClassExample))
144 self.assertFalse(inspect.isabstract(a))
145 self.assertFalse(inspect.isabstract(int))
146 self.assertFalse(inspect.isabstract(5))
147
Amaury Forgeot d'Arcb54447f2009-01-13 23:39:22 +0000148
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000149class TestInterpreterStack(IsTestBase):
150 def __init__(self, *args, **kwargs):
151 unittest.TestCase.__init__(self, *args, **kwargs)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000152
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000153 git.abuse(7, 8, 9)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000154
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000155 def test_abuse_done(self):
156 self.istest(inspect.istraceback, 'git.ex[2]')
157 self.istest(inspect.isframe, 'mod.fr')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000158
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000159 def test_stack(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000160 self.assertTrue(len(mod.st) >= 5)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000161 self.assertEqual(mod.st[0][1:],
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000162 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000163 self.assertEqual(mod.st[1][1:],
164 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
165 self.assertEqual(mod.st[2][1:],
166 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
167 self.assertEqual(mod.st[3][1:],
168 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000169
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000170 def test_trace(self):
171 self.assertEqual(len(git.tr), 3)
172 self.assertEqual(git.tr[0][1:], (modfile, 43, 'argue',
173 [' spam(a, b, c)\n'], 0))
174 self.assertEqual(git.tr[1][1:], (modfile, 9, 'spam',
175 [' eggs(b + d, c + f)\n'], 0))
176 self.assertEqual(git.tr[2][1:], (modfile, 18, 'eggs',
Mark Dickinsonc68e9f02010-02-03 16:50:14 +0000177 [' q = y // 0\n'], 0))
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000178
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000179 def test_frame(self):
180 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
181 self.assertEqual(args, ['x', 'y'])
182 self.assertEqual(varargs, None)
183 self.assertEqual(varkw, None)
184 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
185 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
186 '(x=11, y=14)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000187
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000188 def test_previous_frame(self):
189 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
190 self.assertEqual(args, ['a', 'b', 'c', 'd', ['e', ['f']]])
191 self.assertEqual(varargs, 'g')
192 self.assertEqual(varkw, 'h')
193 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
194 '(a=7, b=8, c=9, d=3, (e=4, (f=5,)), *g=(), **h={})')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000195
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000196class GetSourceBase(unittest.TestCase):
197 # Subclasses must override.
198 fodderFile = None
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000199
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000200 def __init__(self, *args, **kwargs):
201 unittest.TestCase.__init__(self, *args, **kwargs)
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000202
Philip Jenvey6a111022009-05-28 05:58:44 +0000203 with open(inspect.getsourcefile(self.fodderFile)) as fp:
204 self.source = fp.read()
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000205
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000206 def sourcerange(self, top, bottom):
207 lines = self.source.split("\n")
208 return "\n".join(lines[top-1:bottom]) + "\n"
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000209
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000210 def assertSourceEqual(self, obj, top, bottom):
211 self.assertEqual(inspect.getsource(obj),
212 self.sourcerange(top, bottom))
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000213
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000214class TestRetrievingSourceCode(GetSourceBase):
215 fodderFile = mod
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000216
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000217 def test_getclasses(self):
218 classes = inspect.getmembers(mod, inspect.isclass)
219 self.assertEqual(classes,
220 [('FesteringGob', mod.FesteringGob),
221 ('MalodorousPervert', mod.MalodorousPervert),
222 ('ParrotDroppings', mod.ParrotDroppings),
223 ('StupidGit', mod.StupidGit)])
224 tree = inspect.getclasstree([cls[1] for cls in classes], 1)
225 self.assertEqual(tree,
226 [(mod.ParrotDroppings, ()),
227 (mod.StupidGit, ()),
228 [(mod.MalodorousPervert, (mod.StupidGit,)),
229 [(mod.FesteringGob, (mod.MalodorousPervert,
230 mod.ParrotDroppings))
231 ]
232 ]
233 ])
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000234
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000235 def test_getfunctions(self):
236 functions = inspect.getmembers(mod, inspect.isfunction)
237 self.assertEqual(functions, [('eggs', mod.eggs),
238 ('spam', mod.spam)])
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000239
R. David Murrayf28fd242010-02-23 00:24:49 +0000240 @unittest.skipIf(sys.flags.optimize >= 2,
241 "Docstrings are omitted with -O2 and above")
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000242 def test_getdoc(self):
243 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
244 self.assertEqual(inspect.getdoc(mod.StupidGit),
245 'A longer,\n\nindented\n\ndocstring.')
246 self.assertEqual(inspect.getdoc(git.abuse),
247 'Another\n\ndocstring\n\ncontaining\n\ntabs')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000248
Georg Brandl7be19aa2008-06-07 15:59:10 +0000249 def test_cleandoc(self):
250 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
251 'An\nindented\ndocstring.')
252
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000253 def test_getcomments(self):
254 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
255 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000256
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000257 def test_getmodule(self):
Nick Coghlanc495c662006-09-07 10:50:34 +0000258 # Check actual module
259 self.assertEqual(inspect.getmodule(mod), mod)
260 # Check class (uses __module__ attribute)
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000261 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
Nick Coghlanc495c662006-09-07 10:50:34 +0000262 # Check a method (no __module__ attribute, falls back to filename)
263 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
264 # Do it again (check the caching isn't broken)
265 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
266 # Check a builtin
267 self.assertEqual(inspect.getmodule(str), sys.modules["__builtin__"])
268 # Check filename override
269 self.assertEqual(inspect.getmodule(None, modfile), mod)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000270
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000271 def test_getsource(self):
272 self.assertSourceEqual(git.abuse, 29, 39)
273 self.assertSourceEqual(mod.StupidGit, 21, 46)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000274
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000275 def test_getsourcefile(self):
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000276 self.assertEqual(inspect.getsourcefile(mod.spam), modfile)
277 self.assertEqual(inspect.getsourcefile(git.abuse), modfile)
R. David Murraydf1cf302010-06-17 01:36:52 +0000278 fn = "_non_existing_filename_used_for_sourcefile_test.py"
279 co = compile("None", fn, "exec")
280 self.assertEqual(inspect.getsourcefile(co), None)
281 linecache.cache[co.co_filename] = (1, None, "None", co.co_filename)
282 self.assertEqual(inspect.getsourcefile(co), fn)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000283
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000284 def test_getfile(self):
285 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000286
Phillip J. Eby5d86bdb2006-07-10 19:03:29 +0000287 def test_getmodule_recursion(self):
Christian Heimesc756d002007-11-27 21:34:01 +0000288 from types import ModuleType
Phillip J. Eby5d86bdb2006-07-10 19:03:29 +0000289 name = '__inspect_dummy'
Christian Heimesc756d002007-11-27 21:34:01 +0000290 m = sys.modules[name] = ModuleType(name)
Tim Peters722b8832006-07-10 21:11:49 +0000291 m.__file__ = "<string>" # hopefully not a real filename...
Phillip J. Eby5d86bdb2006-07-10 19:03:29 +0000292 m.__loader__ = "dummy" # pretend the filename is understood by a loader
293 exec "def x(): pass" in m.__dict__
294 self.assertEqual(inspect.getsourcefile(m.x.func_code), '<string>')
295 del sys.modules[name]
Phillip J. Eby1a2959c2006-07-20 15:54:16 +0000296 inspect.getmodule(compile('a=10','','single'))
Phillip J. Eby5d86bdb2006-07-10 19:03:29 +0000297
Benjamin Peterson0eb4ac42011-06-11 15:53:11 -0500298 def test_proceed_with_fake_filename(self):
299 '''doctest monkeypatches linecache to enable inspection'''
300 fn, source = '<test>', 'def x(): pass\n'
301 getlines = linecache.getlines
302 def monkey(filename, module_globals=None):
303 if filename == fn:
304 return source.splitlines(True)
305 else:
306 return getlines(filename, module_globals)
307 linecache.getlines = monkey
308 try:
309 ns = {}
310 exec compile(source, fn, 'single') in ns
311 inspect.getsource(ns["x"])
312 finally:
313 linecache.getlines = getlines
314
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000315class TestDecorators(GetSourceBase):
316 fodderFile = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000317
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000318 def test_wrapped_decorator(self):
319 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000320
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000321 def test_replacing_decorator(self):
322 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000323
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000324class TestOneliners(GetSourceBase):
325 fodderFile = mod2
326 def test_oneline_lambda(self):
327 # Test inspect.getsource with a one-line lambda function.
328 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000329
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000330 def test_threeline_lambda(self):
331 # Test inspect.getsource with a three-line lambda function,
332 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000333 self.assertSourceEqual(mod2.tll, 28, 30)
334
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000335 def test_twoline_indented_lambda(self):
336 # Test inspect.getsource with a two-line lambda function,
337 # where the second line _is_ indented.
338 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000339
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000340 def test_onelinefunc(self):
341 # Test inspect.getsource with a regular one-line function.
342 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000343
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000344 def test_manyargs(self):
345 # Test inspect.getsource with a regular function where
346 # the arguments are on two lines and _not_ indented and
347 # the body on the second line with the last arguments.
348 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000349
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000350 def test_twolinefunc(self):
351 # Test inspect.getsource with a regular function where
352 # the body is on two lines, following the argument list and
353 # continued on the next line by a \\.
354 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000355
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000356 def test_lambda_in_list(self):
357 # Test inspect.getsource with a one-line lambda function
358 # defined in a list, indented.
359 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000360
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000361 def test_anonymous(self):
362 # Test inspect.getsource with a lambda function defined
363 # as argument to another function.
364 self.assertSourceEqual(mod2.anonymous, 55, 55)
365
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000366class TestBuggyCases(GetSourceBase):
367 fodderFile = mod2
368
369 def test_with_comment(self):
370 self.assertSourceEqual(mod2.with_comment, 58, 59)
371
372 def test_multiline_sig(self):
373 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
374
Armin Rigodd5c0232005-09-25 11:45:45 +0000375 def test_nested_class(self):
376 self.assertSourceEqual(mod2.func69().func71, 71, 72)
377
378 def test_one_liner_followed_by_non_name(self):
379 self.assertSourceEqual(mod2.func77, 77, 77)
380
381 def test_one_liner_dedent_non_name(self):
382 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
383
384 def test_with_comment_instead_of_docstring(self):
385 self.assertSourceEqual(mod2.func88, 88, 90)
386
Georg Brandl2463f8f2006-08-14 21:34:08 +0000387 def test_method_in_dynamic_class(self):
388 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
389
R. David Murray87855542009-05-14 16:12:57 +0000390 @unittest.skipIf(
391 not hasattr(unicodedata, '__file__') or
392 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
393 "unicodedata is not an external binary module")
R. David Murray996ba022009-05-13 17:14:11 +0000394 def test_findsource_binary(self):
R. David Murray87855542009-05-14 16:12:57 +0000395 self.assertRaises(IOError, inspect.getsource, unicodedata)
396 self.assertRaises(IOError, inspect.findsource, unicodedata)
R. David Murray996ba022009-05-13 17:14:11 +0000397
R. David Murraydf1cf302010-06-17 01:36:52 +0000398 def test_findsource_code_in_linecache(self):
399 lines = ["x=1"]
400 co = compile(lines[0], "_dynamically_created_file", "exec")
401 self.assertRaises(IOError, inspect.findsource, co)
402 self.assertRaises(IOError, inspect.getsource, co)
403 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
Ezio Melotti2623a372010-11-21 13:34:58 +0000404 self.assertEqual(inspect.findsource(co), (lines,0))
405 self.assertEqual(inspect.getsource(co), lines[0])
R. David Murraydf1cf302010-06-17 01:36:52 +0000406
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000407# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000408def attrs_wo_objs(cls):
409 return [t[:3] for t in inspect.classify_class_attrs(cls)]
410
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000411class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000412 def test_classic_mro(self):
413 # Test classic-class method resolution order.
414 class A: pass
415 class B(A): pass
416 class C(A): pass
417 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000418
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000419 expected = (D, B, A, C)
420 got = inspect.getmro(D)
421 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000422
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000423 def test_newstyle_mro(self):
424 # The same w/ new-class MRO.
425 class A(object): pass
426 class B(A): pass
427 class C(A): pass
428 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000429
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000430 expected = (D, B, C, A, object)
431 got = inspect.getmro(D)
432 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000433
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000434 def assertArgSpecEquals(self, routine, args_e, varargs_e = None,
435 varkw_e = None, defaults_e = None,
436 formatted = None):
437 args, varargs, varkw, defaults = inspect.getargspec(routine)
438 self.assertEqual(args, args_e)
439 self.assertEqual(varargs, varargs_e)
440 self.assertEqual(varkw, varkw_e)
441 self.assertEqual(defaults, defaults_e)
442 if formatted is not None:
443 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
444 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000445
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000446 def test_getargspec(self):
447 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted = '(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000448
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000449 self.assertArgSpecEquals(mod.spam,
450 ['a', 'b', 'c', 'd', ['e', ['f']]],
451 'g', 'h', (3, (4, (5,))),
452 '(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000453
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000454 def test_getargspec_method(self):
455 class A(object):
456 def m(self):
457 pass
458 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000459
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000460 def test_getargspec_sublistofone(self):
Florent Xicluna07627882010-03-21 01:14:24 +0000461 with check_py3k_warnings(
462 ("tuple parameter unpacking has been removed", SyntaxWarning),
463 ("parenthesized argument names are invalid", SyntaxWarning)):
464 exec 'def sublistOfOne((foo,)): return 1'
465 self.assertArgSpecEquals(sublistOfOne, [['foo']])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000466
Florent Xicluna07627882010-03-21 01:14:24 +0000467 exec 'def fakeSublistOfOne((foo)): return 1'
468 self.assertArgSpecEquals(fakeSublistOfOne, ['foo'])
Neal Norwitz33b730e2006-03-27 08:58:23 +0000469
Jean-Paul Calderoneb60ee462010-04-10 19:59:28 +0000470
471 def _classify_test(self, newstyle):
472 """Helper for testing that classify_class_attrs finds a bunch of
473 different kinds of attributes on a given class.
474 """
475 if newstyle:
476 base = object
477 else:
478 class base:
479 pass
480
481 class A(base):
482 def s(): pass
483 s = staticmethod(s)
484
485 def c(cls): pass
486 c = classmethod(c)
487
488 def getp(self): pass
489 p = property(getp)
490
491 def m(self): pass
492
493 def m1(self): pass
494
495 datablob = '1'
496
497 attrs = attrs_wo_objs(A)
498 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
499 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
500 self.assertIn(('p', 'property', A), attrs, 'missing property')
501 self.assertIn(('m', 'method', A), attrs, 'missing plain method')
502 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
503 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
504
505 class B(A):
506 def m(self): pass
507
508 attrs = attrs_wo_objs(B)
509 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
510 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
511 self.assertIn(('p', 'property', A), attrs, 'missing property')
512 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
513 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
514 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
515
516
517 class C(A):
518 def m(self): pass
519 def c(self): pass
520
521 attrs = attrs_wo_objs(C)
522 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
523 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
524 self.assertIn(('p', 'property', A), attrs, 'missing property')
525 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
526 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
527 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
528
529 class D(B, C):
530 def m1(self): pass
531
532 attrs = attrs_wo_objs(D)
533 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
534 if newstyle:
535 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
536 else:
537 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
538 self.assertIn(('p', 'property', A), attrs, 'missing property')
539 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
540 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
541 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
542
543
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000544 def test_classify_oldstyle(self):
Jean-Paul Calderoneb60ee462010-04-10 19:59:28 +0000545 """classify_class_attrs finds static methods, class methods,
546 properties, normal methods, and data attributes on an old-style
547 class.
548 """
549 self._classify_test(False)
Tim Peters13b49d32001-09-23 02:00:29 +0000550
551
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000552 def test_classify_newstyle(self):
Jean-Paul Calderoneb60ee462010-04-10 19:59:28 +0000553 """Just like test_classify_oldstyle, but for a new-style class.
554 """
555 self._classify_test(True)
Tim Peters13b49d32001-09-23 02:00:29 +0000556
557
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000558
Benjamin Peterson7e213252010-03-30 17:58:13 +0000559class TestGetcallargsFunctions(unittest.TestCase):
560
561 # tuple parameters are named '.1', '.2', etc.
562 is_tuplename = re.compile(r'^\.\d+$').match
563
564 def assertEqualCallArgs(self, func, call_params_string, locs=None):
565 locs = dict(locs or {}, func=func)
566 r1 = eval('func(%s)' % call_params_string, None, locs)
567 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
568 locs)
569 self.assertEqual(r1, r2)
570
571 def assertEqualException(self, func, call_param_string, locs=None):
572 locs = dict(locs or {}, func=func)
573 try:
574 eval('func(%s)' % call_param_string, None, locs)
575 except Exception, ex1:
576 pass
577 else:
578 self.fail('Exception not raised')
579 try:
580 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
581 locs)
582 except Exception, ex2:
583 pass
584 else:
585 self.fail('Exception not raised')
586 self.assertIs(type(ex1), type(ex2))
587 self.assertEqual(str(ex1), str(ex2))
588
589 def makeCallable(self, signature):
590 """Create a function that returns its locals(), excluding the
591 autogenerated '.1', '.2', etc. tuple param names (if any)."""
Ezio Melottifcc500e2010-03-31 08:33:50 +0000592 with check_py3k_warnings(
593 ("tuple parameter unpacking has been removed", SyntaxWarning),
594 quiet=True):
595 code = ("lambda %s: dict(i for i in locals().items() "
596 "if not is_tuplename(i[0]))")
597 return eval(code % signature, {'is_tuplename' : self.is_tuplename})
Benjamin Peterson7e213252010-03-30 17:58:13 +0000598
599 def test_plain(self):
600 f = self.makeCallable('a, b=1')
601 self.assertEqualCallArgs(f, '2')
602 self.assertEqualCallArgs(f, '2, 3')
603 self.assertEqualCallArgs(f, 'a=2')
604 self.assertEqualCallArgs(f, 'b=3, a=2')
605 self.assertEqualCallArgs(f, '2, b=3')
606 # expand *iterable / **mapping
607 self.assertEqualCallArgs(f, '*(2,)')
608 self.assertEqualCallArgs(f, '*[2]')
609 self.assertEqualCallArgs(f, '*(2, 3)')
610 self.assertEqualCallArgs(f, '*[2, 3]')
611 self.assertEqualCallArgs(f, '**{"a":2}')
612 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
613 self.assertEqualCallArgs(f, '2, **{"b":3}')
614 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
615 # expand UserList / UserDict
616 self.assertEqualCallArgs(f, '*UserList([2])')
617 self.assertEqualCallArgs(f, '*UserList([2, 3])')
618 self.assertEqualCallArgs(f, '**UserDict(a=2)')
619 self.assertEqualCallArgs(f, '2, **UserDict(b=3)')
620 self.assertEqualCallArgs(f, 'b=2, **UserDict(a=3)')
621 # unicode keyword args
622 self.assertEqualCallArgs(f, '**{u"a":2}')
623 self.assertEqualCallArgs(f, 'b=3, **{u"a":2}')
624 self.assertEqualCallArgs(f, '2, **{u"b":3}')
625 self.assertEqualCallArgs(f, '**{u"b":3, u"a":2}')
626
627 def test_varargs(self):
628 f = self.makeCallable('a, b=1, *c')
629 self.assertEqualCallArgs(f, '2')
630 self.assertEqualCallArgs(f, '2, 3')
631 self.assertEqualCallArgs(f, '2, 3, 4')
632 self.assertEqualCallArgs(f, '*(2,3,4)')
633 self.assertEqualCallArgs(f, '2, *[3,4]')
634 self.assertEqualCallArgs(f, '2, 3, *UserList([4])')
635
636 def test_varkw(self):
637 f = self.makeCallable('a, b=1, **c')
638 self.assertEqualCallArgs(f, 'a=2')
639 self.assertEqualCallArgs(f, '2, b=3, c=4')
640 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
641 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
642 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
643 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
644 self.assertEqualCallArgs(f, '**UserDict(a=2, b=3, c=4)')
645 self.assertEqualCallArgs(f, '2, c=4, **UserDict(b=3)')
646 self.assertEqualCallArgs(f, 'b=2, **UserDict(a=3, c=4)')
647 # unicode keyword args
648 self.assertEqualCallArgs(f, 'c=4, **{u"a":2, u"b":3}')
649 self.assertEqualCallArgs(f, '2, c=4, **{u"b":3}')
650 self.assertEqualCallArgs(f, 'b=2, **{u"a":3, u"c":4}')
651
Benjamin Peterson77d46602011-03-28 17:32:31 -0500652 def test_varkw_only(self):
653 # issue11256:
654 f = self.makeCallable('**c')
655 self.assertEqualCallArgs(f, '')
656 self.assertEqualCallArgs(f, 'a=1')
657 self.assertEqualCallArgs(f, 'a=1, b=2')
658 self.assertEqualCallArgs(f, 'c=3, **{"a": 1, "b": 2}')
659 self.assertEqualCallArgs(f, '**UserDict(a=1, b=2)')
660 self.assertEqualCallArgs(f, 'c=3, **UserDict(a=1, b=2)')
661
Benjamin Peterson7e213252010-03-30 17:58:13 +0000662 def test_tupleargs(self):
663 f = self.makeCallable('(b,c), (d,(e,f))=(0,[1,2])')
664 self.assertEqualCallArgs(f, '(2,3)')
665 self.assertEqualCallArgs(f, '[2,3]')
666 self.assertEqualCallArgs(f, 'UserList([2,3])')
667 self.assertEqualCallArgs(f, '(2,3), (4,(5,6))')
668 self.assertEqualCallArgs(f, '(2,3), (4,[5,6])')
669 self.assertEqualCallArgs(f, '(2,3), [4,UserList([5,6])]')
670
671 def test_multiple_features(self):
672 f = self.makeCallable('a, b=2, (c,(d,e))=(3,[4,5]), *f, **g')
673 self.assertEqualCallArgs(f, '2, 3, (4,[5,6]), 7')
674 self.assertEqualCallArgs(f, '2, 3, *[(4,[5,6]), 7], x=8')
675 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
676 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
677 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
678 self.assertEqualCallArgs(f, 'x=8, *UserList([2, 3, (4,[5,6])]), '
679 '**{"y":9, "z":10}')
680 self.assertEqualCallArgs(f, '2, x=8, *UserList([3, (4,[5,6])]), '
681 '**UserDict(y=9, z=10)')
682
683 def test_errors(self):
684 f0 = self.makeCallable('')
685 f1 = self.makeCallable('a, b')
686 f2 = self.makeCallable('a, b=1')
687 # f0 takes no arguments
688 self.assertEqualException(f0, '1')
689 self.assertEqualException(f0, 'x=1')
690 self.assertEqualException(f0, '1,x=1')
691 # f1 takes exactly 2 arguments
692 self.assertEqualException(f1, '')
693 self.assertEqualException(f1, '1')
694 self.assertEqualException(f1, 'a=2')
695 self.assertEqualException(f1, 'b=3')
696 # f2 takes at least 1 argument
697 self.assertEqualException(f2, '')
698 self.assertEqualException(f2, 'b=3')
699 for f in f1, f2:
700 # f1/f2 takes exactly/at most 2 arguments
701 self.assertEqualException(f, '2, 3, 4')
702 self.assertEqualException(f, '1, 2, 3, a=1')
703 self.assertEqualException(f, '2, 3, 4, c=5')
704 self.assertEqualException(f, '2, 3, 4, a=1, c=5')
705 # f got an unexpected keyword argument
706 self.assertEqualException(f, 'c=2')
707 self.assertEqualException(f, '2, c=3')
708 self.assertEqualException(f, '2, 3, c=4')
709 self.assertEqualException(f, '2, c=4, b=3')
710 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
711 # f got multiple values for keyword argument
712 self.assertEqualException(f, '1, a=2')
713 self.assertEqualException(f, '1, **{"a":2}')
714 self.assertEqualException(f, '1, 2, b=3')
715 # XXX: Python inconsistency
716 # - for functions and bound methods: unexpected keyword 'c'
717 # - for unbound methods: multiple values for keyword 'a'
718 #self.assertEqualException(f, '1, c=3, a=2')
719 f = self.makeCallable('(a,b)=(0,1)')
720 self.assertEqualException(f, '1')
721 self.assertEqualException(f, '[1]')
722 self.assertEqualException(f, '(1,2,3)')
Benjamin Peterson77d46602011-03-28 17:32:31 -0500723 # issue11256:
724 f3 = self.makeCallable('**c')
725 self.assertEqualException(f3, '1, 2')
726 self.assertEqualException(f3, '1, 2, a=1, b=2')
Benjamin Peterson7e213252010-03-30 17:58:13 +0000727
728class TestGetcallargsMethods(TestGetcallargsFunctions):
729
730 def setUp(self):
731 class Foo(object):
732 pass
733 self.cls = Foo
734 self.inst = Foo()
735
736 def makeCallable(self, signature):
737 assert 'self' not in signature
738 mk = super(TestGetcallargsMethods, self).makeCallable
739 self.cls.method = mk('self, ' + signature)
740 return self.inst.method
741
742class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
743
744 def makeCallable(self, signature):
745 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
746 return self.cls.method
747
748 def assertEqualCallArgs(self, func, call_params_string, locs=None):
749 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
750 *self._getAssertEqualParams(func, call_params_string, locs))
751
752 def assertEqualException(self, func, call_params_string, locs=None):
753 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
754 *self._getAssertEqualParams(func, call_params_string, locs))
755
756 def _getAssertEqualParams(self, func, call_params_string, locs=None):
757 assert 'inst' not in call_params_string
758 locs = dict(locs or {}, inst=self.inst)
759 return (func, 'inst,' + call_params_string, locs)
760
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000761def test_main():
Benjamin Peterson7e213252010-03-30 17:58:13 +0000762 run_unittest(
763 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
764 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
765 TestGetcallargsFunctions, TestGetcallargsMethods,
766 TestGetcallargsUnboundMethods)
Martin v. Löwis893ffa42003-10-31 15:35:53 +0000767
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000768if __name__ == "__main__":
769 test_main()