Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | # Print tracebacks, with a dump of local variables. |
2 | # Also an interactive stack trace browser. | |
3 | # Note -- this module is obsolete -- use pdb.pm() instead. | |
4 | ||
5 | import sys | |
6 | import os | |
7 | from stat import * | |
8 | import linecache | |
9 | ||
10 | def br(): browser(sys.last_traceback) | |
11 | ||
12 | def tb(): printtb(sys.last_traceback) | |
13 | ||
14 | def browser(tb): | |
15 | if not tb: | |
16 | print 'No traceback.' | |
17 | return | |
18 | tblist = [] | |
19 | while tb: | |
20 | tblist.append(tb) | |
21 | tb = tb.tb_next | |
22 | ptr = len(tblist)-1 | |
23 | tb = tblist[ptr] | |
24 | while 1: | |
25 | if tb != tblist[ptr]: | |
26 | tb = tblist[ptr] | |
27 | print `ptr` + ':', | |
28 | printtbheader(tb) | |
29 | try: | |
30 | line = raw_input('TB: ') | |
31 | except KeyboardInterrupt: | |
32 | print '\n[Interrupted]' | |
33 | break | |
34 | except EOFError: | |
35 | print '\n[EOF]' | |
36 | break | |
37 | cmd = line.strip() | |
38 | if cmd: | |
39 | if cmd == 'quit': | |
40 | break | |
41 | elif cmd == 'list': | |
42 | browserlist(tb) | |
43 | elif cmd == 'up': | |
44 | if ptr-1 >= 0: ptr = ptr-1 | |
45 | else: print 'Bottom of stack.' | |
46 | elif cmd == 'down': | |
47 | if ptr+1 < len(tblist): ptr = ptr+1 | |
48 | else: print 'Top of stack.' | |
49 | elif cmd == 'locals': | |
50 | printsymbols(tb.tb_frame.f_locals) | |
51 | elif cmd == 'globals': | |
52 | printsymbols(tb.tb_frame.f_globals) | |
53 | elif cmd in ('?', 'help'): | |
54 | browserhelp() | |
55 | else: | |
56 | browserexec(tb, cmd) | |
57 | ||
58 | def browserlist(tb): | |
59 | filename = tb.tb_frame.f_code.co_filename | |
60 | lineno = tb.tb_lineno | |
61 | last = lineno | |
62 | first = max(1, last-10) | |
63 | for i in range(first, last+1): | |
64 | if i == lineno: prefix = '***' + `i`.rjust(4) + ':' | |
65 | else: prefix = `i`.rjust(7) + ':' | |
66 | line = linecache.getline(filename, i) | |
67 | if line[-1:] == '\n': line = line[:-1] | |
68 | print prefix + line | |
69 | ||
70 | def browserexec(tb, cmd): | |
71 | locals = tb.tb_frame.f_locals | |
72 | globals = tb.tb_frame.f_globals | |
73 | try: | |
74 | exec cmd+'\n' in globals, locals | |
75 | except: | |
76 | t, v = sys.exc_info()[:2] | |
77 | print '*** Exception:', | |
78 | if type(t) is type(''): | |
79 | print t, | |
80 | else: | |
81 | print t.__name__, | |
82 | if v is not None: | |
83 | print ':', v, | |
84 | ||
85 | print 'Type help to get help.' | |
86 | ||
87 | def browserhelp(): | |
88 | ||
89 | print ' This is the traceback browser. Commands are:' | |
90 | print ' up : move one level up in the call stack' | |
91 | print ' down : move one level down in the call stack' | |
92 | print ' locals : print all local variables at this level' | |
93 | print ' globals : print all global variables at this level' | |
94 | print ' list : list source code around the failure' | |
95 | print ' help : print help (what you are reading now)' | |
96 | print ' quit : back to command interpreter' | |
97 | print ' Typing any other 1-line statement will execute it' | |
98 | print ' using the current level\'s symbol tables' | |
99 | ||
100 | ||
101 | def printtb(tb): | |
102 | while tb: | |
103 | print1tb(tb) | |
104 | tb = tb.tb_next | |
105 | ||
106 | def print1tb(tb): | |
107 | printtbheader(tb) | |
108 | if tb.tb_frame.f_locals is not tb.tb_frame.f_globals: | |
109 | printsymbols(tb.tb_frame.f_locals) | |
110 | ||
111 | def printtbheader(tb): | |
112 | filename = tb.tb_frame.f_code.co_filename | |
113 | lineno = tb.tb_lineno | |
114 | info = '"' + filename + '"(' + `lineno` + ')' | |
115 | line = linecache.getline(filename, lineno) | |
116 | if line: | |
117 | info = info + ': ' + line.strip() | |
118 | print info | |
119 | ||
120 | def printsymbols(d): | |
121 | keys = d.keys() | |
122 | keys.sort() | |
123 | for name in keys: | |
124 | print ' ' + name.ljust(12) + ':', | |
125 | printobject(d[name], 4) | |
126 | ||
127 | ||
128 | def printobject(v, maxlevel): | |
129 | if v is None: | |
130 | print 'None', | |
131 | elif type(v) in (type(0), type(0.0)): | |
132 | print v, | |
133 | elif type(v) is type(''): | |
134 | if len(v) > 20: | |
135 | print `v[:17] + '...'`, | |
136 | else: | |
137 | print `v`, | |
138 | elif type(v) is type(()): | |
139 | print '(', | |
140 | printlist(v, maxlevel) | |
141 | print ')', | |
142 | elif type(v) is type([]): | |
143 | print '[', | |
144 | printlist(v, maxlevel) | |
145 | print ']', | |
146 | elif type(v) is type({}): | |
147 | print '{', | |
148 | printdict(v, maxlevel) | |
149 | print '}', | |
150 | else: | |
151 | print v, | |
152 | ||
153 | def printlist(v, maxlevel): | |
154 | n = len(v) | |
155 | if n == 0: return | |
156 | if maxlevel <= 0: | |
157 | print '...', | |
158 | return | |
159 | for i in range(min(6, n)): | |
160 | printobject(v[i], maxlevel-1) | |
161 | if i+1 < n: print ',', | |
162 | if n > 6: print '...', | |
163 | ||
164 | def printdict(v, maxlevel): | |
165 | keys = v.keys() | |
166 | n = len(keys) | |
167 | if n == 0: return | |
168 | if maxlevel <= 0: | |
169 | print '...', | |
170 | return | |
171 | keys.sort() | |
172 | for i in range(min(6, n)): | |
173 | key = keys[i] | |
174 | print `key` + ':', | |
175 | printobject(v[key], maxlevel-1) | |
176 | if i+1 < n: print ',', | |
177 | if n > 6: print '...', |