Add better error reporting for MemoryErrors caused by str->float conversions.
[python.git] / Lib / test / test_inspect.py
blobf20b26ceb04229f9d4332affc5252254c72909e9
1 import sys
2 import types
3 import unittest
4 import inspect
5 import datetime
7 from test.test_support import TESTFN, run_unittest
9 from test import inspect_fodder as mod
10 from test import inspect_fodder2 as mod2
12 # C module for test_findsource_binary
13 import unicodedata
15 # Functions tested in this suite:
16 # ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
17 # isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
18 # getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
19 # getclasstree, getargspec, getargvalues, formatargspec, formatargvalues,
20 # currentframe, stack, trace, isdatadescriptor
22 # NOTE: There are some additional tests relating to interaction with
23 # zipimport in the test_zipimport_support test module.
25 modfile = mod.__file__
26 if modfile.endswith(('c', 'o')):
27 modfile = modfile[:-1]
29 import __builtin__
31 try:
32 1/0
33 except:
34 tb = sys.exc_traceback
36 git = mod.StupidGit()
38 class IsTestBase(unittest.TestCase):
39 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
40 inspect.isframe, inspect.isfunction, inspect.ismethod,
41 inspect.ismodule, inspect.istraceback,
42 inspect.isgenerator, inspect.isgeneratorfunction])
44 def istest(self, predicate, exp):
45 obj = eval(exp)
46 self.assertTrue(predicate(obj), '%s(%s)' % (predicate.__name__, exp))
48 for other in self.predicates - set([predicate]):
49 if predicate == inspect.isgeneratorfunction and\
50 other == inspect.isfunction:
51 continue
52 self.assertFalse(other(obj), 'not %s(%s)' % (other.__name__, exp))
54 def generator_function_example(self):
55 for i in xrange(2):
56 yield i
58 class TestPredicates(IsTestBase):
59 def test_sixteen(self):
60 count = len(filter(lambda x:x.startswith('is'), dir(inspect)))
61 # This test is here for remember you to update Doc/library/inspect.rst
62 # which claims there are 16 such functions
63 expected = 16
64 err_msg = "There are %d (not %d) is* functions" % (count, expected)
65 self.assertEqual(count, expected, err_msg)
68 def test_excluding_predicates(self):
69 self.istest(inspect.isbuiltin, 'sys.exit')
70 self.istest(inspect.isbuiltin, '[].append')
71 self.istest(inspect.iscode, 'mod.spam.func_code')
72 self.istest(inspect.isframe, 'tb.tb_frame')
73 self.istest(inspect.isfunction, 'mod.spam')
74 self.istest(inspect.ismethod, 'mod.StupidGit.abuse')
75 self.istest(inspect.ismethod, 'git.argue')
76 self.istest(inspect.ismodule, 'mod')
77 self.istest(inspect.istraceback, 'tb')
78 self.istest(inspect.isdatadescriptor, '__builtin__.file.closed')
79 self.istest(inspect.isdatadescriptor, '__builtin__.file.softspace')
80 self.istest(inspect.isgenerator, '(x for x in xrange(2))')
81 self.istest(inspect.isgeneratorfunction, 'generator_function_example')
82 if hasattr(types, 'GetSetDescriptorType'):
83 self.istest(inspect.isgetsetdescriptor,
84 'type(tb.tb_frame).f_locals')
85 else:
86 self.assertFalse(inspect.isgetsetdescriptor(type(tb.tb_frame).f_locals))
87 if hasattr(types, 'MemberDescriptorType'):
88 self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
89 else:
90 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
92 def test_isroutine(self):
93 self.assertTrue(inspect.isroutine(mod.spam))
94 self.assertTrue(inspect.isroutine([].count))
96 def test_isclass(self):
97 self.istest(inspect.isclass, 'mod.StupidGit')
98 self.assertTrue(inspect.isclass(list))
100 class newstyle(object): pass
101 self.assertTrue(inspect.isclass(newstyle))
103 class CustomGetattr(object):
104 def __getattr__(self, attr):
105 return None
106 self.assertFalse(inspect.isclass(CustomGetattr()))
108 def test_get_slot_members(self):
109 class C(object):
110 __slots__ = ("a", "b")
112 x = C()
113 x.a = 42
114 members = dict(inspect.getmembers(x))
115 self.assertTrue('a' in members)
116 self.assertTrue('b' not in members)
118 def test_isabstract(self):
119 from abc import ABCMeta, abstractmethod
121 class AbstractClassExample(object):
122 __metaclass__ = ABCMeta
124 @abstractmethod
125 def foo(self):
126 pass
128 class ClassExample(AbstractClassExample):
129 def foo(self):
130 pass
132 a = ClassExample()
134 # Test general behaviour.
135 self.assertTrue(inspect.isabstract(AbstractClassExample))
136 self.assertFalse(inspect.isabstract(ClassExample))
137 self.assertFalse(inspect.isabstract(a))
138 self.assertFalse(inspect.isabstract(int))
139 self.assertFalse(inspect.isabstract(5))
142 class TestInterpreterStack(IsTestBase):
143 def __init__(self, *args, **kwargs):
144 unittest.TestCase.__init__(self, *args, **kwargs)
146 git.abuse(7, 8, 9)
148 def test_abuse_done(self):
149 self.istest(inspect.istraceback, 'git.ex[2]')
150 self.istest(inspect.isframe, 'mod.fr')
152 def test_stack(self):
153 self.assertTrue(len(mod.st) >= 5)
154 self.assertEqual(mod.st[0][1:],
155 (modfile, 16, 'eggs', [' st = inspect.stack()\n'], 0))
156 self.assertEqual(mod.st[1][1:],
157 (modfile, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
158 self.assertEqual(mod.st[2][1:],
159 (modfile, 43, 'argue', [' spam(a, b, c)\n'], 0))
160 self.assertEqual(mod.st[3][1:],
161 (modfile, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
163 def test_trace(self):
164 self.assertEqual(len(git.tr), 3)
165 self.assertEqual(git.tr[0][1:], (modfile, 43, 'argue',
166 [' spam(a, b, c)\n'], 0))
167 self.assertEqual(git.tr[1][1:], (modfile, 9, 'spam',
168 [' eggs(b + d, c + f)\n'], 0))
169 self.assertEqual(git.tr[2][1:], (modfile, 18, 'eggs',
170 [' q = y / 0\n'], 0))
172 def test_frame(self):
173 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
174 self.assertEqual(args, ['x', 'y'])
175 self.assertEqual(varargs, None)
176 self.assertEqual(varkw, None)
177 self.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
178 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
179 '(x=11, y=14)')
181 def test_previous_frame(self):
182 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
183 self.assertEqual(args, ['a', 'b', 'c', 'd', ['e', ['f']]])
184 self.assertEqual(varargs, 'g')
185 self.assertEqual(varkw, 'h')
186 self.assertEqual(inspect.formatargvalues(args, varargs, varkw, locals),
187 '(a=7, b=8, c=9, d=3, (e=4, (f=5,)), *g=(), **h={})')
189 class GetSourceBase(unittest.TestCase):
190 # Subclasses must override.
191 fodderFile = None
193 def __init__(self, *args, **kwargs):
194 unittest.TestCase.__init__(self, *args, **kwargs)
196 with open(inspect.getsourcefile(self.fodderFile)) as fp:
197 self.source = fp.read()
199 def sourcerange(self, top, bottom):
200 lines = self.source.split("\n")
201 return "\n".join(lines[top-1:bottom]) + "\n"
203 def assertSourceEqual(self, obj, top, bottom):
204 self.assertEqual(inspect.getsource(obj),
205 self.sourcerange(top, bottom))
207 class TestRetrievingSourceCode(GetSourceBase):
208 fodderFile = mod
210 def test_getclasses(self):
211 classes = inspect.getmembers(mod, inspect.isclass)
212 self.assertEqual(classes,
213 [('FesteringGob', mod.FesteringGob),
214 ('MalodorousPervert', mod.MalodorousPervert),
215 ('ParrotDroppings', mod.ParrotDroppings),
216 ('StupidGit', mod.StupidGit)])
217 tree = inspect.getclasstree([cls[1] for cls in classes], 1)
218 self.assertEqual(tree,
219 [(mod.ParrotDroppings, ()),
220 (mod.StupidGit, ()),
221 [(mod.MalodorousPervert, (mod.StupidGit,)),
222 [(mod.FesteringGob, (mod.MalodorousPervert,
223 mod.ParrotDroppings))
228 def test_getfunctions(self):
229 functions = inspect.getmembers(mod, inspect.isfunction)
230 self.assertEqual(functions, [('eggs', mod.eggs),
231 ('spam', mod.spam)])
233 def test_getdoc(self):
234 self.assertEqual(inspect.getdoc(mod), 'A module docstring.')
235 self.assertEqual(inspect.getdoc(mod.StupidGit),
236 'A longer,\n\nindented\n\ndocstring.')
237 self.assertEqual(inspect.getdoc(git.abuse),
238 'Another\n\ndocstring\n\ncontaining\n\ntabs')
240 def test_cleandoc(self):
241 self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'),
242 'An\nindented\ndocstring.')
244 def test_getcomments(self):
245 self.assertEqual(inspect.getcomments(mod), '# line 1\n')
246 self.assertEqual(inspect.getcomments(mod.StupidGit), '# line 20\n')
248 def test_getmodule(self):
249 # Check actual module
250 self.assertEqual(inspect.getmodule(mod), mod)
251 # Check class (uses __module__ attribute)
252 self.assertEqual(inspect.getmodule(mod.StupidGit), mod)
253 # Check a method (no __module__ attribute, falls back to filename)
254 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
255 # Do it again (check the caching isn't broken)
256 self.assertEqual(inspect.getmodule(mod.StupidGit.abuse), mod)
257 # Check a builtin
258 self.assertEqual(inspect.getmodule(str), sys.modules["__builtin__"])
259 # Check filename override
260 self.assertEqual(inspect.getmodule(None, modfile), mod)
262 def test_getsource(self):
263 self.assertSourceEqual(git.abuse, 29, 39)
264 self.assertSourceEqual(mod.StupidGit, 21, 46)
266 def test_getsourcefile(self):
267 self.assertEqual(inspect.getsourcefile(mod.spam), modfile)
268 self.assertEqual(inspect.getsourcefile(git.abuse), modfile)
270 def test_getfile(self):
271 self.assertEqual(inspect.getfile(mod.StupidGit), mod.__file__)
273 def test_getmodule_recursion(self):
274 from types import ModuleType
275 name = '__inspect_dummy'
276 m = sys.modules[name] = ModuleType(name)
277 m.__file__ = "<string>" # hopefully not a real filename...
278 m.__loader__ = "dummy" # pretend the filename is understood by a loader
279 exec "def x(): pass" in m.__dict__
280 self.assertEqual(inspect.getsourcefile(m.x.func_code), '<string>')
281 del sys.modules[name]
282 inspect.getmodule(compile('a=10','','single'))
284 class TestDecorators(GetSourceBase):
285 fodderFile = mod2
287 def test_wrapped_decorator(self):
288 self.assertSourceEqual(mod2.wrapped, 14, 17)
290 def test_replacing_decorator(self):
291 self.assertSourceEqual(mod2.gone, 9, 10)
293 class TestOneliners(GetSourceBase):
294 fodderFile = mod2
295 def test_oneline_lambda(self):
296 # Test inspect.getsource with a one-line lambda function.
297 self.assertSourceEqual(mod2.oll, 25, 25)
299 def test_threeline_lambda(self):
300 # Test inspect.getsource with a three-line lambda function,
301 # where the second and third lines are _not_ indented.
302 self.assertSourceEqual(mod2.tll, 28, 30)
304 def test_twoline_indented_lambda(self):
305 # Test inspect.getsource with a two-line lambda function,
306 # where the second line _is_ indented.
307 self.assertSourceEqual(mod2.tlli, 33, 34)
309 def test_onelinefunc(self):
310 # Test inspect.getsource with a regular one-line function.
311 self.assertSourceEqual(mod2.onelinefunc, 37, 37)
313 def test_manyargs(self):
314 # Test inspect.getsource with a regular function where
315 # the arguments are on two lines and _not_ indented and
316 # the body on the second line with the last arguments.
317 self.assertSourceEqual(mod2.manyargs, 40, 41)
319 def test_twolinefunc(self):
320 # Test inspect.getsource with a regular function where
321 # the body is on two lines, following the argument list and
322 # continued on the next line by a \\.
323 self.assertSourceEqual(mod2.twolinefunc, 44, 45)
325 def test_lambda_in_list(self):
326 # Test inspect.getsource with a one-line lambda function
327 # defined in a list, indented.
328 self.assertSourceEqual(mod2.a[1], 49, 49)
330 def test_anonymous(self):
331 # Test inspect.getsource with a lambda function defined
332 # as argument to another function.
333 self.assertSourceEqual(mod2.anonymous, 55, 55)
335 class TestBuggyCases(GetSourceBase):
336 fodderFile = mod2
338 def test_with_comment(self):
339 self.assertSourceEqual(mod2.with_comment, 58, 59)
341 def test_multiline_sig(self):
342 self.assertSourceEqual(mod2.multiline_sig[0], 63, 64)
344 def test_nested_class(self):
345 self.assertSourceEqual(mod2.func69().func71, 71, 72)
347 def test_one_liner_followed_by_non_name(self):
348 self.assertSourceEqual(mod2.func77, 77, 77)
350 def test_one_liner_dedent_non_name(self):
351 self.assertSourceEqual(mod2.cls82.func83, 83, 83)
353 def test_with_comment_instead_of_docstring(self):
354 self.assertSourceEqual(mod2.func88, 88, 90)
356 def test_method_in_dynamic_class(self):
357 self.assertSourceEqual(mod2.method_in_dynamic_class, 95, 97)
359 @unittest.skipIf(
360 not hasattr(unicodedata, '__file__') or
361 unicodedata.__file__[-4:] in (".pyc", ".pyo"),
362 "unicodedata is not an external binary module")
363 def test_findsource_binary(self):
364 self.assertRaises(IOError, inspect.getsource, unicodedata)
365 self.assertRaises(IOError, inspect.findsource, unicodedata)
367 # Helper for testing classify_class_attrs.
368 def attrs_wo_objs(cls):
369 return [t[:3] for t in inspect.classify_class_attrs(cls)]
371 class TestClassesAndFunctions(unittest.TestCase):
372 def test_classic_mro(self):
373 # Test classic-class method resolution order.
374 class A: pass
375 class B(A): pass
376 class C(A): pass
377 class D(B, C): pass
379 expected = (D, B, A, C)
380 got = inspect.getmro(D)
381 self.assertEqual(expected, got)
383 def test_newstyle_mro(self):
384 # The same w/ new-class MRO.
385 class A(object): pass
386 class B(A): pass
387 class C(A): pass
388 class D(B, C): pass
390 expected = (D, B, C, A, object)
391 got = inspect.getmro(D)
392 self.assertEqual(expected, got)
394 def assertArgSpecEquals(self, routine, args_e, varargs_e = None,
395 varkw_e = None, defaults_e = None,
396 formatted = None):
397 args, varargs, varkw, defaults = inspect.getargspec(routine)
398 self.assertEqual(args, args_e)
399 self.assertEqual(varargs, varargs_e)
400 self.assertEqual(varkw, varkw_e)
401 self.assertEqual(defaults, defaults_e)
402 if formatted is not None:
403 self.assertEqual(inspect.formatargspec(args, varargs, varkw, defaults),
404 formatted)
406 def test_getargspec(self):
407 self.assertArgSpecEquals(mod.eggs, ['x', 'y'], formatted = '(x, y)')
409 self.assertArgSpecEquals(mod.spam,
410 ['a', 'b', 'c', 'd', ['e', ['f']]],
411 'g', 'h', (3, (4, (5,))),
412 '(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h)')
414 def test_getargspec_method(self):
415 class A(object):
416 def m(self):
417 pass
418 self.assertArgSpecEquals(A.m, ['self'])
420 def test_getargspec_sublistofone(self):
421 def sublistOfOne((foo,)): return 1
422 self.assertArgSpecEquals(sublistOfOne, [['foo']])
424 def fakeSublistOfOne((foo)): return 1
425 self.assertArgSpecEquals(fakeSublistOfOne, ['foo'])
427 def test_classify_oldstyle(self):
428 class A:
429 def s(): pass
430 s = staticmethod(s)
432 def c(cls): pass
433 c = classmethod(c)
435 def getp(self): pass
436 p = property(getp)
438 def m(self): pass
440 def m1(self): pass
442 datablob = '1'
444 attrs = attrs_wo_objs(A)
445 self.assertTrue(('s', 'static method', A) in attrs, 'missing static method')
446 self.assertTrue(('c', 'class method', A) in attrs, 'missing class method')
447 self.assertTrue(('p', 'property', A) in attrs, 'missing property')
448 self.assertTrue(('m', 'method', A) in attrs, 'missing plain method')
449 self.assertTrue(('m1', 'method', A) in attrs, 'missing plain method')
450 self.assertTrue(('datablob', 'data', A) in attrs, 'missing data')
452 class B(A):
453 def m(self): pass
455 attrs = attrs_wo_objs(B)
456 self.assertTrue(('s', 'static method', A) in attrs, 'missing static method')
457 self.assertTrue(('c', 'class method', A) in attrs, 'missing class method')
458 self.assertTrue(('p', 'property', A) in attrs, 'missing property')
459 self.assertTrue(('m', 'method', B) in attrs, 'missing plain method')
460 self.assertTrue(('m1', 'method', A) in attrs, 'missing plain method')
461 self.assertTrue(('datablob', 'data', A) in attrs, 'missing data')
464 class C(A):
465 def m(self): pass
466 def c(self): pass
468 attrs = attrs_wo_objs(C)
469 self.assertTrue(('s', 'static method', A) in attrs, 'missing static method')
470 self.assertTrue(('c', 'method', C) in attrs, 'missing plain method')
471 self.assertTrue(('p', 'property', A) in attrs, 'missing property')
472 self.assertTrue(('m', 'method', C) in attrs, 'missing plain method')
473 self.assertTrue(('m1', 'method', A) in attrs, 'missing plain method')
474 self.assertTrue(('datablob', 'data', A) in attrs, 'missing data')
476 class D(B, C):
477 def m1(self): pass
479 attrs = attrs_wo_objs(D)
480 self.assertTrue(('s', 'static method', A) in attrs, 'missing static method')
481 self.assertTrue(('c', 'class method', A) in attrs, 'missing class method')
482 self.assertTrue(('p', 'property', A) in attrs, 'missing property')
483 self.assertTrue(('m', 'method', B) in attrs, 'missing plain method')
484 self.assertTrue(('m1', 'method', D) in attrs, 'missing plain method')
485 self.assertTrue(('datablob', 'data', A) in attrs, 'missing data')
487 # Repeat all that, but w/ new-style classes.
488 def test_classify_newstyle(self):
489 class A(object):
491 def s(): pass
492 s = staticmethod(s)
494 def c(cls): pass
495 c = classmethod(c)
497 def getp(self): pass
498 p = property(getp)
500 def m(self): pass
502 def m1(self): pass
504 datablob = '1'
506 attrs = attrs_wo_objs(A)
507 self.assertTrue(('s', 'static method', A) in attrs, 'missing static method')
508 self.assertTrue(('c', 'class method', A) in attrs, 'missing class method')
509 self.assertTrue(('p', 'property', A) in attrs, 'missing property')
510 self.assertTrue(('m', 'method', A) in attrs, 'missing plain method')
511 self.assertTrue(('m1', 'method', A) in attrs, 'missing plain method')
512 self.assertTrue(('datablob', 'data', A) in attrs, 'missing data')
514 class B(A):
516 def m(self): pass
518 attrs = attrs_wo_objs(B)
519 self.assertTrue(('s', 'static method', A) in attrs, 'missing static method')
520 self.assertTrue(('c', 'class method', A) in attrs, 'missing class method')
521 self.assertTrue(('p', 'property', A) in attrs, 'missing property')
522 self.assertTrue(('m', 'method', B) in attrs, 'missing plain method')
523 self.assertTrue(('m1', 'method', A) in attrs, 'missing plain method')
524 self.assertTrue(('datablob', 'data', A) in attrs, 'missing data')
527 class C(A):
529 def m(self): pass
530 def c(self): pass
532 attrs = attrs_wo_objs(C)
533 self.assertTrue(('s', 'static method', A) in attrs, 'missing static method')
534 self.assertTrue(('c', 'method', C) in attrs, 'missing plain method')
535 self.assertTrue(('p', 'property', A) in attrs, 'missing property')
536 self.assertTrue(('m', 'method', C) in attrs, 'missing plain method')
537 self.assertTrue(('m1', 'method', A) in attrs, 'missing plain method')
538 self.assertTrue(('datablob', 'data', A) in attrs, 'missing data')
540 class D(B, C):
542 def m1(self): pass
544 attrs = attrs_wo_objs(D)
545 self.assertTrue(('s', 'static method', A) in attrs, 'missing static method')
546 self.assertTrue(('c', 'method', C) in attrs, 'missing plain method')
547 self.assertTrue(('p', 'property', A) in attrs, 'missing property')
548 self.assertTrue(('m', 'method', B) in attrs, 'missing plain method')
549 self.assertTrue(('m1', 'method', D) in attrs, 'missing plain method')
550 self.assertTrue(('datablob', 'data', A) in attrs, 'missing data')
552 def test_main():
553 run_unittest(TestDecorators, TestRetrievingSourceCode, TestOneliners,
554 TestBuggyCases,
555 TestInterpreterStack, TestClassesAndFunctions, TestPredicates)
557 if __name__ == "__main__":
558 test_main()