blob: c45c686d5c98bf08ad48a0cf0ff52fff8ba5da83 [file] [log] [blame]
Jack Jansencb5704e1998-08-18 14:59:10 +00001__version__ = "$Id$"
2
3import sys
4from time import time
5
6class Trace:
7 def __init__(self):
8 self.dispatch = {
9 'call': self.trace_dispatch_call,
10 'return': self.trace_dispatch_return,
11 'exception': self.trace_dispatch_exception,
12 }
13 self.curframe = None
14 self.depth = -1
15 self.stdout = sys.stdout
16
17 def run(self, cmd, globals = None, locals = None):
18 if globals is None:
19 import __main__
20 globals = __main__.__dict__
21 if locals is None:
22 locals = globals
23 sys.setprofile(self.trace_dispatch)
24 try:
25 exec cmd in globals, locals
26 finally:
27 sys.setprofile(None)
28
29 def runcall(self, func, *args):
30 sys.setprofile(self.trace_dispatch)
31 try:
32 apply(func, args)
33 finally:
34 sys.setprofile(None)
35
36 def trace_dispatch(self, frame, event, arg):
37 curstdout = sys.stdout
38 sys.stdout = self.stdout
39 self.dispatch[event](frame, arg)
40 sys.stdout = curstdout
41
42 def trace_dispatch_call(self, frame, arg):
43 self.depth = self.depth + 1
44 self.curframe = frame
45 code = frame.f_code
46 funcname = code.co_name
47 if not funcname:
48 funcname = '<lambda>'
49 filename = code.co_filename
50 lineno = frame.f_lineno
51 if lineno == -1:
52 code = code.co_code
53 if ord(code[0]) == 127: # SET_LINENO
54 lineno = ord(code[1]) | ord(code[2]) << 8
55 pframe = frame.f_back
56 if pframe:
57 plineno = ' (%d)' % pframe.f_lineno
58 else:
59 plineno = ''
60 print '%s> %s:%d %s%s' % (' '*self.depth,filename,lineno,funcname,plineno)
61 frame.f_locals['__start_time'] = time()
62
63 def trace_dispatch_return(self, frame, arg):
64 try:
65 t = frame.f_locals['__start_time']
66 except KeyError:
67 t = ''
68 else:
69 t = ' [%.4f]' % (time() - t)
70 funcname = frame.f_code.co_name
71 self.curframe = frame.f_back
72 if not funcname:
73 funcname = '<lambda>'
74 filename = frame.f_code.co_filename
75 print '%s< %s:%d %s%s' % (' '*self.depth,filename,frame.f_lineno,funcname,t)
76 self.depth = self.depth - 1
77
78 def trace_dispatch_exception(self, frame, arg):
79 t = ''
80 if frame is not self.curframe:
81 try:
82 t = frame.f_locals['__start_time']
83 except KeyError:
84 pass
85 else:
86 t = ' [%.4f]' % (time() - t)
87 self.depth = self.depth - 1
88 self.curframe = frame
89 funcname = frame.f_code.co_name
90 if not funcname:
91 funcname = '<lambda>'
92 filename = frame.f_code.co_filename
93 print '%sE %s:%d %s%s' % (' '*(self.depth+1),filename,frame.f_lineno,funcname,t)
94
95 def set_trace(self):
96 try:
97 raise 'xyzzy'
98 except:
99 frame = sys.exc_traceback.tb_frame
100 while frame.f_code.co_name != 'set_trace':
101 frame = frame.f_back
102 d = 0
103 while frame:
104 d = d + 1
105 frame = frame.f_back
106 self.depth = d
107 sys.setprofile(self.trace_dispatch)
108
109def run(cmd, globals = None, locals = None):
110 Trace().run(cmd, globals, locals)
111
112def runcall(*func_args):
113 apply(Trace().runcall, funcargs)
114
115def set_trace():
116 Trace().set_trace()
117
118def unset_trace():
119 sys.setprofile(None)