blob: 33e0b0d7e172251b83d8cacb010bbc048aa99c79 [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
Martin v. Löwise59e2ba2003-05-03 09:09:02 +000064# isdatadescriptor
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000065
Barry Warsaw04f357c2002-07-23 19:04:11 +000066from test.test_support import TestFailed, TESTFN
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000067import sys, imp, os, string
68
69def test(assertion, message, *args):
70 if not assertion:
71 raise TestFailed, message % args
72
73import inspect
74
75file = open(TESTFN, 'w')
76file.write(source)
77file.close()
78
Tim Peters243bff42001-03-04 00:30:25 +000079# Note that load_source creates file TESTFN+'c' or TESTFN+'o'.
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000080mod = imp.load_source('testmod', TESTFN)
Tim Peters243bff42001-03-04 00:30:25 +000081files_to_clean_up = [TESTFN, TESTFN + 'c', TESTFN + 'o']
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +000082
83def istest(func, exp):
84 obj = eval(exp)
85 test(func(obj), '%s(%s)' % (func.__name__, exp))
86 for other in [inspect.isbuiltin, inspect.isclass, inspect.iscode,
87 inspect.isframe, inspect.isfunction, inspect.ismethod,
88 inspect.ismodule, inspect.istraceback]:
89 if other is not func:
90 test(not other(obj), 'not %s(%s)' % (other.__name__, exp))
91
92git = mod.StupidGit()
93try:
94 1/0
95except:
96 tb = sys.exc_traceback
97
98istest(inspect.isbuiltin, 'sys.exit')
99istest(inspect.isbuiltin, '[].append')
100istest(inspect.isclass, 'mod.StupidGit')
101istest(inspect.iscode, 'mod.spam.func_code')
102istest(inspect.isframe, 'tb.tb_frame')
103istest(inspect.isfunction, 'mod.spam')
104istest(inspect.ismethod, 'mod.StupidGit.abuse')
105istest(inspect.ismethod, 'git.argue')
106istest(inspect.ismodule, 'mod')
107istest(inspect.istraceback, 'tb')
Martin v. Löwise59e2ba2003-05-03 09:09:02 +0000108istest(inspect.isdatadescriptor, '__builtins__.file.closed')
109istest(inspect.isdatadescriptor, '__builtins__.file.softspace')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000110test(inspect.isroutine(mod.spam), 'isroutine(mod.spam)')
111test(inspect.isroutine([].count), 'isroutine([].count)')
112
113classes = inspect.getmembers(mod, inspect.isclass)
114test(classes ==
115 [('FesteringGob', mod.FesteringGob),
116 ('MalodorousPervert', mod.MalodorousPervert),
117 ('ParrotDroppings', mod.ParrotDroppings),
118 ('StupidGit', mod.StupidGit)], 'class list')
119tree = inspect.getclasstree(map(lambda x: x[1], classes), 1)
120test(tree ==
121 [(mod.ParrotDroppings, ()),
122 (mod.StupidGit, ()),
123 [(mod.MalodorousPervert, (mod.StupidGit,)),
124 [(mod.FesteringGob, (mod.MalodorousPervert, mod.ParrotDroppings))
125 ]
126 ]
127 ], 'class tree')
128
129functions = inspect.getmembers(mod, inspect.isfunction)
130test(functions == [('eggs', mod.eggs), ('spam', mod.spam)], 'function list')
131
132test(inspect.getdoc(mod) == 'A module docstring.', 'getdoc(mod)')
133test(inspect.getcomments(mod) == '# line 1\n', 'getcomments(mod)')
134test(inspect.getmodule(mod.StupidGit) == mod, 'getmodule(mod.StupidGit)')
135test(inspect.getfile(mod.StupidGit) == TESTFN, 'getfile(mod.StupidGit)')
136test(inspect.getsourcefile(mod.spam) == TESTFN, 'getsourcefile(mod.spam)')
137test(inspect.getsourcefile(git.abuse) == TESTFN, 'getsourcefile(git.abuse)')
138
139def sourcerange(top, bottom):
140 lines = string.split(source, '\n')
141 return string.join(lines[top-1:bottom], '\n') + '\n'
142
143test(inspect.getsource(git.abuse) == sourcerange(29, 39),
144 'getsource(git.abuse)')
145test(inspect.getsource(mod.StupidGit) == sourcerange(21, 46),
146 'getsource(mod.StupidGit)')
147test(inspect.getdoc(mod.StupidGit) ==
148 'A longer,\n\nindented\n\ndocstring.', 'getdoc(mod.StupidGit)')
149test(inspect.getdoc(git.abuse) ==
Ka-Ping Yeea59ef7b2002-11-30 03:53:15 +0000150 'Another\n\ndocstring\n\ncontaining\n\ntabs', 'getdoc(git.abuse)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000151test(inspect.getcomments(mod.StupidGit) == '# line 20\n',
152 'getcomments(mod.StupidGit)')
153
154args, varargs, varkw, defaults = inspect.getargspec(mod.eggs)
155test(args == ['x', 'y'], 'mod.eggs args')
156test(varargs == None, 'mod.eggs varargs')
157test(varkw == None, 'mod.eggs varkw')
158test(defaults == None, 'mod.eggs defaults')
159test(inspect.formatargspec(args, varargs, varkw, defaults) ==
160 '(x, y)', 'mod.eggs formatted argspec')
161args, varargs, varkw, defaults = inspect.getargspec(mod.spam)
162test(args == ['a', 'b', 'c', 'd', ['e', ['f']]], 'mod.spam args')
163test(varargs == 'g', 'mod.spam varargs')
164test(varkw == 'h', 'mod.spam varkw')
165test(defaults == (3, (4, (5,))), 'mod.spam defaults')
166test(inspect.formatargspec(args, varargs, varkw, defaults) ==
167 '(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h)',
168 'mod.spam formatted argspec')
169
170git.abuse(7, 8, 9)
171
172istest(inspect.istraceback, 'git.ex[2]')
173istest(inspect.isframe, 'mod.fr')
174
Ka-Ping Yeef170d7f2001-03-23 05:14:10 +0000175test(len(git.tr) == 3, 'trace() length')
176test(git.tr[0][1:] == (TESTFN, 46, 'argue',
177 [' self.tr = inspect.trace()\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000178 'trace() row 2')
Ka-Ping Yeef170d7f2001-03-23 05:14:10 +0000179test(git.tr[1][1:] == (TESTFN, 9, 'spam', [' eggs(b + d, c + f)\n'], 0),
180 'trace() row 2')
181test(git.tr[2][1:] == (TESTFN, 18, 'eggs', [' q = y / 0\n'], 0),
182 'trace() row 3')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000183
184test(len(mod.st) >= 5, 'stack() length')
185test(mod.st[0][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000186 (TESTFN, 16, 'eggs', [' st = inspect.stack()\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000187 'stack() row 1')
188test(mod.st[1][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000189 (TESTFN, 9, 'spam', [' eggs(b + d, c + f)\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000190 'stack() row 2')
191test(mod.st[2][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000192 (TESTFN, 43, 'argue', [' spam(a, b, c)\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000193 'stack() row 3')
194test(mod.st[3][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000195 (TESTFN, 39, 'abuse', [' self.argue(a, b, c)\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000196 'stack() row 4')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000197
198args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
199test(args == ['x', 'y'], 'mod.fr args')
200test(varargs == None, 'mod.fr varargs')
201test(varkw == None, 'mod.fr varkw')
202test(locals == {'x': 11, 'p': 11, 'y': 14}, 'mod.fr locals')
203test(inspect.formatargvalues(args, varargs, varkw, locals) ==
204 '(x=11, y=14)', 'mod.fr formatted argvalues')
205
206args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
207test(args == ['a', 'b', 'c', 'd', ['e', ['f']]], 'mod.fr.f_back args')
208test(varargs == 'g', 'mod.fr.f_back varargs')
209test(varkw == 'h', 'mod.fr.f_back varkw')
210test(inspect.formatargvalues(args, varargs, varkw, locals) ==
211 '(a=7, b=8, c=9, d=3, (e=4, (f=5,)), *g=(), **h={})',
212 'mod.fr.f_back formatted argvalues')
213
Tim Peters243bff42001-03-04 00:30:25 +0000214for fname in files_to_clean_up:
215 try:
216 os.unlink(fname)
217 except:
218 pass
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000219
220# Test classic-class method resolution order.
221class A: pass
222class B(A): pass
223class C(A): pass
224class D(B, C): pass
225
226expected = (D, B, A, C)
227got = inspect.getmro(D)
228test(expected == got, "expected %r mro, got %r", expected, got)
229
230# The same w/ new-class MRO.
231class A(object): pass
232class B(A): pass
233class C(A): pass
234class D(B, C): pass
235
236expected = (D, B, C, A, object)
237got = inspect.getmro(D)
238test(expected == got, "expected %r mro, got %r", expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000239
240# Test classify_class_attrs.
241def attrs_wo_objs(cls):
242 return [t[:3] for t in inspect.classify_class_attrs(cls)]
243
244class A:
245 def s(): pass
246 s = staticmethod(s)
247
248 def c(cls): pass
249 c = classmethod(c)
250
251 def getp(self): pass
252 p = property(getp)
253
254 def m(self): pass
255
256 def m1(self): pass
257
258 datablob = '1'
259
260attrs = attrs_wo_objs(A)
261test(('s', 'static method', A) in attrs, 'missing static method')
262test(('c', 'class method', A) in attrs, 'missing class method')
263test(('p', 'property', A) in attrs, 'missing property')
264test(('m', 'method', A) in attrs, 'missing plain method')
265test(('m1', 'method', A) in attrs, 'missing plain method')
266test(('datablob', 'data', A) in attrs, 'missing data')
267
268class B(A):
269 def m(self): pass
270
271attrs = attrs_wo_objs(B)
272test(('s', 'static method', A) in attrs, 'missing static method')
273test(('c', 'class method', A) in attrs, 'missing class method')
274test(('p', 'property', A) in attrs, 'missing property')
275test(('m', 'method', B) in attrs, 'missing plain method')
276test(('m1', 'method', A) in attrs, 'missing plain method')
277test(('datablob', 'data', A) in attrs, 'missing data')
278
279
280class C(A):
281 def m(self): pass
282 def c(self): pass
283
284attrs = attrs_wo_objs(C)
285test(('s', 'static method', A) in attrs, 'missing static method')
286test(('c', 'method', C) in attrs, 'missing plain method')
287test(('p', 'property', A) in attrs, 'missing property')
288test(('m', 'method', C) in attrs, 'missing plain method')
289test(('m1', 'method', A) in attrs, 'missing plain method')
290test(('datablob', 'data', A) in attrs, 'missing data')
291
292class D(B, C):
293 def m1(self): pass
294
295attrs = attrs_wo_objs(D)
296test(('s', 'static method', A) in attrs, 'missing static method')
297test(('c', 'class method', A) in attrs, 'missing class method')
298test(('p', 'property', A) in attrs, 'missing property')
299test(('m', 'method', B) in attrs, 'missing plain method')
300test(('m1', 'method', D) in attrs, 'missing plain method')
301test(('datablob', 'data', A) in attrs, 'missing data')
302
Tim Peters60066292001-10-15 22:53:29 +0000303# Repeat all that, but w/ new-style classes.
Tim Peters13b49d32001-09-23 02:00:29 +0000304
305class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000306
307 def s(): pass
308 s = staticmethod(s)
309
310 def c(cls): pass
311 c = classmethod(c)
312
313 def getp(self): pass
314 p = property(getp)
315
316 def m(self): pass
317
318 def m1(self): pass
319
320 datablob = '1'
321
322attrs = attrs_wo_objs(A)
323test(('s', 'static method', A) in attrs, 'missing static method')
324test(('c', 'class method', A) in attrs, 'missing class method')
325test(('p', 'property', A) in attrs, 'missing property')
326test(('m', 'method', A) in attrs, 'missing plain method')
327test(('m1', 'method', A) in attrs, 'missing plain method')
328test(('datablob', 'data', A) in attrs, 'missing data')
329
330class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000331
332 def m(self): pass
333
334attrs = attrs_wo_objs(B)
335test(('s', 'static method', A) in attrs, 'missing static method')
336test(('c', 'class method', A) in attrs, 'missing class method')
337test(('p', 'property', A) in attrs, 'missing property')
338test(('m', 'method', B) in attrs, 'missing plain method')
339test(('m1', 'method', A) in attrs, 'missing plain method')
340test(('datablob', 'data', A) in attrs, 'missing data')
341
342
343class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000344
345 def m(self): pass
346 def c(self): pass
347
348attrs = attrs_wo_objs(C)
349test(('s', 'static method', A) in attrs, 'missing static method')
350test(('c', 'method', C) in attrs, 'missing plain method')
351test(('p', 'property', A) in attrs, 'missing property')
352test(('m', 'method', C) in attrs, 'missing plain method')
353test(('m1', 'method', A) in attrs, 'missing plain method')
354test(('datablob', 'data', A) in attrs, 'missing data')
355
356class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000357
358 def m1(self): pass
359
360attrs = attrs_wo_objs(D)
361test(('s', 'static method', A) in attrs, 'missing static method')
362test(('c', 'method', C) in attrs, 'missing plain method')
363test(('p', 'property', A) in attrs, 'missing property')
364test(('m', 'method', B) in attrs, 'missing plain method')
365test(('m1', 'method', D) in attrs, 'missing plain method')
366test(('datablob', 'data', A) in attrs, 'missing data')