append(): Fixing the test for convertability after consultation with
[python/dscho.git] / Lib / test / test_inspect.py
blobccfba34ea680eec688655a42deabb39353015ac7
1 source = '''# line 1
2 'A module docstring.'
4 import sys, inspect
5 # line 5
7 # line 7
8 def spam(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h):
9 eggs(b + d, c + f)
11 # line 11
12 def eggs(x, y):
13 "A docstring."
14 global fr, st
15 fr = inspect.currentframe()
16 st = inspect.stack()
17 p = x
18 q = y / 0
20 # line 20
21 class StupidGit:
22 """A longer,
24 indented
26 docstring."""
27 # line 27
29 def abuse(self, a, b, c):
30 """Another
32 \tdocstring
34 containing
36 \ttabs
38 """
39 self.argue(a, b, c)
40 # line 40
41 def argue(self, a, b, c):
42 try:
43 spam(a, b, c)
44 except:
45 self.ex = sys.exc_info()
46 self.tr = inspect.trace()
48 # line 48
49 class MalodorousPervert(StupidGit):
50 pass
52 class ParrotDroppings:
53 pass
55 class FesteringGob(MalodorousPervert, ParrotDroppings):
56 pass
57 '''
59 # Functions tested in this suite:
60 # ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode,
61 # isbuiltin, isroutine, getmembers, getdoc, getfile, getmodule,
62 # getsourcefile, getcomments, getsource, getclasstree, getargspec,
63 # getargvalues, formatargspec, formatargvalues, currentframe, stack, trace
65 from test.test_support import TestFailed, TESTFN
66 import sys, imp, os, string
68 def test(assertion, message, *args):
69 if not assertion:
70 raise TestFailed, message % args
72 import inspect
74 file = open(TESTFN, 'w')
75 file.write(source)
76 file.close()
78 # Note that load_source creates file TESTFN+'c' or TESTFN+'o'.
79 mod = imp.load_source('testmod', TESTFN)
80 files_to_clean_up = [TESTFN, TESTFN + 'c', TESTFN + 'o']
82 def istest(func, exp):
83 obj = eval(exp)
84 test(func(obj), '%s(%s)' % (func.__name__, exp))
85 for other in [inspect.isbuiltin, inspect.isclass, inspect.iscode,
86 inspect.isframe, inspect.isfunction, inspect.ismethod,
87 inspect.ismodule, inspect.istraceback]:
88 if other is not func:
89 test(not other(obj), 'not %s(%s)' % (other.__name__, exp))
91 git = mod.StupidGit()
92 try:
93 1/0
94 except:
95 tb = sys.exc_traceback
97 istest(inspect.isbuiltin, 'sys.exit')
98 istest(inspect.isbuiltin, '[].append')
99 istest(inspect.isclass, 'mod.StupidGit')
100 istest(inspect.iscode, 'mod.spam.func_code')
101 istest(inspect.isframe, 'tb.tb_frame')
102 istest(inspect.isfunction, 'mod.spam')
103 istest(inspect.ismethod, 'mod.StupidGit.abuse')
104 istest(inspect.ismethod, 'git.argue')
105 istest(inspect.ismodule, 'mod')
106 istest(inspect.istraceback, 'tb')
107 test(inspect.isroutine(mod.spam), 'isroutine(mod.spam)')
108 test(inspect.isroutine([].count), 'isroutine([].count)')
110 classes = inspect.getmembers(mod, inspect.isclass)
111 test(classes ==
112 [('FesteringGob', mod.FesteringGob),
113 ('MalodorousPervert', mod.MalodorousPervert),
114 ('ParrotDroppings', mod.ParrotDroppings),
115 ('StupidGit', mod.StupidGit)], 'class list')
116 tree = inspect.getclasstree(map(lambda x: x[1], classes), 1)
117 test(tree ==
118 [(mod.ParrotDroppings, ()),
119 (mod.StupidGit, ()),
120 [(mod.MalodorousPervert, (mod.StupidGit,)),
121 [(mod.FesteringGob, (mod.MalodorousPervert, mod.ParrotDroppings))
124 ], 'class tree')
126 functions = inspect.getmembers(mod, inspect.isfunction)
127 test(functions == [('eggs', mod.eggs), ('spam', mod.spam)], 'function list')
129 test(inspect.getdoc(mod) == 'A module docstring.', 'getdoc(mod)')
130 test(inspect.getcomments(mod) == '# line 1\n', 'getcomments(mod)')
131 test(inspect.getmodule(mod.StupidGit) == mod, 'getmodule(mod.StupidGit)')
132 test(inspect.getfile(mod.StupidGit) == TESTFN, 'getfile(mod.StupidGit)')
133 test(inspect.getsourcefile(mod.spam) == TESTFN, 'getsourcefile(mod.spam)')
134 test(inspect.getsourcefile(git.abuse) == TESTFN, 'getsourcefile(git.abuse)')
136 def sourcerange(top, bottom):
137 lines = string.split(source, '\n')
138 return string.join(lines[top-1:bottom], '\n') + '\n'
140 test(inspect.getsource(git.abuse) == sourcerange(29, 39),
141 'getsource(git.abuse)')
142 test(inspect.getsource(mod.StupidGit) == sourcerange(21, 46),
143 'getsource(mod.StupidGit)')
144 test(inspect.getdoc(mod.StupidGit) ==
145 'A longer,\n\nindented\n\ndocstring.', 'getdoc(mod.StupidGit)')
146 test(inspect.getdoc(git.abuse) ==
147 'Another\n\ndocstring\n\ncontaining\n\ntabs\n\n', 'getdoc(git.abuse)')
148 test(inspect.getcomments(mod.StupidGit) == '# line 20\n',
149 'getcomments(mod.StupidGit)')
151 args, varargs, varkw, defaults = inspect.getargspec(mod.eggs)
152 test(args == ['x', 'y'], 'mod.eggs args')
153 test(varargs == None, 'mod.eggs varargs')
154 test(varkw == None, 'mod.eggs varkw')
155 test(defaults == None, 'mod.eggs defaults')
156 test(inspect.formatargspec(args, varargs, varkw, defaults) ==
157 '(x, y)', 'mod.eggs formatted argspec')
158 args, varargs, varkw, defaults = inspect.getargspec(mod.spam)
159 test(args == ['a', 'b', 'c', 'd', ['e', ['f']]], 'mod.spam args')
160 test(varargs == 'g', 'mod.spam varargs')
161 test(varkw == 'h', 'mod.spam varkw')
162 test(defaults == (3, (4, (5,))), 'mod.spam defaults')
163 test(inspect.formatargspec(args, varargs, varkw, defaults) ==
164 '(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h)',
165 'mod.spam formatted argspec')
167 git.abuse(7, 8, 9)
169 istest(inspect.istraceback, 'git.ex[2]')
170 istest(inspect.isframe, 'mod.fr')
172 test(len(git.tr) == 3, 'trace() length')
173 test(git.tr[0][1:] == (TESTFN, 46, 'argue',
174 [' self.tr = inspect.trace()\n'], 0),
175 'trace() row 2')
176 test(git.tr[1][1:] == (TESTFN, 9, 'spam', [' eggs(b + d, c + f)\n'], 0),
177 'trace() row 2')
178 test(git.tr[2][1:] == (TESTFN, 18, 'eggs', [' q = y / 0\n'], 0),
179 'trace() row 3')
181 test(len(mod.st) >= 5, 'stack() length')
182 test(mod.st[0][1:] ==
183 (TESTFN, 16, 'eggs', [' st = inspect.stack()\n'], 0),
184 'stack() row 1')
185 test(mod.st[1][1:] ==
186 (TESTFN, 9, 'spam', [' eggs(b + d, c + f)\n'], 0),
187 'stack() row 2')
188 test(mod.st[2][1:] ==
189 (TESTFN, 43, 'argue', [' spam(a, b, c)\n'], 0),
190 'stack() row 3')
191 test(mod.st[3][1:] ==
192 (TESTFN, 39, 'abuse', [' self.argue(a, b, c)\n'], 0),
193 'stack() row 4')
195 args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
196 test(args == ['x', 'y'], 'mod.fr args')
197 test(varargs == None, 'mod.fr varargs')
198 test(varkw == None, 'mod.fr varkw')
199 test(locals == {'x': 11, 'p': 11, 'y': 14}, 'mod.fr locals')
200 test(inspect.formatargvalues(args, varargs, varkw, locals) ==
201 '(x=11, y=14)', 'mod.fr formatted argvalues')
203 args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
204 test(args == ['a', 'b', 'c', 'd', ['e', ['f']]], 'mod.fr.f_back args')
205 test(varargs == 'g', 'mod.fr.f_back varargs')
206 test(varkw == 'h', 'mod.fr.f_back varkw')
207 test(inspect.formatargvalues(args, varargs, varkw, locals) ==
208 '(a=7, b=8, c=9, d=3, (e=4, (f=5,)), *g=(), **h={})',
209 'mod.fr.f_back formatted argvalues')
211 for fname in files_to_clean_up:
212 try:
213 os.unlink(fname)
214 except:
215 pass
217 # Test classic-class method resolution order.
218 class A: pass
219 class B(A): pass
220 class C(A): pass
221 class D(B, C): pass
223 expected = (D, B, A, C)
224 got = inspect.getmro(D)
225 test(expected == got, "expected %r mro, got %r", expected, got)
227 # The same w/ new-class MRO.
228 class A(object): pass
229 class B(A): pass
230 class C(A): pass
231 class D(B, C): pass
233 expected = (D, B, C, A, object)
234 got = inspect.getmro(D)
235 test(expected == got, "expected %r mro, got %r", expected, got)
237 # Test classify_class_attrs.
238 def attrs_wo_objs(cls):
239 return [t[:3] for t in inspect.classify_class_attrs(cls)]
241 class A:
242 def s(): pass
243 s = staticmethod(s)
245 def c(cls): pass
246 c = classmethod(c)
248 def getp(self): pass
249 p = property(getp)
251 def m(self): pass
253 def m1(self): pass
255 datablob = '1'
257 attrs = attrs_wo_objs(A)
258 test(('s', 'static method', A) in attrs, 'missing static method')
259 test(('c', 'class method', A) in attrs, 'missing class method')
260 test(('p', 'property', A) in attrs, 'missing property')
261 test(('m', 'method', A) in attrs, 'missing plain method')
262 test(('m1', 'method', A) in attrs, 'missing plain method')
263 test(('datablob', 'data', A) in attrs, 'missing data')
265 class B(A):
266 def m(self): pass
268 attrs = attrs_wo_objs(B)
269 test(('s', 'static method', A) in attrs, 'missing static method')
270 test(('c', 'class method', A) in attrs, 'missing class method')
271 test(('p', 'property', A) in attrs, 'missing property')
272 test(('m', 'method', B) in attrs, 'missing plain method')
273 test(('m1', 'method', A) in attrs, 'missing plain method')
274 test(('datablob', 'data', A) in attrs, 'missing data')
277 class C(A):
278 def m(self): pass
279 def c(self): pass
281 attrs = attrs_wo_objs(C)
282 test(('s', 'static method', A) in attrs, 'missing static method')
283 test(('c', 'method', C) in attrs, 'missing plain method')
284 test(('p', 'property', A) in attrs, 'missing property')
285 test(('m', 'method', C) in attrs, 'missing plain method')
286 test(('m1', 'method', A) in attrs, 'missing plain method')
287 test(('datablob', 'data', A) in attrs, 'missing data')
289 class D(B, C):
290 def m1(self): pass
292 attrs = attrs_wo_objs(D)
293 test(('s', 'static method', A) in attrs, 'missing static method')
294 test(('c', 'class method', A) in attrs, 'missing class method')
295 test(('p', 'property', A) in attrs, 'missing property')
296 test(('m', 'method', B) in attrs, 'missing plain method')
297 test(('m1', 'method', D) in attrs, 'missing plain method')
298 test(('datablob', 'data', A) in attrs, 'missing data')
300 # Repeat all that, but w/ new-style classes.
302 class A(object):
304 def s(): pass
305 s = staticmethod(s)
307 def c(cls): pass
308 c = classmethod(c)
310 def getp(self): pass
311 p = property(getp)
313 def m(self): pass
315 def m1(self): pass
317 datablob = '1'
319 attrs = attrs_wo_objs(A)
320 test(('s', 'static method', A) in attrs, 'missing static method')
321 test(('c', 'class method', A) in attrs, 'missing class method')
322 test(('p', 'property', A) in attrs, 'missing property')
323 test(('m', 'method', A) in attrs, 'missing plain method')
324 test(('m1', 'method', A) in attrs, 'missing plain method')
325 test(('datablob', 'data', A) in attrs, 'missing data')
327 class B(A):
329 def m(self): pass
331 attrs = attrs_wo_objs(B)
332 test(('s', 'static method', A) in attrs, 'missing static method')
333 test(('c', 'class method', A) in attrs, 'missing class method')
334 test(('p', 'property', A) in attrs, 'missing property')
335 test(('m', 'method', B) in attrs, 'missing plain method')
336 test(('m1', 'method', A) in attrs, 'missing plain method')
337 test(('datablob', 'data', A) in attrs, 'missing data')
340 class C(A):
342 def m(self): pass
343 def c(self): pass
345 attrs = attrs_wo_objs(C)
346 test(('s', 'static method', A) in attrs, 'missing static method')
347 test(('c', 'method', C) in attrs, 'missing plain method')
348 test(('p', 'property', A) in attrs, 'missing property')
349 test(('m', 'method', C) in attrs, 'missing plain method')
350 test(('m1', 'method', A) in attrs, 'missing plain method')
351 test(('datablob', 'data', A) in attrs, 'missing data')
353 class D(B, C):
355 def m1(self): pass
357 attrs = attrs_wo_objs(D)
358 test(('s', 'static method', A) in attrs, 'missing static method')
359 test(('c', 'method', C) in attrs, 'missing plain method')
360 test(('p', 'property', A) in attrs, 'missing property')
361 test(('m', 'method', B) in attrs, 'missing plain method')
362 test(('m1', 'method', D) in attrs, 'missing plain method')
363 test(('datablob', 'data', A) in attrs, 'missing data')