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
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]
34 tb
= sys
.exc_traceback
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
):
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
:
52 self
.assertFalse(other(obj
), 'not %s(%s)' % (other
.__name
__, exp
))
54 def generator_function_example(self
):
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
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')
86 self
.assertFalse(inspect
.isgetsetdescriptor(type(tb
.tb_frame
).f_locals
))
87 if hasattr(types
, 'MemberDescriptorType'):
88 self
.istest(inspect
.ismemberdescriptor
, 'datetime.timedelta.days')
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
):
106 self
.assertFalse(inspect
.isclass(CustomGetattr()))
108 def test_get_slot_members(self
):
110 __slots__
= ("a", "b")
114 members
= dict(inspect
.getmembers(x
))
115 self
.assertTrue('a' in members
)
116 self
.assertTrue('b' not in members
)
119 class TestInterpreterStack(IsTestBase
):
120 def __init__(self
, *args
, **kwargs
):
121 unittest
.TestCase
.__init
__(self
, *args
, **kwargs
)
125 def test_abuse_done(self
):
126 self
.istest(inspect
.istraceback
, 'git.ex[2]')
127 self
.istest(inspect
.isframe
, 'mod.fr')
129 def test_stack(self
):
130 self
.assertTrue(len(mod
.st
) >= 5)
131 self
.assertEqual(mod
.st
[0][1:],
132 (modfile
, 16, 'eggs', [' st = inspect.stack()\n'], 0))
133 self
.assertEqual(mod
.st
[1][1:],
134 (modfile
, 9, 'spam', [' eggs(b + d, c + f)\n'], 0))
135 self
.assertEqual(mod
.st
[2][1:],
136 (modfile
, 43, 'argue', [' spam(a, b, c)\n'], 0))
137 self
.assertEqual(mod
.st
[3][1:],
138 (modfile
, 39, 'abuse', [' self.argue(a, b, c)\n'], 0))
140 def test_trace(self
):
141 self
.assertEqual(len(git
.tr
), 3)
142 self
.assertEqual(git
.tr
[0][1:], (modfile
, 43, 'argue',
143 [' spam(a, b, c)\n'], 0))
144 self
.assertEqual(git
.tr
[1][1:], (modfile
, 9, 'spam',
145 [' eggs(b + d, c + f)\n'], 0))
146 self
.assertEqual(git
.tr
[2][1:], (modfile
, 18, 'eggs',
147 [' q = y / 0\n'], 0))
149 def test_frame(self
):
150 args
, varargs
, varkw
, locals = inspect
.getargvalues(mod
.fr
)
151 self
.assertEqual(args
, ['x', 'y'])
152 self
.assertEqual(varargs
, None)
153 self
.assertEqual(varkw
, None)
154 self
.assertEqual(locals, {'x': 11, 'p': 11, 'y': 14})
155 self
.assertEqual(inspect
.formatargvalues(args
, varargs
, varkw
, locals),
158 def test_previous_frame(self
):
159 args
, varargs
, varkw
, locals = inspect
.getargvalues(mod
.fr
.f_back
)
160 self
.assertEqual(args
, ['a', 'b', 'c', 'd', ['e', ['f']]])
161 self
.assertEqual(varargs
, 'g')
162 self
.assertEqual(varkw
, 'h')
163 self
.assertEqual(inspect
.formatargvalues(args
, varargs
, varkw
, locals),
164 '(a=7, b=8, c=9, d=3, (e=4, (f=5,)), *g=(), **h={})')
166 class GetSourceBase(unittest
.TestCase
):
167 # Subclasses must override.
170 def __init__(self
, *args
, **kwargs
):
171 unittest
.TestCase
.__init
__(self
, *args
, **kwargs
)
173 with
open(inspect
.getsourcefile(self
.fodderFile
)) as fp
:
174 self
.source
= fp
.read()
176 def sourcerange(self
, top
, bottom
):
177 lines
= self
.source
.split("\n")
178 return "\n".join(lines
[top
-1:bottom
]) + "\n"
180 def assertSourceEqual(self
, obj
, top
, bottom
):
181 self
.assertEqual(inspect
.getsource(obj
),
182 self
.sourcerange(top
, bottom
))
184 class TestRetrievingSourceCode(GetSourceBase
):
187 def test_getclasses(self
):
188 classes
= inspect
.getmembers(mod
, inspect
.isclass
)
189 self
.assertEqual(classes
,
190 [('FesteringGob', mod
.FesteringGob
),
191 ('MalodorousPervert', mod
.MalodorousPervert
),
192 ('ParrotDroppings', mod
.ParrotDroppings
),
193 ('StupidGit', mod
.StupidGit
)])
194 tree
= inspect
.getclasstree([cls
[1] for cls
in classes
], 1)
195 self
.assertEqual(tree
,
196 [(mod
.ParrotDroppings
, ()),
198 [(mod
.MalodorousPervert
, (mod
.StupidGit
,)),
199 [(mod
.FesteringGob
, (mod
.MalodorousPervert
,
200 mod
.ParrotDroppings
))
205 def test_getfunctions(self
):
206 functions
= inspect
.getmembers(mod
, inspect
.isfunction
)
207 self
.assertEqual(functions
, [('eggs', mod
.eggs
),
210 def test_getdoc(self
):
211 self
.assertEqual(inspect
.getdoc(mod
), 'A module docstring.')
212 self
.assertEqual(inspect
.getdoc(mod
.StupidGit
),
213 'A longer,\n\nindented\n\ndocstring.')
214 self
.assertEqual(inspect
.getdoc(git
.abuse
),
215 'Another\n\ndocstring\n\ncontaining\n\ntabs')
217 def test_cleandoc(self
):
218 self
.assertEqual(inspect
.cleandoc('An\n indented\n docstring.'),
219 'An\nindented\ndocstring.')
221 def test_getcomments(self
):
222 self
.assertEqual(inspect
.getcomments(mod
), '# line 1\n')
223 self
.assertEqual(inspect
.getcomments(mod
.StupidGit
), '# line 20\n')
225 def test_getmodule(self
):
226 # Check actual module
227 self
.assertEqual(inspect
.getmodule(mod
), mod
)
228 # Check class (uses __module__ attribute)
229 self
.assertEqual(inspect
.getmodule(mod
.StupidGit
), mod
)
230 # Check a method (no __module__ attribute, falls back to filename)
231 self
.assertEqual(inspect
.getmodule(mod
.StupidGit
.abuse
), mod
)
232 # Do it again (check the caching isn't broken)
233 self
.assertEqual(inspect
.getmodule(mod
.StupidGit
.abuse
), mod
)
235 self
.assertEqual(inspect
.getmodule(str), sys
.modules
["__builtin__"])
236 # Check filename override
237 self
.assertEqual(inspect
.getmodule(None, modfile
), mod
)
239 def test_getsource(self
):
240 self
.assertSourceEqual(git
.abuse
, 29, 39)
241 self
.assertSourceEqual(mod
.StupidGit
, 21, 46)
243 def test_getsourcefile(self
):
244 self
.assertEqual(inspect
.getsourcefile(mod
.spam
), modfile
)
245 self
.assertEqual(inspect
.getsourcefile(git
.abuse
), modfile
)
247 def test_getfile(self
):
248 self
.assertEqual(inspect
.getfile(mod
.StupidGit
), mod
.__file
__)
250 def test_getmodule_recursion(self
):
251 from types
import ModuleType
252 name
= '__inspect_dummy'
253 m
= sys
.modules
[name
] = ModuleType(name
)
254 m
.__file
__ = "<string>" # hopefully not a real filename...
255 m
.__loader
__ = "dummy" # pretend the filename is understood by a loader
256 exec "def x(): pass" in m
.__dict
__
257 self
.assertEqual(inspect
.getsourcefile(m
.x
.func_code
), '<string>')
258 del sys
.modules
[name
]
259 inspect
.getmodule(compile('a=10','','single'))
261 class TestDecorators(GetSourceBase
):
264 def test_wrapped_decorator(self
):
265 self
.assertSourceEqual(mod2
.wrapped
, 14, 17)
267 def test_replacing_decorator(self
):
268 self
.assertSourceEqual(mod2
.gone
, 9, 10)
270 class TestOneliners(GetSourceBase
):
272 def test_oneline_lambda(self
):
273 # Test inspect.getsource with a one-line lambda function.
274 self
.assertSourceEqual(mod2
.oll
, 25, 25)
276 def test_threeline_lambda(self
):
277 # Test inspect.getsource with a three-line lambda function,
278 # where the second and third lines are _not_ indented.
279 self
.assertSourceEqual(mod2
.tll
, 28, 30)
281 def test_twoline_indented_lambda(self
):
282 # Test inspect.getsource with a two-line lambda function,
283 # where the second line _is_ indented.
284 self
.assertSourceEqual(mod2
.tlli
, 33, 34)
286 def test_onelinefunc(self
):
287 # Test inspect.getsource with a regular one-line function.
288 self
.assertSourceEqual(mod2
.onelinefunc
, 37, 37)
290 def test_manyargs(self
):
291 # Test inspect.getsource with a regular function where
292 # the arguments are on two lines and _not_ indented and
293 # the body on the second line with the last arguments.
294 self
.assertSourceEqual(mod2
.manyargs
, 40, 41)
296 def test_twolinefunc(self
):
297 # Test inspect.getsource with a regular function where
298 # the body is on two lines, following the argument list and
299 # continued on the next line by a \\.
300 self
.assertSourceEqual(mod2
.twolinefunc
, 44, 45)
302 def test_lambda_in_list(self
):
303 # Test inspect.getsource with a one-line lambda function
304 # defined in a list, indented.
305 self
.assertSourceEqual(mod2
.a
[1], 49, 49)
307 def test_anonymous(self
):
308 # Test inspect.getsource with a lambda function defined
309 # as argument to another function.
310 self
.assertSourceEqual(mod2
.anonymous
, 55, 55)
312 class TestBuggyCases(GetSourceBase
):
315 def test_with_comment(self
):
316 self
.assertSourceEqual(mod2
.with_comment
, 58, 59)
318 def test_multiline_sig(self
):
319 self
.assertSourceEqual(mod2
.multiline_sig
[0], 63, 64)
321 def test_nested_class(self
):
322 self
.assertSourceEqual(mod2
.func69().func71
, 71, 72)
324 def test_one_liner_followed_by_non_name(self
):
325 self
.assertSourceEqual(mod2
.func77
, 77, 77)
327 def test_one_liner_dedent_non_name(self
):
328 self
.assertSourceEqual(mod2
.cls82
.func83
, 83, 83)
330 def test_with_comment_instead_of_docstring(self
):
331 self
.assertSourceEqual(mod2
.func88
, 88, 90)
333 def test_method_in_dynamic_class(self
):
334 self
.assertSourceEqual(mod2
.method_in_dynamic_class
, 95, 97)
337 not hasattr(unicodedata
, '__file__') or
338 unicodedata
.__file
__[-4:] in (".pyc", ".pyo"),
339 "unicodedata is not an external binary module")
340 def test_findsource_binary(self
):
341 self
.assertRaises(IOError, inspect
.getsource
, unicodedata
)
342 self
.assertRaises(IOError, inspect
.findsource
, unicodedata
)
344 # Helper for testing classify_class_attrs.
345 def attrs_wo_objs(cls
):
346 return [t
[:3] for t
in inspect
.classify_class_attrs(cls
)]
348 class TestClassesAndFunctions(unittest
.TestCase
):
349 def test_classic_mro(self
):
350 # Test classic-class method resolution order.
356 expected
= (D
, B
, A
, C
)
357 got
= inspect
.getmro(D
)
358 self
.assertEqual(expected
, got
)
360 def test_newstyle_mro(self
):
361 # The same w/ new-class MRO.
362 class A(object): pass
367 expected
= (D
, B
, C
, A
, object)
368 got
= inspect
.getmro(D
)
369 self
.assertEqual(expected
, got
)
371 def assertArgSpecEquals(self
, routine
, args_e
, varargs_e
= None,
372 varkw_e
= None, defaults_e
= None,
374 args
, varargs
, varkw
, defaults
= inspect
.getargspec(routine
)
375 self
.assertEqual(args
, args_e
)
376 self
.assertEqual(varargs
, varargs_e
)
377 self
.assertEqual(varkw
, varkw_e
)
378 self
.assertEqual(defaults
, defaults_e
)
379 if formatted
is not None:
380 self
.assertEqual(inspect
.formatargspec(args
, varargs
, varkw
, defaults
),
383 def test_getargspec(self
):
384 self
.assertArgSpecEquals(mod
.eggs
, ['x', 'y'], formatted
= '(x, y)')
386 self
.assertArgSpecEquals(mod
.spam
,
387 ['a', 'b', 'c', 'd', ['e', ['f']]],
388 'g', 'h', (3, (4, (5,))),
389 '(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h)')
391 def test_getargspec_method(self
):
395 self
.assertArgSpecEquals(A
.m
, ['self'])
397 def test_getargspec_sublistofone(self
):
398 def sublistOfOne((foo
,)): return 1
399 self
.assertArgSpecEquals(sublistOfOne
, [['foo']])
401 def fakeSublistOfOne((foo
)): return 1
402 self
.assertArgSpecEquals(fakeSublistOfOne
, ['foo'])
404 def test_classify_oldstyle(self
):
421 attrs
= attrs_wo_objs(A
)
422 self
.assertTrue(('s', 'static method', A
) in attrs
, 'missing static method')
423 self
.assertTrue(('c', 'class method', A
) in attrs
, 'missing class method')
424 self
.assertTrue(('p', 'property', A
) in attrs
, 'missing property')
425 self
.assertTrue(('m', 'method', A
) in attrs
, 'missing plain method')
426 self
.assertTrue(('m1', 'method', A
) in attrs
, 'missing plain method')
427 self
.assertTrue(('datablob', 'data', A
) in attrs
, 'missing data')
432 attrs
= attrs_wo_objs(B
)
433 self
.assertTrue(('s', 'static method', A
) in attrs
, 'missing static method')
434 self
.assertTrue(('c', 'class method', A
) in attrs
, 'missing class method')
435 self
.assertTrue(('p', 'property', A
) in attrs
, 'missing property')
436 self
.assertTrue(('m', 'method', B
) in attrs
, 'missing plain method')
437 self
.assertTrue(('m1', 'method', A
) in attrs
, 'missing plain method')
438 self
.assertTrue(('datablob', 'data', A
) in attrs
, 'missing data')
445 attrs
= attrs_wo_objs(C
)
446 self
.assertTrue(('s', 'static method', A
) in attrs
, 'missing static method')
447 self
.assertTrue(('c', 'method', C
) in attrs
, 'missing plain method')
448 self
.assertTrue(('p', 'property', A
) in attrs
, 'missing property')
449 self
.assertTrue(('m', 'method', C
) in attrs
, 'missing plain method')
450 self
.assertTrue(('m1', 'method', A
) in attrs
, 'missing plain method')
451 self
.assertTrue(('datablob', 'data', A
) in attrs
, 'missing data')
456 attrs
= attrs_wo_objs(D
)
457 self
.assertTrue(('s', 'static method', A
) in attrs
, 'missing static method')
458 self
.assertTrue(('c', 'class method', A
) in attrs
, 'missing class method')
459 self
.assertTrue(('p', 'property', A
) in attrs
, 'missing property')
460 self
.assertTrue(('m', 'method', B
) in attrs
, 'missing plain method')
461 self
.assertTrue(('m1', 'method', D
) in attrs
, 'missing plain method')
462 self
.assertTrue(('datablob', 'data', A
) in attrs
, 'missing data')
464 # Repeat all that, but w/ new-style classes.
465 def test_classify_newstyle(self
):
483 attrs
= attrs_wo_objs(A
)
484 self
.assertTrue(('s', 'static method', A
) in attrs
, 'missing static method')
485 self
.assertTrue(('c', 'class method', A
) in attrs
, 'missing class method')
486 self
.assertTrue(('p', 'property', A
) in attrs
, 'missing property')
487 self
.assertTrue(('m', 'method', A
) in attrs
, 'missing plain method')
488 self
.assertTrue(('m1', 'method', A
) in attrs
, 'missing plain method')
489 self
.assertTrue(('datablob', 'data', A
) in attrs
, 'missing data')
495 attrs
= attrs_wo_objs(B
)
496 self
.assertTrue(('s', 'static method', A
) in attrs
, 'missing static method')
497 self
.assertTrue(('c', 'class method', A
) in attrs
, 'missing class method')
498 self
.assertTrue(('p', 'property', A
) in attrs
, 'missing property')
499 self
.assertTrue(('m', 'method', B
) in attrs
, 'missing plain method')
500 self
.assertTrue(('m1', 'method', A
) in attrs
, 'missing plain method')
501 self
.assertTrue(('datablob', 'data', A
) in attrs
, 'missing data')
509 attrs
= attrs_wo_objs(C
)
510 self
.assertTrue(('s', 'static method', A
) in attrs
, 'missing static method')
511 self
.assertTrue(('c', 'method', C
) in attrs
, 'missing plain method')
512 self
.assertTrue(('p', 'property', A
) in attrs
, 'missing property')
513 self
.assertTrue(('m', 'method', C
) in attrs
, 'missing plain method')
514 self
.assertTrue(('m1', 'method', A
) in attrs
, 'missing plain method')
515 self
.assertTrue(('datablob', 'data', A
) in attrs
, 'missing data')
521 attrs
= attrs_wo_objs(D
)
522 self
.assertTrue(('s', 'static method', A
) in attrs
, 'missing static method')
523 self
.assertTrue(('c', 'method', C
) in attrs
, 'missing plain method')
524 self
.assertTrue(('p', 'property', A
) in attrs
, 'missing property')
525 self
.assertTrue(('m', 'method', B
) in attrs
, 'missing plain method')
526 self
.assertTrue(('m1', 'method', D
) in attrs
, 'missing plain method')
527 self
.assertTrue(('datablob', 'data', A
) in attrs
, 'missing data')
530 run_unittest(TestDecorators
, TestRetrievingSourceCode
, TestOneliners
,
532 TestInterpreterStack
, TestClassesAndFunctions
, TestPredicates
)
534 if __name__
== "__main__":