blob: c67c23c414dfb70c8e7c994e7f2ee9b300f33227 [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öwis4d28d962003-05-03 09:58:26 +0000108import __builtin__
109istest(inspect.isdatadescriptor, '__builtin__.file.closed')
110istest(inspect.isdatadescriptor, '__builtin__.file.softspace')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000111test(inspect.isroutine(mod.spam), 'isroutine(mod.spam)')
112test(inspect.isroutine([].count), 'isroutine([].count)')
113
114classes = inspect.getmembers(mod, inspect.isclass)
115test(classes ==
116 [('FesteringGob', mod.FesteringGob),
117 ('MalodorousPervert', mod.MalodorousPervert),
118 ('ParrotDroppings', mod.ParrotDroppings),
119 ('StupidGit', mod.StupidGit)], 'class list')
120tree = inspect.getclasstree(map(lambda x: x[1], classes), 1)
121test(tree ==
122 [(mod.ParrotDroppings, ()),
123 (mod.StupidGit, ()),
124 [(mod.MalodorousPervert, (mod.StupidGit,)),
125 [(mod.FesteringGob, (mod.MalodorousPervert, mod.ParrotDroppings))
126 ]
127 ]
128 ], 'class tree')
129
130functions = inspect.getmembers(mod, inspect.isfunction)
131test(functions == [('eggs', mod.eggs), ('spam', mod.spam)], 'function list')
132
133test(inspect.getdoc(mod) == 'A module docstring.', 'getdoc(mod)')
134test(inspect.getcomments(mod) == '# line 1\n', 'getcomments(mod)')
135test(inspect.getmodule(mod.StupidGit) == mod, 'getmodule(mod.StupidGit)')
136test(inspect.getfile(mod.StupidGit) == TESTFN, 'getfile(mod.StupidGit)')
137test(inspect.getsourcefile(mod.spam) == TESTFN, 'getsourcefile(mod.spam)')
138test(inspect.getsourcefile(git.abuse) == TESTFN, 'getsourcefile(git.abuse)')
139
140def sourcerange(top, bottom):
141 lines = string.split(source, '\n')
142 return string.join(lines[top-1:bottom], '\n') + '\n'
143
144test(inspect.getsource(git.abuse) == sourcerange(29, 39),
145 'getsource(git.abuse)')
146test(inspect.getsource(mod.StupidGit) == sourcerange(21, 46),
147 'getsource(mod.StupidGit)')
148test(inspect.getdoc(mod.StupidGit) ==
149 'A longer,\n\nindented\n\ndocstring.', 'getdoc(mod.StupidGit)')
150test(inspect.getdoc(git.abuse) ==
Ka-Ping Yeea59ef7b2002-11-30 03:53:15 +0000151 'Another\n\ndocstring\n\ncontaining\n\ntabs', 'getdoc(git.abuse)')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000152test(inspect.getcomments(mod.StupidGit) == '# line 20\n',
153 'getcomments(mod.StupidGit)')
154
155args, varargs, varkw, defaults = inspect.getargspec(mod.eggs)
156test(args == ['x', 'y'], 'mod.eggs args')
157test(varargs == None, 'mod.eggs varargs')
158test(varkw == None, 'mod.eggs varkw')
159test(defaults == None, 'mod.eggs defaults')
160test(inspect.formatargspec(args, varargs, varkw, defaults) ==
161 '(x, y)', 'mod.eggs formatted argspec')
162args, varargs, varkw, defaults = inspect.getargspec(mod.spam)
163test(args == ['a', 'b', 'c', 'd', ['e', ['f']]], 'mod.spam args')
164test(varargs == 'g', 'mod.spam varargs')
165test(varkw == 'h', 'mod.spam varkw')
166test(defaults == (3, (4, (5,))), 'mod.spam defaults')
167test(inspect.formatargspec(args, varargs, varkw, defaults) ==
168 '(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h)',
169 'mod.spam formatted argspec')
170
171git.abuse(7, 8, 9)
172
173istest(inspect.istraceback, 'git.ex[2]')
174istest(inspect.isframe, 'mod.fr')
175
Ka-Ping Yeef170d7f2001-03-23 05:14:10 +0000176test(len(git.tr) == 3, 'trace() length')
177test(git.tr[0][1:] == (TESTFN, 46, 'argue',
178 [' self.tr = inspect.trace()\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000179 'trace() row 2')
Ka-Ping Yeef170d7f2001-03-23 05:14:10 +0000180test(git.tr[1][1:] == (TESTFN, 9, 'spam', [' eggs(b + d, c + f)\n'], 0),
181 'trace() row 2')
182test(git.tr[2][1:] == (TESTFN, 18, 'eggs', [' q = y / 0\n'], 0),
183 'trace() row 3')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000184
185test(len(mod.st) >= 5, 'stack() length')
186test(mod.st[0][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000187 (TESTFN, 16, 'eggs', [' st = inspect.stack()\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000188 'stack() row 1')
189test(mod.st[1][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000190 (TESTFN, 9, 'spam', [' eggs(b + d, c + f)\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000191 'stack() row 2')
192test(mod.st[2][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000193 (TESTFN, 43, 'argue', [' spam(a, b, c)\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000194 'stack() row 3')
195test(mod.st[3][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000196 (TESTFN, 39, 'abuse', [' self.argue(a, b, c)\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000197 'stack() row 4')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000198
199args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
200test(args == ['x', 'y'], 'mod.fr args')
201test(varargs == None, 'mod.fr varargs')
202test(varkw == None, 'mod.fr varkw')
203test(locals == {'x': 11, 'p': 11, 'y': 14}, 'mod.fr locals')
204test(inspect.formatargvalues(args, varargs, varkw, locals) ==
205 '(x=11, y=14)', 'mod.fr formatted argvalues')
206
207args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
208test(args == ['a', 'b', 'c', 'd', ['e', ['f']]], 'mod.fr.f_back args')
209test(varargs == 'g', 'mod.fr.f_back varargs')
210test(varkw == 'h', 'mod.fr.f_back varkw')
211test(inspect.formatargvalues(args, varargs, varkw, locals) ==
212 '(a=7, b=8, c=9, d=3, (e=4, (f=5,)), *g=(), **h={})',
213 'mod.fr.f_back formatted argvalues')
214
Tim Peters243bff42001-03-04 00:30:25 +0000215for fname in files_to_clean_up:
216 try:
217 os.unlink(fname)
218 except:
219 pass
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000220
221# Test classic-class method resolution order.
222class A: pass
223class B(A): pass
224class C(A): pass
225class D(B, C): pass
226
227expected = (D, B, A, C)
228got = inspect.getmro(D)
229test(expected == got, "expected %r mro, got %r", expected, got)
230
231# The same w/ new-class MRO.
232class A(object): pass
233class B(A): pass
234class C(A): pass
235class D(B, C): pass
236
237expected = (D, B, C, A, object)
238got = inspect.getmro(D)
239test(expected == got, "expected %r mro, got %r", expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000240
241# Test classify_class_attrs.
242def attrs_wo_objs(cls):
243 return [t[:3] for t in inspect.classify_class_attrs(cls)]
244
245class A:
246 def s(): pass
247 s = staticmethod(s)
248
249 def c(cls): pass
250 c = classmethod(c)
251
252 def getp(self): pass
253 p = property(getp)
254
255 def m(self): pass
256
257 def m1(self): pass
258
259 datablob = '1'
260
261attrs = attrs_wo_objs(A)
262test(('s', 'static method', A) in attrs, 'missing static method')
263test(('c', 'class method', A) in attrs, 'missing class method')
264test(('p', 'property', A) in attrs, 'missing property')
265test(('m', 'method', A) in attrs, 'missing plain method')
266test(('m1', 'method', A) in attrs, 'missing plain method')
267test(('datablob', 'data', A) in attrs, 'missing data')
268
269class B(A):
270 def m(self): pass
271
272attrs = attrs_wo_objs(B)
273test(('s', 'static method', A) in attrs, 'missing static method')
274test(('c', 'class method', A) in attrs, 'missing class method')
275test(('p', 'property', A) in attrs, 'missing property')
276test(('m', 'method', B) in attrs, 'missing plain method')
277test(('m1', 'method', A) in attrs, 'missing plain method')
278test(('datablob', 'data', A) in attrs, 'missing data')
279
280
281class C(A):
282 def m(self): pass
283 def c(self): pass
284
285attrs = attrs_wo_objs(C)
286test(('s', 'static method', A) in attrs, 'missing static method')
287test(('c', 'method', C) in attrs, 'missing plain method')
288test(('p', 'property', A) in attrs, 'missing property')
289test(('m', 'method', C) in attrs, 'missing plain method')
290test(('m1', 'method', A) in attrs, 'missing plain method')
291test(('datablob', 'data', A) in attrs, 'missing data')
292
293class D(B, C):
294 def m1(self): pass
295
296attrs = attrs_wo_objs(D)
297test(('s', 'static method', A) in attrs, 'missing static method')
298test(('c', 'class method', A) in attrs, 'missing class method')
299test(('p', 'property', A) in attrs, 'missing property')
300test(('m', 'method', B) in attrs, 'missing plain method')
301test(('m1', 'method', D) in attrs, 'missing plain method')
302test(('datablob', 'data', A) in attrs, 'missing data')
303
Tim Peters60066292001-10-15 22:53:29 +0000304# Repeat all that, but w/ new-style classes.
Tim Peters13b49d32001-09-23 02:00:29 +0000305
306class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000307
308 def s(): pass
309 s = staticmethod(s)
310
311 def c(cls): pass
312 c = classmethod(c)
313
314 def getp(self): pass
315 p = property(getp)
316
317 def m(self): pass
318
319 def m1(self): pass
320
321 datablob = '1'
322
323attrs = attrs_wo_objs(A)
324test(('s', 'static method', A) in attrs, 'missing static method')
325test(('c', 'class method', A) in attrs, 'missing class method')
326test(('p', 'property', A) in attrs, 'missing property')
327test(('m', 'method', A) in attrs, 'missing plain method')
328test(('m1', 'method', A) in attrs, 'missing plain method')
329test(('datablob', 'data', A) in attrs, 'missing data')
330
331class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000332
333 def m(self): pass
334
335attrs = attrs_wo_objs(B)
336test(('s', 'static method', A) in attrs, 'missing static method')
337test(('c', 'class method', A) in attrs, 'missing class method')
338test(('p', 'property', A) in attrs, 'missing property')
339test(('m', 'method', B) in attrs, 'missing plain method')
340test(('m1', 'method', A) in attrs, 'missing plain method')
341test(('datablob', 'data', A) in attrs, 'missing data')
342
343
344class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000345
346 def m(self): pass
347 def c(self): pass
348
349attrs = attrs_wo_objs(C)
350test(('s', 'static method', A) in attrs, 'missing static method')
351test(('c', 'method', C) in attrs, 'missing plain method')
352test(('p', 'property', A) in attrs, 'missing property')
353test(('m', 'method', C) in attrs, 'missing plain method')
354test(('m1', 'method', A) in attrs, 'missing plain method')
355test(('datablob', 'data', A) in attrs, 'missing data')
356
357class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000358
359 def m1(self): pass
360
361attrs = attrs_wo_objs(D)
362test(('s', 'static method', A) in attrs, 'missing static method')
363test(('c', 'method', C) in attrs, 'missing plain method')
364test(('p', 'property', A) in attrs, 'missing property')
365test(('m', 'method', B) in attrs, 'missing plain method')
366test(('m1', 'method', D) in attrs, 'missing plain method')
367test(('datablob', 'data', A) in attrs, 'missing data')