blob: e3bf73a85c20b9c90a609c87d38308b879a6f4fd [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
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000155git.abuse(7, 8, 9)
156
157istest(inspect.istraceback, 'git.ex[2]')
158istest(inspect.isframe, 'mod.fr')
159
Ka-Ping Yeef170d7f2001-03-23 05:14:10 +0000160test(len(git.tr) == 3, 'trace() length')
Andrew M. Kuchlingba8b6bc2004-06-05 14:11:59 +0000161test(git.tr[0][1:] == (TESTFN, 43, 'argue',
162 [' spam(a, b, c)\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000163 'trace() row 2')
Ka-Ping Yeef170d7f2001-03-23 05:14:10 +0000164test(git.tr[1][1:] == (TESTFN, 9, 'spam', [' eggs(b + d, c + f)\n'], 0),
165 'trace() row 2')
166test(git.tr[2][1:] == (TESTFN, 18, 'eggs', [' q = y / 0\n'], 0),
167 'trace() row 3')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000168
169test(len(mod.st) >= 5, 'stack() length')
170test(mod.st[0][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000171 (TESTFN, 16, 'eggs', [' st = inspect.stack()\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000172 'stack() row 1')
173test(mod.st[1][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000174 (TESTFN, 9, 'spam', [' eggs(b + d, c + f)\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000175 'stack() row 2')
176test(mod.st[2][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000177 (TESTFN, 43, 'argue', [' spam(a, b, c)\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000178 'stack() row 3')
179test(mod.st[3][1:] ==
Ka-Ping Yee90543442001-03-02 05:48:10 +0000180 (TESTFN, 39, 'abuse', [' self.argue(a, b, c)\n'], 0),
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000181 'stack() row 4')
Ka-Ping Yee6397c7c2001-02-27 14:43:21 +0000182
183args, varargs, varkw, locals = inspect.getargvalues(mod.fr)
184test(args == ['x', 'y'], 'mod.fr args')
185test(varargs == None, 'mod.fr varargs')
186test(varkw == None, 'mod.fr varkw')
187test(locals == {'x': 11, 'p': 11, 'y': 14}, 'mod.fr locals')
188test(inspect.formatargvalues(args, varargs, varkw, locals) ==
189 '(x=11, y=14)', 'mod.fr formatted argvalues')
190
191args, varargs, varkw, locals = inspect.getargvalues(mod.fr.f_back)
192test(args == ['a', 'b', 'c', 'd', ['e', ['f']]], 'mod.fr.f_back args')
193test(varargs == 'g', 'mod.fr.f_back varargs')
194test(varkw == 'h', 'mod.fr.f_back varkw')
195test(inspect.formatargvalues(args, varargs, varkw, locals) ==
196 '(a=7, b=8, c=9, d=3, (e=4, (f=5,)), *g=(), **h={})',
197 'mod.fr.f_back formatted argvalues')
198
Tim Peters243bff42001-03-04 00:30:25 +0000199for fname in files_to_clean_up:
200 try:
201 os.unlink(fname)
202 except:
203 pass
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000204
Johannes Gijsbersc473c992004-08-18 12:40:31 +0000205# Test for decorators as well.
206
207source = r"""
208def wrap(foo=None):
209 def wrapper(func):
210 return func
211 return wrapper
212
213def replace(func):
214 def insteadfunc():
215 print 'hello'
216 return insteadfunc
217
218# two decorators, one with argument
219@wrap()
220@wrap(wrap)
221def wrapped():
222 pass
223
224@replace
225def gone():
226 pass"""
227
228file = open(TESTFN + "2", "w")
229file.write(source)
230file.close()
231files_to_clean_up = [TESTFN + "2", TESTFN + '2c', TESTFN + '2o']
232
233mod2 = imp.load_source("testmod3", TESTFN + "2")
234
235test(inspect.getsource(mod2.wrapped) == sourcerange(13, 16),
236 "inspect.getsource(mod.wrapped)")
237test(inspect.getsource(mod2.gone) == sourcerange(8, 9),
238 "inspect.getsource(mod.gone)")
239
240for fname in files_to_clean_up:
241 try:
242 os.unlink(fname)
243 except:
244 pass
245
Tim Peterse0b2d7a2001-09-22 06:10:55 +0000246# Test classic-class method resolution order.
247class A: pass
248class B(A): pass
249class C(A): pass
250class D(B, C): pass
251
252expected = (D, B, A, C)
253got = inspect.getmro(D)
254test(expected == got, "expected %r mro, got %r", expected, got)
255
256# The same w/ new-class MRO.
257class A(object): pass
258class B(A): pass
259class C(A): pass
260class D(B, C): pass
261
262expected = (D, B, C, A, object)
263got = inspect.getmro(D)
264test(expected == got, "expected %r mro, got %r", expected, got)
Tim Peters13b49d32001-09-23 02:00:29 +0000265
266# Test classify_class_attrs.
267def attrs_wo_objs(cls):
268 return [t[:3] for t in inspect.classify_class_attrs(cls)]
269
270class A:
271 def s(): pass
272 s = staticmethod(s)
273
274 def c(cls): pass
275 c = classmethod(c)
276
277 def getp(self): pass
278 p = property(getp)
279
280 def m(self): pass
281
282 def m1(self): pass
283
284 datablob = '1'
285
286attrs = attrs_wo_objs(A)
287test(('s', 'static method', A) in attrs, 'missing static method')
288test(('c', 'class method', A) in attrs, 'missing class method')
289test(('p', 'property', A) in attrs, 'missing property')
290test(('m', 'method', A) in attrs, 'missing plain method')
291test(('m1', 'method', A) in attrs, 'missing plain method')
292test(('datablob', 'data', A) in attrs, 'missing data')
293
294class B(A):
295 def m(self): pass
296
297attrs = attrs_wo_objs(B)
298test(('s', 'static method', A) in attrs, 'missing static method')
299test(('c', 'class method', A) in attrs, 'missing class method')
300test(('p', 'property', A) in attrs, 'missing property')
301test(('m', 'method', B) in attrs, 'missing plain method')
302test(('m1', 'method', A) in attrs, 'missing plain method')
303test(('datablob', 'data', A) in attrs, 'missing data')
304
305
306class C(A):
307 def m(self): pass
308 def c(self): pass
309
310attrs = attrs_wo_objs(C)
311test(('s', 'static method', A) in attrs, 'missing static method')
312test(('c', 'method', C) in attrs, 'missing plain method')
313test(('p', 'property', A) in attrs, 'missing property')
314test(('m', 'method', C) in attrs, 'missing plain method')
315test(('m1', 'method', A) in attrs, 'missing plain method')
316test(('datablob', 'data', A) in attrs, 'missing data')
317
318class D(B, C):
319 def m1(self): pass
320
321attrs = attrs_wo_objs(D)
322test(('s', 'static method', A) in attrs, 'missing static method')
323test(('c', 'class method', A) in attrs, 'missing class method')
324test(('p', 'property', A) in attrs, 'missing property')
325test(('m', 'method', B) in attrs, 'missing plain method')
326test(('m1', 'method', D) in attrs, 'missing plain method')
327test(('datablob', 'data', A) in attrs, 'missing data')
328
Tim Peters60066292001-10-15 22:53:29 +0000329# Repeat all that, but w/ new-style classes.
Tim Peters13b49d32001-09-23 02:00:29 +0000330
331class A(object):
Tim Peters13b49d32001-09-23 02:00:29 +0000332
333 def s(): pass
334 s = staticmethod(s)
335
336 def c(cls): pass
337 c = classmethod(c)
338
339 def getp(self): pass
340 p = property(getp)
341
342 def m(self): pass
343
344 def m1(self): pass
345
346 datablob = '1'
347
348attrs = attrs_wo_objs(A)
349test(('s', 'static method', A) in attrs, 'missing static method')
350test(('c', 'class method', A) in attrs, 'missing class method')
351test(('p', 'property', A) in attrs, 'missing property')
352test(('m', 'method', A) in attrs, 'missing plain method')
353test(('m1', 'method', A) in attrs, 'missing plain method')
354test(('datablob', 'data', A) in attrs, 'missing data')
355
356class B(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000357
358 def m(self): pass
359
360attrs = attrs_wo_objs(B)
361test(('s', 'static method', A) in attrs, 'missing static method')
362test(('c', 'class method', A) in attrs, 'missing class method')
363test(('p', 'property', A) in attrs, 'missing property')
364test(('m', 'method', B) in attrs, 'missing plain method')
365test(('m1', 'method', A) in attrs, 'missing plain method')
366test(('datablob', 'data', A) in attrs, 'missing data')
367
368
369class C(A):
Tim Peters13b49d32001-09-23 02:00:29 +0000370
371 def m(self): pass
372 def c(self): pass
373
374attrs = attrs_wo_objs(C)
375test(('s', 'static method', A) in attrs, 'missing static method')
376test(('c', 'method', C) in attrs, 'missing plain method')
377test(('p', 'property', A) in attrs, 'missing property')
378test(('m', 'method', C) in attrs, 'missing plain method')
379test(('m1', 'method', A) in attrs, 'missing plain method')
380test(('datablob', 'data', A) in attrs, 'missing data')
381
382class D(B, C):
Tim Peters13b49d32001-09-23 02:00:29 +0000383
384 def m1(self): pass
385
386attrs = attrs_wo_objs(D)
387test(('s', 'static method', A) in attrs, 'missing static method')
388test(('c', 'method', C) in attrs, 'missing plain method')
389test(('p', 'property', A) in attrs, 'missing property')
390test(('m', 'method', B) in attrs, 'missing plain method')
391test(('m1', 'method', D) in attrs, 'missing plain method')
392test(('datablob', 'data', A) in attrs, 'missing data')
Jeremy Hyltonc4bf5ed2003-06-27 18:43:12 +0000393
394args, varargs, varkw, defaults = inspect.getargspec(mod.eggs)
395test(args == ['x', 'y'], 'mod.eggs args')
396test(varargs == None, 'mod.eggs varargs')
397test(varkw == None, 'mod.eggs varkw')
398test(defaults == None, 'mod.eggs defaults')
399test(inspect.formatargspec(args, varargs, varkw, defaults) ==
400 '(x, y)', 'mod.eggs formatted argspec')
401args, varargs, varkw, defaults = inspect.getargspec(mod.spam)
402test(args == ['a', 'b', 'c', 'd', ['e', ['f']]], 'mod.spam args')
403test(varargs == 'g', 'mod.spam varargs')
404test(varkw == 'h', 'mod.spam varkw')
405test(defaults == (3, (4, (5,))), 'mod.spam defaults')
406test(inspect.formatargspec(args, varargs, varkw, defaults) ==
407 '(a, b, c, d=3, (e, (f,))=(4, (5,)), *g, **h)',
408 'mod.spam formatted argspec')
409args, varargs, varkw, defaults = inspect.getargspec(A.m)
410test(args == ['self'], 'A.m args')
411test(varargs is None, 'A.m varargs')
412test(varkw is None, 'A.m varkw')
413test(defaults is None, 'A.m defaults')
Martin v. Löwis893ffa42003-10-31 15:35:53 +0000414
415# Doc/lib/libinspect.tex claims there are 11 such functions
416count = len(filter(lambda x:x.startswith('is'), dir(inspect)))
417test(count == 11, "There are %d (not 11) is* functions", count)
Matthias Klose2e829c02004-08-15 17:04:33 +0000418
419def sublistOfOne((foo)): return 1
420
421args, varargs, varkw, defaults = inspect.getargspec(sublistOfOne)
422test(args == [['foo']], 'sublistOfOne args')
423test(varargs is None, 'sublistOfOne varargs')
424test(varkw is None, 'sublistOfOne varkw')
425test(defaults is None, 'sublistOfOn defaults')