blob: 08630a59f7ea19ea5cb6f41392235bd2f9ed8690 [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
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000298class TestDecorators(GetSourceBase):
299 fodderFile = mod2
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000300
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000301 def test_wrapped_decorator(self):
302 self.assertSourceEqual(mod2.wrapped, 14, 17)
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000303
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000304 def test_replacing_decorator(self):
305 self.assertSourceEqual(mod2.gone, 9, 10)
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000306
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000307class TestOneliners(GetSourceBase):
308 fodderFile = mod2
309 def test_oneline_lambda(self):
310 # Test inspect.getsource with a one-line lambda function.
311 self.assertSourceEqual(mod2.oll, 25, 25)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000312
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000313 def test_threeline_lambda(self):
314 # Test inspect.getsource with a three-line lambda function,
315 # where the second and third lines are _not_ indented.
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000316 self.assertSourceEqual(mod2.tll, 28, 30)
317
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000318 def test_twoline_indented_lambda(self):
319 # Test inspect.getsource with a two-line lambda function,
320 # where the second line _is_ indented.
321 self.assertSourceEqual(mod2.tlli, 33, 34)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000322
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000323 def test_onelinefunc(self):
324 # Test inspect.getsource with a regular one-line function.
325 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000326
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000327 def test_manyargs(self):
328 # Test inspect.getsource with a regular function where
329 # the arguments are on two lines and _not_ indented and
330 # the body on the second line with the last arguments.
331 self.assertSourceEqual(mod2.manyargs, 40, 41)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000332
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000333 def test_twolinefunc(self):
334 # Test inspect.getsource with a regular function where
335 # the body is on two lines, following the argument list and
336 # continued on the next line by a \\.
337 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000338
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000339 def test_lambda_in_list(self):
340 # Test inspect.getsource with a one-line lambda function
341 # defined in a list, indented.
342 self.assertSourceEqual(mod2.a[1], 49, 49)
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000343
Johannes Gijsbers1542f342004-12-12 16:46:28 +0000344 def test_anonymous(self):
345 # Test inspect.getsource with a lambda function defined
346 # as argument to another function.
347 self.assertSourceEqual(mod2.anonymous, 55, 55)
348
Johannes Gijsbersa5855d52005-03-12 16:37:11 +0000349class TestBuggyCases(GetSourceBase):
350 fodderFile = mod2
351
352 def test_with_comment(self):
353 self.assertSourceEqual(mod2.with_comment, 58, 59)
354
355 def test_multiline_sig(self):
356 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
357
Armin Rigodd5c0232005-09-25 11:45:45 +0000358 def test_nested_class(self):
359 self.assertSourceEqual(mod2.func69().func71, 71, 72)
360
361 def test_one_liner_followed_by_non_name(self):
362 self.assertSourceEqual(mod2.func77, 77, 77)
363
364 def test_one_liner_dedent_non_name(self):
365 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
366
367 def test_with_comment_instead_of_docstring(self):
368 self.assertSourceEqual(mod2.func88, 88, 90)
369
Georg Brandl2463f8f2006-08-14 21:34:08 +0000370 def test_method_in_dynamic_class(self):
371 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
372
R. David Murray87855542009-05-14 16:12:57 +0000373 @unittest.skipIf(
374 not hasattr(unicodedata, '__file__') or
375 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
376 "unicodedata is not an external binary module")
R. David Murray996ba022009-05-13 17:14:11 +0000377 def test_findsource_binary(self):
R. David Murray87855542009-05-14 16:12:57 +0000378 self.assertRaises(IOError, inspect.getsource, unicodedata)
379 self.assertRaises(IOError, inspect.findsource, unicodedata)
R. David Murray996ba022009-05-13 17:14:11 +0000380
R. David Murraydf1cf302010-06-17 01:36:52 +0000381 def test_findsource_code_in_linecache(self):
382 lines = ["x=1"]
383 co = compile(lines[0], "_dynamically_created_file", "exec")
384 self.assertRaises(IOError, inspect.findsource, co)
385 self.assertRaises(IOError, inspect.getsource, co)
386 linecache.cache[co.co_filename] = (1, None, lines, co.co_filename)
387 self.assertEquals(inspect.findsource(co), (lines,0))
388 self.assertEquals(inspect.getsource(co), lines[0])
389
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000390# Helper for testing classify_class_attrs.
Tim Peters13b49d32001-09-23 02:00:29 +0000391def attrs_wo_objs(cls):
392 return [t[:3] for t in inspect.classify_class_attrs(cls)]
393
Tim Peters5a9fb3c2005-01-07 16:01:32 +0000394class TestClassesAndFunctions(unittest.TestCase):
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000395 def test_classic_mro(self):
396 # Test classic-class method resolution order.
397 class A: pass
398 class B(A): pass
399 class C(A): pass
400 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000401
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000402 expected = (D, B, A, C)
403 got = inspect.getmro(D)
404 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000405
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000406 def test_newstyle_mro(self):
407 # The same w/ new-class MRO.
408 class A(object): pass
409 class B(A): pass
410 class C(A): pass
411 class D(B, C): pass
Tim Peters13b49d32001-09-23 02:00:29 +0000412
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000413 expected = (D, B, C, A, object)
414 got = inspect.getmro(D)
415 self.assertEqual(expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000416
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000417 def assertArgSpecEquals(self, routine, args_e, varargs_e = None,
418 varkw_e = None, defaults_e = None,
419 formatted = None):
420 args, varargs, varkw, defaults = inspect.getargspec(routine)
421 self.assertEqual(args, args_e)
422 self.assertEqual(varargs, varargs_e)
423 self.assertEqual(varkw, varkw_e)
424 self.assertEqual(defaults, defaults_e)
425 if formatted is not None:
426 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
427 formatted)
Tim Peters13b49d32001-09-23 02:00:29 +0000428
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000429 def test_getargspec(self):
430 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted = '(x, y)')
Tim Peters13b49d32001-09-23 02:00:29 +0000431
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000432 self.assertArgSpecEquals(mod.spam,
433 ['a', 'b', 'c', 'd', ['e', ['f']]],
434 'g', 'h', (3, (4, (5,))),
435 '(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h)')
Tim Peters13b49d32001-09-23 02:00:29 +0000436
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000437 def test_getargspec_method(self):
438 class A(object):
439 def m(self):
440 pass
441 self.assertArgSpecEquals(A.m, ['self'])
Tim Peters13b49d32001-09-23 02:00:29 +0000442
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000443 def test_getargspec_sublistofone(self):
Florent Xicluna07627882010-03-21 01:14:24 +0000444 with check_py3k_warnings(
445 ("tuple parameter unpacking has been removed", SyntaxWarning),
446 ("parenthesized argument names are invalid", SyntaxWarning)):
447 exec 'def sublistOfOne((foo,)): return 1'
448 self.assertArgSpecEquals(sublistOfOne, [['foo']])
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000449
Florent Xicluna07627882010-03-21 01:14:24 +0000450 exec 'def fakeSublistOfOne((foo)): return 1'
451 self.assertArgSpecEquals(fakeSublistOfOne, ['foo'])
Neal Norwitz33b730e2006-03-27 08:58:23 +0000452
Jean-Paul Calderoneb60ee462010-04-10 19:59:28 +0000453
454 def _classify_test(self, newstyle):
455 """Helper for testing that classify_class_attrs finds a bunch of
456 different kinds of attributes on a given class.
457 """
458 if newstyle:
459 base = object
460 else:
461 class base:
462 pass
463
464 class A(base):
465 def s(): pass
466 s = staticmethod(s)
467
468 def c(cls): pass
469 c = classmethod(c)
470
471 def getp(self): pass
472 p = property(getp)
473
474 def m(self): pass
475
476 def m1(self): pass
477
478 datablob = '1'
479
480 attrs = attrs_wo_objs(A)
481 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
482 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
483 self.assertIn(('p', 'property', A), attrs, 'missing property')
484 self.assertIn(('m', 'method', A), attrs, 'missing plain method')
485 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
486 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
487
488 class B(A):
489 def m(self): pass
490
491 attrs = attrs_wo_objs(B)
492 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
493 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
494 self.assertIn(('p', 'property', A), attrs, 'missing property')
495 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
496 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
497 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
498
499
500 class C(A):
501 def m(self): pass
502 def c(self): pass
503
504 attrs = attrs_wo_objs(C)
505 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
506 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
507 self.assertIn(('p', 'property', A), attrs, 'missing property')
508 self.assertIn(('m', 'method', C), attrs, 'missing plain method')
509 self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
510 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
511
512 class D(B, C):
513 def m1(self): pass
514
515 attrs = attrs_wo_objs(D)
516 self.assertIn(('s', 'static method', A), attrs, 'missing static method')
517 if newstyle:
518 self.assertIn(('c', 'method', C), attrs, 'missing plain method')
519 else:
520 self.assertIn(('c', 'class method', A), attrs, 'missing class method')
521 self.assertIn(('p', 'property', A), attrs, 'missing property')
522 self.assertIn(('m', 'method', B), attrs, 'missing plain method')
523 self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
524 self.assertIn(('datablob', 'data', A), attrs, 'missing data')
525
526
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000527 def test_classify_oldstyle(self):
Jean-Paul Calderoneb60ee462010-04-10 19:59:28 +0000528 """classify_class_attrs finds static methods, class methods,
529 properties, normal methods, and data attributes on an old-style
530 class.
531 """
532 self._classify_test(False)
Tim Peters13b49d32001-09-23 02:00:29 +0000533
534
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000535 def test_classify_newstyle(self):
Jean-Paul Calderoneb60ee462010-04-10 19:59:28 +0000536 """Just like test_classify_oldstyle, but for a new-style class.
537 """
538 self._classify_test(True)
Tim Peters13b49d32001-09-23 02:00:29 +0000539
540
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000541
Benjamin Peterson7e213252010-03-30 17:58:13 +0000542class TestGetcallargsFunctions(unittest.TestCase):
543
544 # tuple parameters are named '.1', '.2', etc.
545 is_tuplename = re.compile(r'^\.\d+$').match
546
547 def assertEqualCallArgs(self, func, call_params_string, locs=None):
548 locs = dict(locs or {}, func=func)
549 r1 = eval('func(%s)' % call_params_string, None, locs)
550 r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None,
551 locs)
552 self.assertEqual(r1, r2)
553
554 def assertEqualException(self, func, call_param_string, locs=None):
555 locs = dict(locs or {}, func=func)
556 try:
557 eval('func(%s)' % call_param_string, None, locs)
558 except Exception, ex1:
559 pass
560 else:
561 self.fail('Exception not raised')
562 try:
563 eval('inspect.getcallargs(func, %s)' % call_param_string, None,
564 locs)
565 except Exception, ex2:
566 pass
567 else:
568 self.fail('Exception not raised')
569 self.assertIs(type(ex1), type(ex2))
570 self.assertEqual(str(ex1), str(ex2))
571
572 def makeCallable(self, signature):
573 """Create a function that returns its locals(), excluding the
574 autogenerated '.1', '.2', etc. tuple param names (if any)."""
Ezio Melottifcc500e2010-03-31 08:33:50 +0000575 with check_py3k_warnings(
576 ("tuple parameter unpacking has been removed", SyntaxWarning),
577 quiet=True):
578 code = ("lambda %s: dict(i for i in locals().items() "
579 "if not is_tuplename(i[0]))")
580 return eval(code % signature, {'is_tuplename' : self.is_tuplename})
Benjamin Peterson7e213252010-03-30 17:58:13 +0000581
582 def test_plain(self):
583 f = self.makeCallable('a, b=1')
584 self.assertEqualCallArgs(f, '2')
585 self.assertEqualCallArgs(f, '2, 3')
586 self.assertEqualCallArgs(f, 'a=2')
587 self.assertEqualCallArgs(f, 'b=3, a=2')
588 self.assertEqualCallArgs(f, '2, b=3')
589 # expand *iterable / **mapping
590 self.assertEqualCallArgs(f, '*(2,)')
591 self.assertEqualCallArgs(f, '*[2]')
592 self.assertEqualCallArgs(f, '*(2, 3)')
593 self.assertEqualCallArgs(f, '*[2, 3]')
594 self.assertEqualCallArgs(f, '**{"a":2}')
595 self.assertEqualCallArgs(f, 'b=3, **{"a":2}')
596 self.assertEqualCallArgs(f, '2, **{"b":3}')
597 self.assertEqualCallArgs(f, '**{"b":3, "a":2}')
598 # expand UserList / UserDict
599 self.assertEqualCallArgs(f, '*UserList([2])')
600 self.assertEqualCallArgs(f, '*UserList([2, 3])')
601 self.assertEqualCallArgs(f, '**UserDict(a=2)')
602 self.assertEqualCallArgs(f, '2, **UserDict(b=3)')
603 self.assertEqualCallArgs(f, 'b=2, **UserDict(a=3)')
604 # unicode keyword args
605 self.assertEqualCallArgs(f, '**{u"a":2}')
606 self.assertEqualCallArgs(f, 'b=3, **{u"a":2}')
607 self.assertEqualCallArgs(f, '2, **{u"b":3}')
608 self.assertEqualCallArgs(f, '**{u"b":3, u"a":2}')
609
610 def test_varargs(self):
611 f = self.makeCallable('a, b=1, *c')
612 self.assertEqualCallArgs(f, '2')
613 self.assertEqualCallArgs(f, '2, 3')
614 self.assertEqualCallArgs(f, '2, 3, 4')
615 self.assertEqualCallArgs(f, '*(2,3,4)')
616 self.assertEqualCallArgs(f, '2, *[3,4]')
617 self.assertEqualCallArgs(f, '2, 3, *UserList([4])')
618
619 def test_varkw(self):
620 f = self.makeCallable('a, b=1, **c')
621 self.assertEqualCallArgs(f, 'a=2')
622 self.assertEqualCallArgs(f, '2, b=3, c=4')
623 self.assertEqualCallArgs(f, 'b=3, a=2, c=4')
624 self.assertEqualCallArgs(f, 'c=4, **{"a":2, "b":3}')
625 self.assertEqualCallArgs(f, '2, c=4, **{"b":3}')
626 self.assertEqualCallArgs(f, 'b=2, **{"a":3, "c":4}')
627 self.assertEqualCallArgs(f, '**UserDict(a=2, b=3, c=4)')
628 self.assertEqualCallArgs(f, '2, c=4, **UserDict(b=3)')
629 self.assertEqualCallArgs(f, 'b=2, **UserDict(a=3, c=4)')
630 # unicode keyword args
631 self.assertEqualCallArgs(f, 'c=4, **{u"a":2, u"b":3}')
632 self.assertEqualCallArgs(f, '2, c=4, **{u"b":3}')
633 self.assertEqualCallArgs(f, 'b=2, **{u"a":3, u"c":4}')
634
635 def test_tupleargs(self):
636 f = self.makeCallable('(b,c), (d,(e,f))=(0,[1,2])')
637 self.assertEqualCallArgs(f, '(2,3)')
638 self.assertEqualCallArgs(f, '[2,3]')
639 self.assertEqualCallArgs(f, 'UserList([2,3])')
640 self.assertEqualCallArgs(f, '(2,3), (4,(5,6))')
641 self.assertEqualCallArgs(f, '(2,3), (4,[5,6])')
642 self.assertEqualCallArgs(f, '(2,3), [4,UserList([5,6])]')
643
644 def test_multiple_features(self):
645 f = self.makeCallable('a, b=2, (c,(d,e))=(3,[4,5]), *f, **g')
646 self.assertEqualCallArgs(f, '2, 3, (4,[5,6]), 7')
647 self.assertEqualCallArgs(f, '2, 3, *[(4,[5,6]), 7], x=8')
648 self.assertEqualCallArgs(f, '2, 3, x=8, *[(4,[5,6]), 7]')
649 self.assertEqualCallArgs(f, '2, x=8, *[3, (4,[5,6]), 7], y=9')
650 self.assertEqualCallArgs(f, 'x=8, *[2, 3, (4,[5,6])], y=9')
651 self.assertEqualCallArgs(f, 'x=8, *UserList([2, 3, (4,[5,6])]), '
652 '**{"y":9, "z":10}')
653 self.assertEqualCallArgs(f, '2, x=8, *UserList([3, (4,[5,6])]), '
654 '**UserDict(y=9, z=10)')
655
656 def test_errors(self):
657 f0 = self.makeCallable('')
658 f1 = self.makeCallable('a, b')
659 f2 = self.makeCallable('a, b=1')
660 # f0 takes no arguments
661 self.assertEqualException(f0, '1')
662 self.assertEqualException(f0, 'x=1')
663 self.assertEqualException(f0, '1,x=1')
664 # f1 takes exactly 2 arguments
665 self.assertEqualException(f1, '')
666 self.assertEqualException(f1, '1')
667 self.assertEqualException(f1, 'a=2')
668 self.assertEqualException(f1, 'b=3')
669 # f2 takes at least 1 argument
670 self.assertEqualException(f2, '')
671 self.assertEqualException(f2, 'b=3')
672 for f in f1, f2:
673 # f1/f2 takes exactly/at most 2 arguments
674 self.assertEqualException(f, '2, 3, 4')
675 self.assertEqualException(f, '1, 2, 3, a=1')
676 self.assertEqualException(f, '2, 3, 4, c=5')
677 self.assertEqualException(f, '2, 3, 4, a=1, c=5')
678 # f got an unexpected keyword argument
679 self.assertEqualException(f, 'c=2')
680 self.assertEqualException(f, '2, c=3')
681 self.assertEqualException(f, '2, 3, c=4')
682 self.assertEqualException(f, '2, c=4, b=3')
683 self.assertEqualException(f, '**{u"\u03c0\u03b9": 4}')
684 # f got multiple values for keyword argument
685 self.assertEqualException(f, '1, a=2')
686 self.assertEqualException(f, '1, **{"a":2}')
687 self.assertEqualException(f, '1, 2, b=3')
688 # XXX: Python inconsistency
689 # - for functions and bound methods: unexpected keyword 'c'
690 # - for unbound methods: multiple values for keyword 'a'
691 #self.assertEqualException(f, '1, c=3, a=2')
692 f = self.makeCallable('(a,b)=(0,1)')
693 self.assertEqualException(f, '1')
694 self.assertEqualException(f, '[1]')
695 self.assertEqualException(f, '(1,2,3)')
696
697class TestGetcallargsMethods(TestGetcallargsFunctions):
698
699 def setUp(self):
700 class Foo(object):
701 pass
702 self.cls = Foo
703 self.inst = Foo()
704
705 def makeCallable(self, signature):
706 assert 'self' not in signature
707 mk = super(TestGetcallargsMethods, self).makeCallable
708 self.cls.method = mk('self, ' + signature)
709 return self.inst.method
710
711class TestGetcallargsUnboundMethods(TestGetcallargsMethods):
712
713 def makeCallable(self, signature):
714 super(TestGetcallargsUnboundMethods, self).makeCallable(signature)
715 return self.cls.method
716
717 def assertEqualCallArgs(self, func, call_params_string, locs=None):
718 return super(TestGetcallargsUnboundMethods, self).assertEqualCallArgs(
719 *self._getAssertEqualParams(func, call_params_string, locs))
720
721 def assertEqualException(self, func, call_params_string, locs=None):
722 return super(TestGetcallargsUnboundMethods, self).assertEqualException(
723 *self._getAssertEqualParams(func, call_params_string, locs))
724
725 def _getAssertEqualParams(self, func, call_params_string, locs=None):
726 assert 'inst' not in call_params_string
727 locs = dict(locs or {}, inst=self.inst)
728 return (func, 'inst,' + call_params_string, locs)
729
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000730def test_main():
Benjamin Peterson7e213252010-03-30 17:58:13 +0000731 run_unittest(
732 TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
733 TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
734 TestGetcallargsFunctions, TestGetcallargsMethods,
735 TestGetcallargsUnboundMethods)
Martin v. Löwis893ffa42003-10-31 15:35:53 +0000736
Johannes Gijsberscb9015d2004-12-12 16:20:22 +0000737if __name__ == "__main__":
738 test_main()