1990-12-26 15:40:07 +00:00
|
|
|
# Print tracebacks, with a dump of local variables.
|
|
|
|
# Also an interactive stack trace browser.
|
|
|
|
|
|
|
|
import sys
|
1992-01-12 23:27:56 +00:00
|
|
|
import os
|
1990-12-26 15:40:07 +00:00
|
|
|
from stat import *
|
|
|
|
import string
|
1992-01-12 23:27:56 +00:00
|
|
|
import linecache
|
1990-12-26 15:40:07 +00:00
|
|
|
|
|
|
|
def br(): browser(sys.last_traceback)
|
|
|
|
|
|
|
|
def tb(): printtb(sys.last_traceback)
|
|
|
|
|
|
|
|
def browser(tb):
|
|
|
|
if not tb:
|
|
|
|
print 'No traceback.'
|
|
|
|
return
|
|
|
|
tblist = []
|
|
|
|
while tb:
|
|
|
|
tblist.append(tb)
|
|
|
|
tb = tb.tb_next
|
|
|
|
ptr = len(tblist)-1
|
|
|
|
tb = tblist[ptr]
|
|
|
|
while 1:
|
|
|
|
if tb <> tblist[ptr]:
|
|
|
|
tb = tblist[ptr]
|
|
|
|
print `ptr` + ':',
|
|
|
|
printtbheader(tb)
|
|
|
|
try:
|
|
|
|
line = raw_input('TB: ')
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
print '\n[Interrupted]'
|
|
|
|
break
|
|
|
|
except EOFError:
|
|
|
|
print '\n[EOF]'
|
|
|
|
break
|
|
|
|
cmd = string.strip(line)
|
|
|
|
if cmd:
|
1992-01-01 19:35:13 +00:00
|
|
|
if cmd == 'quit':
|
1990-12-26 15:40:07 +00:00
|
|
|
break
|
1992-01-01 19:35:13 +00:00
|
|
|
elif cmd == 'list':
|
1990-12-26 15:40:07 +00:00
|
|
|
browserlist(tb)
|
1992-01-01 19:35:13 +00:00
|
|
|
elif cmd == 'up':
|
1990-12-26 15:40:07 +00:00
|
|
|
if ptr-1 >= 0: ptr = ptr-1
|
|
|
|
else: print 'Bottom of stack.'
|
1992-01-01 19:35:13 +00:00
|
|
|
elif cmd == 'down':
|
1990-12-26 15:40:07 +00:00
|
|
|
if ptr+1 < len(tblist): ptr = ptr+1
|
|
|
|
else: print 'Top of stack.'
|
1992-01-01 19:35:13 +00:00
|
|
|
elif cmd == 'locals':
|
1990-12-26 15:40:07 +00:00
|
|
|
printsymbols(tb.tb_frame.f_locals)
|
1992-01-01 19:35:13 +00:00
|
|
|
elif cmd == 'globals':
|
1990-12-26 15:40:07 +00:00
|
|
|
printsymbols(tb.tb_frame.f_globals)
|
|
|
|
elif cmd in ('?', 'help'):
|
|
|
|
browserhelp()
|
|
|
|
else:
|
|
|
|
browserexec(tb, cmd)
|
|
|
|
|
|
|
|
def browserlist(tb):
|
|
|
|
filename = tb.tb_frame.f_code.co_filename
|
|
|
|
lineno = tb.tb_lineno
|
|
|
|
last = lineno
|
|
|
|
first = max(1, last-10)
|
|
|
|
for i in range(first, last+1):
|
1992-01-01 19:35:13 +00:00
|
|
|
if i == lineno: prefix = '***' + string.rjust(`i`, 4) + ':'
|
1990-12-26 15:40:07 +00:00
|
|
|
else: prefix = string.rjust(`i`, 7) + ':'
|
1992-01-12 23:27:56 +00:00
|
|
|
line = linecache.getline(filename, i)
|
1992-01-01 19:35:13 +00:00
|
|
|
if line[-1:] == '\n': line = line[:-1]
|
1990-12-26 15:40:07 +00:00
|
|
|
print prefix + line
|
|
|
|
|
|
|
|
def browserexec(tb, cmd):
|
|
|
|
locals = tb.tb_frame.f_locals
|
|
|
|
globals = tb.tb_frame.f_globals
|
|
|
|
try:
|
|
|
|
exec(cmd+'\n', globals, locals)
|
|
|
|
except:
|
|
|
|
print '*** Exception:',
|
|
|
|
print sys.exc_type,
|
|
|
|
if sys.exc_value <> None:
|
|
|
|
print ':', sys.exc_value,
|
|
|
|
print
|
|
|
|
print 'Type help to get help.'
|
|
|
|
|
|
|
|
def browserhelp():
|
|
|
|
print
|
|
|
|
print ' This is the traceback browser. Commands are:'
|
|
|
|
print ' up : move one level up in the call stack'
|
|
|
|
print ' down : move one level down in the call stack'
|
|
|
|
print ' locals : print all local variables at this level'
|
|
|
|
print ' globals : print all global variables at this level'
|
|
|
|
print ' list : list source code around the failure'
|
|
|
|
print ' help : print help (what you are reading now)'
|
|
|
|
print ' quit : back to command interpreter'
|
|
|
|
print ' Typing any other 1-line statement will execute it'
|
|
|
|
print ' using the current level\'s symbol tables'
|
|
|
|
print
|
|
|
|
|
|
|
|
def printtb(tb):
|
|
|
|
while tb:
|
|
|
|
print1tb(tb)
|
|
|
|
tb = tb.tb_next
|
|
|
|
|
|
|
|
def print1tb(tb):
|
|
|
|
printtbheader(tb)
|
|
|
|
if tb.tb_frame.f_locals is not tb.tb_frame.f_globals:
|
|
|
|
printsymbols(tb.tb_frame.f_locals)
|
|
|
|
|
|
|
|
def printtbheader(tb):
|
|
|
|
filename = tb.tb_frame.f_code.co_filename
|
|
|
|
lineno = tb.tb_lineno
|
|
|
|
info = '"' + filename + '"(' + `lineno` + ')'
|
1992-01-12 23:27:56 +00:00
|
|
|
line = linecache.getline(filename, lineno)
|
1990-12-26 15:40:07 +00:00
|
|
|
if line:
|
|
|
|
info = info + ': ' + string.strip(line)
|
|
|
|
print info
|
|
|
|
|
|
|
|
def printsymbols(d):
|
|
|
|
keys = d.keys()
|
|
|
|
keys.sort()
|
|
|
|
for name in keys:
|
|
|
|
print ' ' + string.ljust(name, 12) + ':',
|
|
|
|
printobject(d[name], 4)
|
|
|
|
print
|
|
|
|
|
|
|
|
def printobject(v, maxlevel):
|
1992-01-01 19:35:13 +00:00
|
|
|
if v == None:
|
1990-12-26 15:40:07 +00:00
|
|
|
print 'None',
|
|
|
|
elif type(v) in (type(0), type(0.0)):
|
|
|
|
print v,
|
1992-01-01 19:35:13 +00:00
|
|
|
elif type(v) == type(''):
|
1990-12-26 15:40:07 +00:00
|
|
|
if len(v) > 20:
|
|
|
|
print `v[:17] + '...'`,
|
|
|
|
else:
|
|
|
|
print `v`,
|
1992-01-01 19:35:13 +00:00
|
|
|
elif type(v) == type(()):
|
1990-12-26 15:40:07 +00:00
|
|
|
print '(',
|
|
|
|
printlist(v, maxlevel)
|
|
|
|
print ')',
|
1992-01-01 19:35:13 +00:00
|
|
|
elif type(v) == type([]):
|
1990-12-26 15:40:07 +00:00
|
|
|
print '[',
|
|
|
|
printlist(v, maxlevel)
|
|
|
|
print ']',
|
1992-01-01 19:35:13 +00:00
|
|
|
elif type(v) == type({}):
|
1990-12-26 15:40:07 +00:00
|
|
|
print '{',
|
|
|
|
printdict(v, maxlevel)
|
|
|
|
print '}',
|
|
|
|
else:
|
|
|
|
print v,
|
|
|
|
|
|
|
|
def printlist(v, maxlevel):
|
|
|
|
n = len(v)
|
1992-01-01 19:35:13 +00:00
|
|
|
if n == 0: return
|
1990-12-26 15:40:07 +00:00
|
|
|
if maxlevel <= 0:
|
|
|
|
print '...',
|
|
|
|
return
|
|
|
|
for i in range(min(6, n)):
|
|
|
|
printobject(v[i], maxlevel-1)
|
|
|
|
if i+1 < n: print ',',
|
|
|
|
if n > 6: print '...',
|
|
|
|
|
|
|
|
def printdict(v, maxlevel):
|
|
|
|
keys = v.keys()
|
|
|
|
n = len(keys)
|
1992-01-01 19:35:13 +00:00
|
|
|
if n == 0: return
|
1990-12-26 15:40:07 +00:00
|
|
|
if maxlevel <= 0:
|
|
|
|
print '...',
|
|
|
|
return
|
|
|
|
keys.sort()
|
|
|
|
for i in range(min(6, n)):
|
|
|
|
key = keys[i]
|
|
|
|
print `key` + ':',
|
|
|
|
printobject(v[key], maxlevel-1)
|
|
|
|
if i+1 < n: print ',',
|
|
|
|
if n > 6: print '...',
|