blob: 9167b14b7c297eb3810bf24059b04d10f69596d8 [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
65from test_support import TestFailed, TESTFN
66import 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) ==
147 'Another\n\ndocstring\n\ncontaining\n\ntabs\n\n', 'getdoc(git.abuse)')
148test(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
300# Repeat all that, but w/ new-style non-dynamic classes.
301
302class A(object):
303 __dynamic__ = 0
304
305 def s(): pass
306 s = staticmethod(s)
307
308 def c(cls): pass
309 c = classmethod(c)
310
311 def getp(self): pass
312 p = property(getp)
313
314 def m(self): pass
315
316 def m1(self): pass
317
318 datablob = '1'
319
320attrs = attrs_wo_objs(A)
321test(('s', 'static method', A) in attrs, 'missing static method')
322test(('c', 'class method', A) in attrs, 'missing class method')
323test(('p', 'property', A) in attrs, 'missing property')
324test(('m', 'method', A) in attrs, 'missing plain method')
325test(('m1', 'method', A) in attrs, 'missing plain method')
326test(('datablob', 'data', A) in attrs, 'missing data')
327
328class B(A):
329 __dynamic__ = 0
330
331 def m(self): pass
332
333attrs = attrs_wo_objs(B)
334test(('s', 'static method', A) in attrs, 'missing static method')
335test(('c', 'class method', A) in attrs, 'missing class method')
336test(('p', 'property', A) in attrs, 'missing property')
337test(('m', 'method', B) in attrs, 'missing plain method')
338test(('m1', 'method', A) in attrs, 'missing plain method')
339test(('datablob', 'data', A) in attrs, 'missing data')
340
341
342class C(A):
343 __dynamic__ = 0
344
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):
357 __dynamic__ = 0
358
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')
368
369# And again, but w/ new-style dynamic classes.
370
371class A(object):
372 __dynamic__ = 1
373
374 def s(): pass
375 s = staticmethod(s)
376
377 def c(cls): pass
378 c = classmethod(c)
379
380 def getp(self): pass
381 p = property(getp)
382
383 def m(self): pass
384
385 def m1(self): pass
386
387 datablob = '1'
388
389attrs = attrs_wo_objs(A)
390test(('s', 'static method', A) in attrs, 'missing static method')
391test(('c', 'class method', A) in attrs, 'missing class method')
392test(('p', 'property', A) in attrs, 'missing property')
393test(('m', 'method', A) in attrs, 'missing plain method')
394test(('m1', 'method', A) in attrs, 'missing plain method')
395test(('datablob', 'data', A) in attrs, 'missing data')
396
397class B(A):
398 __dynamic__ = 1
399
400 def m(self): pass
401
402attrs = attrs_wo_objs(B)
403test(('s', 'static method', A) in attrs, 'missing static method')
404test(('c', 'class method', A) in attrs, 'missing class method')
405test(('p', 'property', A) in attrs, 'missing property')
406test(('m', 'method', B) in attrs, 'missing plain method')
407test(('m1', 'method', A) in attrs, 'missing plain method')
408test(('datablob', 'data', A) in attrs, 'missing data')
409
410
411class C(A):
412 __dynamic__ = 1
413
414 def m(self): pass
415 def c(self): pass
416
417attrs = attrs_wo_objs(C)
418test(('s', 'static method', A) in attrs, 'missing static method')
419test(('c', 'method', C) in attrs, 'missing plain method')
420test(('p', 'property', A) in attrs, 'missing property')
421test(('m', 'method', C) in attrs, 'missing plain method')
422test(('m1', 'method', A) in attrs, 'missing plain method')
423test(('datablob', 'data', A) in attrs, 'missing data')
424
425class D(B, C):
426 __dynamic__ = 1
427
428 def m1(self): pass
429
430attrs = attrs_wo_objs(D)
431test(('s', 'static method', A) in attrs, 'missing static method')
432test(('c', 'method', C) in attrs, 'missing plain method')
433test(('p', 'property', A) in attrs, 'missing property')
434test(('m', 'method', B) in attrs, 'missing plain method')
435test(('m1', 'method', D) in attrs, 'missing plain method')
436test(('datablob', 'data', A) in attrs, 'missing data')