blob: d253f26a5fd96f45f451dd0fc54321229f2bbf59 [file] [log] [blame]
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +00001source = '''# line 1
2'A module docstring.'
3
4import sys, inspect
5# line 5
6
7# line 7
8def spam(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h):
9 eggs(b + d, c + f)
10
11# line 11
12def 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
19
20# line 20
21class StupidGit:
22 """A longer,
23
24 indented
25
26 docstring."""
27# line 27
28
29 def abuse(self, a, b, c):
30 """Another
31
32\tdocstring
33
34 containing
35
36\ttabs
37\t
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()
47
48# line 48
49class MalodorousPervert(StupidGit):
50 pass
51
52class ParrotDroppings:
53 pass
54
55class FesteringGob(MalodorousPervert, ParrotDroppings):
56 pass
57'''
58
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
64
Barry Warsaw04f357c2002-07-23 19:04:11 +000065from test.test_support import TestFailed, TESTFN
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000066import sys, imp, os, string
67
68def test(assertion, message, *args):
69 if not assertion:
70 raise TestFailed, message % args
71
72import inspect
73
74file = open(TESTFN, 'w')
75file.write(source)
76file.close()
77
Tim Peters243bff42001-03-04 00:30:25 +000078# Note that load_source creates file TESTFN+'c' or TESTFN+'o'.
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000079mod = imp.load_source('testmod', TESTFN)
Tim Peters243bff42001-03-04 00:30:25 +000080files_to_clean_up = [TESTFN, TESTFN + 'c', TESTFN + 'o']
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000081
82def 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))
90
91git = mod.StupidGit()
92try:
93 1/0
94except:
95 tb = sys.exc_traceback
96
97istest(inspect.isbuiltin, 'sys.exit')
98istest(inspect.isbuiltin, '[].append')
99istest(inspect.isclass, 'mod.StupidGit')
100istest(inspect.iscode, 'mod.spam.func_code')
101istest(inspect.isframe, 'tb.tb_frame')
102istest(inspect.isfunction, 'mod.spam')
103istest(inspect.ismethod, 'mod.StupidGit.abuse')
104istest(inspect.ismethod, 'git.argue')
105istest(inspect.ismodule, 'mod')
106istest(inspect.istraceback, 'tb')
107test(inspect.isroutine(mod.spam), 'isroutine(mod.spam)')
108test(inspect.isroutine([].count), 'isroutine([].count)')
109
110classes = inspect.getmembers(mod, inspect.isclass)
111test(classes ==
112 [('FesteringGob', mod.FesteringGob),
113 ('MalodorousPervert', mod.MalodorousPervert),
114 ('ParrotDroppings', mod.ParrotDroppings),
115 ('StupidGit', mod.StupidGit)], 'class list')
116tree = inspect.getclasstree(map(lambda x: x[1], classes), 1)
117test(tree ==
118 [(mod.ParrotDroppings, ()),
119 (mod.StupidGit, ()),
120 [(mod.MalodorousPervert, (mod.StupidGit,)),
121 [(mod.FesteringGob, (mod.MalodorousPervert, mod.ParrotDroppings))
122 ]
123 ]
124 ], 'class tree')
125
126functions = inspect.getmembers(mod, inspect.isfunction)
127test(functions == [('eggs', mod.eggs), ('spam', mod.spam)], 'function list')
128
129test(inspect.getdoc(mod) == 'A module docstring.', 'getdoc(mod)')
130test(inspect.getcomments(mod) == '# line 1\n', 'getcomments(mod)')
131test(inspect.getmodule(mod.StupidGit) == mod, 'getmodule(mod.StupidGit)')
132test(inspect.getfile(mod.StupidGit) == TESTFN, 'getfile(mod.StupidGit)')
133test(inspect.getsourcefile(mod.spam) == TESTFN, 'getsourcefile(mod.spam)')
134test(inspect.getsourcefile(git.abuse) == TESTFN, 'getsourcefile(git.abuse)')
135
136def sourcerange(top, bottom):
137 lines = string.split(source, '\n')
138 return string.join(lines[top-1:bottom], '\n') + '\n'
139
140test(inspect.getsource(git.abuse) == sourcerange(29, 39),
141 'getsource(git.abuse)')
142test(inspect.getsource(mod.StupidGit) == sourcerange(21, 46),
143 'getsource(mod.StupidGit)')
144test(inspect.getdoc(mod.StupidGit) ==
145 'A longer,\n\nindented\n\ndocstring.', 'getdoc(mod.StupidGit)')
146test(inspect.getdoc(git.abuse) ==
Ka-Ping Yeea59ef7b2002-11-30 03:53:15 +0000147 'Another\n\ndocstring\n\ncontaining\n\ntabs', 'getdoc(git.abuse)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000148test(inspect.getcomments(mod.StupidGit) == '# line 20\n',
149 'getcomments(mod.StupidGit)')
150
151args, varargs, varkw, defaults = inspect.getargspec(mod.eggs)
152test(args == ['x', 'y'], 'mod.eggs args')
153test(varargs == None, 'mod.eggs varargs')
154test(varkw == None, 'mod.eggs varkw')
155test(defaults == None, 'mod.eggs defaults')
156test(inspect.formatargspec(args, varargs, varkw, defaults) ==
157 '(x, y)', 'mod.eggs formatted argspec')
158args, varargs, varkw, defaults = inspect.getargspec(mod.spam)
159test(args == ['a', 'b', 'c', 'd', ['e', ['f']]], 'mod.spam args')
160test(varargs == 'g', 'mod.spam varargs')
161test(varkw == 'h', 'mod.spam varkw')
162test(defaults == (3, (4, (5,))), 'mod.spam defaults')
163test(inspect.formatargspec(args, varargs, varkw, defaults) ==
164 '(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h)',
165 'mod.spam formatted argspec')
166
167git.abuse(7, 8, 9)
168
169istest(inspect.istraceback, 'git.ex[2]')
170istest(inspect.isframe, 'mod.fr')
171
Ka-Ping Yeef170d7f2001-03-23 05:14:10 +0000172test(len(git.tr) == 3, 'trace() length')
173test(git.tr[0][1:] == (TESTFN, 46, 'argue',
174 [' self.tr = inspect.trace()\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000175 'trace() row 2')
Ka-Ping Yeef170d7f2001-03-23 05:14:10 +0000176test(git.tr[1][1:] == (TESTFN, 9, 'spam', [' eggs(b + d, c + f)\n'], 0),
177 'trace() row 2')
178test(git.tr[2][1:] == (TESTFN, 18, 'eggs', [' q = y / 0\n'], 0),
179 'trace() row 3')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000180
181test(len(mod.st) >= 5, 'stack() length')
182test(mod.st[0][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000183 (TESTFN, 16, 'eggs', [' st = inspect.stack()\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000184 'stack() row 1')
185test(mod.st[1][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000186 (TESTFN, 9, 'spam', [' eggs(b + d, c + f)\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000187 'stack() row 2')
188test(mod.st[2][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000189 (TESTFN, 43, 'argue', [' spam(a, b, c)\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000190 'stack() row 3')
191test(mod.st[3][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000192 (TESTFN, 39, 'abuse', [' self.argue(a, b, c)\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000193 'stack() row 4')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000194
195args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
196test(args == ['x', 'y'], 'mod.fr args')
197test(varargs == None, 'mod.fr varargs')
198test(varkw == None, 'mod.fr varkw')
199test(locals == {'x': 11, 'p': 11, 'y': 14}, 'mod.fr locals')
200test(inspect.formatargvalues(args, varargs, varkw, locals) ==
201 '(x=11, y=14)', 'mod.fr formatted argvalues')
202
203args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
204test(args == ['a', 'b', 'c', 'd', ['e', ['f']]], 'mod.fr.f_back args')
205test(varargs == 'g', 'mod.fr.f_back varargs')
206test(varkw == 'h', 'mod.fr.f_back varkw')
207test(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')
210
Tim Peters243bff42001-03-04 00:30:25 +0000211for fname in files_to_clean_up:
212 try:
213 os.unlink(fname)
214 except:
215 pass
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000216
217# Test classic-class method resolution order.
218class A: pass
219class B(A): pass
220class C(A): pass
221class D(B, C): pass
222
223expected = (D, B, A, C)
224got = inspect.getmro(D)
225test(expected == got, "expected %r mro, got %r", expected, got)
226
227# The same w/ new-class MRO.
228class A(object): pass
229class B(A): pass
230class C(A): pass
231class D(B, C): pass
232
233expected = (D, B, C, A, object)
234got = inspect.getmro(D)
235test(expected == got, "expected %r mro, got %r", expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000236
237# Test classify_class_attrs.
238def attrs_wo_objs(cls):
239 return [t[:3] for t in inspect.classify_class_attrs(cls)]
240
241class A:
242 def s(): pass
243 s = staticmethod(s)
244
245 def c(cls): pass
246 c = classmethod(c)
247
248 def getp(self): pass
249 p = property(getp)
250
251 def m(self): pass
252
253 def m1(self): pass
254
255 datablob = '1'
256
257attrs = attrs_wo_objs(A)
258test(('s', 'static method', A) in attrs, 'missing static method')
259test(('c', 'class method', A) in attrs, 'missing class method')
260test(('p', 'property', A) in attrs, 'missing property')
261test(('m', 'method', A) in attrs, 'missing plain method')
262test(('m1', 'method', A) in attrs, 'missing plain method')
263test(('datablob', 'data', A) in attrs, 'missing data')
264
265class B(A):
266 def m(self): pass
267
268attrs = attrs_wo_objs(B)
269test(('s', 'static method', A) in attrs, 'missing static method')
270test(('c', 'class method', A) in attrs, 'missing class method')
271test(('p', 'property', A) in attrs, 'missing property')
272test(('m', 'method', B) in attrs, 'missing plain method')
273test(('m1', 'method', A) in attrs, 'missing plain method')
274test(('datablob', 'data', A) in attrs, 'missing data')
275
276
277class C(A):
278 def m(self): pass
279 def c(self): pass
280
281attrs = attrs_wo_objs(C)
282test(('s', 'static method', A) in attrs, 'missing static method')
283test(('c', 'method', C) in attrs, 'missing plain method')
284test(('p', 'property', A) in attrs, 'missing property')
285test(('m', 'method', C) in attrs, 'missing plain method')
286test(('m1', 'method', A) in attrs, 'missing plain method')
287test(('datablob', 'data', A) in attrs, 'missing data')
288
289class D(B, C):
290 def m1(self): pass
291
292attrs = attrs_wo_objs(D)
293test(('s', 'static method', A) in attrs, 'missing static method')
294test(('c', 'class method', A) in attrs, 'missing class method')
295test(('p', 'property', A) in attrs, 'missing property')
296test(('m', 'method', B) in attrs, 'missing plain method')
297test(('m1', 'method', D) in attrs, 'missing plain method')
298test(('datablob', 'data', A) in attrs, 'missing data')
299
Tim Peters60066292001-10-15 22:53:29 +0000300# Repeat all that, but w/ new-style classes.
Tim Peters13b49d32001-09-23 02:00:29 +0000301
302class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000303
304 def s(): pass
305 s = staticmethod(s)
306
307 def c(cls): pass
308 c = classmethod(c)
309
310 def getp(self): pass
311 p = property(getp)
312
313 def m(self): pass
314
315 def m1(self): pass
316
317 datablob = '1'
318
319attrs = attrs_wo_objs(A)
320test(('s', 'static method', A) in attrs, 'missing static method')
321test(('c', 'class method', A) in attrs, 'missing class method')
322test(('p', 'property', A) in attrs, 'missing property')
323test(('m', 'method', A) in attrs, 'missing plain method')
324test(('m1', 'method', A) in attrs, 'missing plain method')
325test(('datablob', 'data', A) in attrs, 'missing data')
326
327class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000328
329 def m(self): pass
330
331attrs = attrs_wo_objs(B)
332test(('s', 'static method', A) in attrs, 'missing static method')
333test(('c', 'class method', A) in attrs, 'missing class method')
334test(('p', 'property', A) in attrs, 'missing property')
335test(('m', 'method', B) in attrs, 'missing plain method')
336test(('m1', 'method', A) in attrs, 'missing plain method')
337test(('datablob', 'data', A) in attrs, 'missing data')
338
339
340class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000341
342 def m(self): pass
343 def c(self): pass
344
345attrs = attrs_wo_objs(C)
346test(('s', 'static method', A) in attrs, 'missing static method')
347test(('c', 'method', C) in attrs, 'missing plain method')
348test(('p', 'property', A) in attrs, 'missing property')
349test(('m', 'method', C) in attrs, 'missing plain method')
350test(('m1', 'method', A) in attrs, 'missing plain method')
351test(('datablob', 'data', A) in attrs, 'missing data')
352
353class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000354
355 def m1(self): pass
356
357attrs = attrs_wo_objs(D)
358test(('s', 'static method', A) in attrs, 'missing static method')
359test(('c', 'method', C) in attrs, 'missing plain method')
360test(('p', 'property', A) in attrs, 'missing property')
361test(('m', 'method', B) in attrs, 'missing plain method')
362test(('m1', 'method', D) in attrs, 'missing plain method')
363test(('datablob', 'data', A) in attrs, 'missing data')