blob: 61bbceefe05770e11884bd34516a6edc06792826 [file] [log] [blame]
Enrico Granatac8b36f12013-05-07 19:49:59 +00001import sys
2import inspect
3from collections import OrderedDict
4
5class TracebackFancy:
6 def __init__(self,traceback):
7 self.t = traceback
8
9 def getFrame(self):
10 return FrameFancy(self.t.tb_frame)
11
12 def getLineNumber(self):
Enrico Granata78f05f12013-05-07 21:42:18 +000013 return self.t.tb_lineno if self.t != None else None
Enrico Granatac8b36f12013-05-07 19:49:59 +000014
15 def getNext(self):
16 return TracebackFancy(self.t.tb_next)
17
18 def __str__(self):
19 if self.t == None:
20 return ""
21 str_self = "%s @ %s" % (self.getFrame().getName(), self.getLineNumber())
22 return str_self + "\n" + self.getNext().__str__()
23
24class ExceptionFancy:
25 def __init__(self,frame):
26 self.etraceback = frame.f_exc_traceback
27 self.etype = frame.exc_type
28 self.evalue = frame.f_exc_value
29
30 def __init__(self,tb,ty,va):
31 self.etraceback = tb
32 self.etype = ty
33 self.evalue = va
34
35 def getTraceback(self):
36 return TracebackFancy(self.etraceback)
37
38 def __nonzero__(self):
39 return self.etraceback != None or self.etype != None or self.evalue != None
40
41 def getType(self):
42 return str(self.etype)
43
44 def getValue(self):
45 return self.evalue
46
47class CodeFancy:
48 def __init__(self,code):
49 self.c = code
50
51 def getArgCount(self):
Enrico Granata78f05f12013-05-07 21:42:18 +000052 return self.c.co_argcount if self.c != None else 0
Enrico Granatac8b36f12013-05-07 19:49:59 +000053
54 def getFilename(self):
Enrico Granata78f05f12013-05-07 21:42:18 +000055 return self.c.co_filename if self.c != None else ""
Enrico Granatac8b36f12013-05-07 19:49:59 +000056
57 def getVariables(self):
Enrico Granata78f05f12013-05-07 21:42:18 +000058 return self.c.co_varnames if self.c != None else []
Enrico Granatac8b36f12013-05-07 19:49:59 +000059
60 def getName(self):
Enrico Granata78f05f12013-05-07 21:42:18 +000061 return self.c.co_name if self.c != None else ""
62
63 def getFileName(self):
64 return self.c.co_filename if self.c != None else ""
Enrico Granatac8b36f12013-05-07 19:49:59 +000065
66class ArgsFancy:
67 def __init__(self,frame,arginfo):
68 self.f = frame
69 self.a = arginfo
70
71 def __str__(self):
72 args, varargs, kwargs = self.getArgs(), self.getVarArgs(), self.getKWArgs()
73 ret = ""
74 count = 0
75 size = len(args)
76 for arg in args:
77 ret = ret + ("%s = %s" % (arg, args[arg]))
78 count = count + 1
79 if count < size:
80 ret = ret + ", "
81 if varargs:
82 if size > 0:
83 ret = ret + " "
84 ret = ret + "varargs are " + str(varargs)
85 if kwargs:
86 if size > 0:
87 ret = ret + " "
88 ret = ret + "kwargs are " + str(kwargs)
89 return ret
90
91 def getNumArgs(wantVarargs = False, wantKWArgs=False):
92 args, varargs, keywords, values = self.a
93 size = len(args)
94 if varargs and wantVarargs:
95 size = size+len(self.getVarArgs())
96 if keywords and wantKWArgs:
97 size = size+len(self.getKWArgs())
98 return size
99
100 def getArgs(self):
101 args, _, _, values = self.a
102 argWValues = OrderedDict()
103 for arg in args:
104 argWValues[arg] = values[arg]
105 return argWValues
106
107 def getVarArgs(self):
108 _, vargs, _, _ = self.a
109 if vargs:
110 return self.f.f_locals[vargs]
111 return ()
112
113 def getKWArgs(self):
114 _, _, kwargs, _ = self.a
115 if kwargs:
116 return self.f.f_locals[kwargs]
117 return {}
118
119class FrameFancy:
120 def __init__(self,frame):
121 self.f = frame
122
123 def getCaller(self):
124 return FrameFancy(self.f.f_back)
125
126 def getLineNumber(self):
Enrico Granata78f05f12013-05-07 21:42:18 +0000127 return self.f.f_lineno if self.f != None else 0
Enrico Granatac8b36f12013-05-07 19:49:59 +0000128
129 def getCodeInformation(self):
Enrico Granata78f05f12013-05-07 21:42:18 +0000130 return CodeFancy(self.f.f_code) if self.f != None else None
Enrico Granatac8b36f12013-05-07 19:49:59 +0000131
132 def getExceptionInfo(self):
Enrico Granata78f05f12013-05-07 21:42:18 +0000133 return ExceptionFancy(self.f) if self.f != None else None
Enrico Granatac8b36f12013-05-07 19:49:59 +0000134
135 def getName(self):
Enrico Granata78f05f12013-05-07 21:42:18 +0000136 return self.getCodeInformation().getName() if self.f != None else ""
137
138 def getFileName(self):
139 return self.getCodeInformation().getFileName() if self.f != None else ""
Enrico Granatac8b36f12013-05-07 19:49:59 +0000140
141 def getLocals(self):
Enrico Granata78f05f12013-05-07 21:42:18 +0000142 return self.f.f_locals if self.f != None else {}
Enrico Granatac8b36f12013-05-07 19:49:59 +0000143
144 def getArgumentInfo(self):
Enrico Granata78f05f12013-05-07 21:42:18 +0000145 return ArgsFancy(self.f,inspect.getargvalues(self.f)) if self.f != None else None
Enrico Granatac8b36f12013-05-07 19:49:59 +0000146
147class TracerClass:
148 def callEvent(self,frame):
149 pass
150
151 def lineEvent(self,frame):
152 pass
153
154 def returnEvent(self,frame,retval):
155 pass
156
157 def exceptionEvent(self,frame,exception,value,traceback):
158 pass
159
160 def cCallEvent(self,frame,cfunct):
161 pass
162
163 def cReturnEvent(self,frame,cfunct):
164 pass
165
166 def cExceptionEvent(self,frame,cfunct):
167 pass
168
169tracer_impl = TracerClass()
170
171
172def the_tracer_entrypoint(frame,event,args):
173 if tracer_impl == None:
174 return None
175 if event == "call":
176 call_retval = tracer_impl.callEvent(FrameFancy(frame))
177 if call_retval == False:
178 return None
179 return the_tracer_entrypoint
180 elif event == "line":
181 line_retval = tracer_impl.lineEvent(FrameFancy(frame))
182 if line_retval == False:
183 return None
184 return the_tracer_entrypoint
185 elif event == "return":
186 tracer_impl.returnEvent(FrameFancy(frame),args)
187 elif event == "exception":
188 exty,exva,extb = args
189 exception_retval = tracer_impl.exceptionEvent(FrameFancy(frame),ExceptionFancy(extb,exty,exva))
190 if exception_retval == False:
191 return None
192 return the_tracer_entrypoint
193 elif event == "c_call":
194 tracer_impl.cCallEvent(FrameFancy(frame),args)
195 elif event == "c_return":
196 tracer_impl.cReturnEvent(FrameFancy(frame),args)
197 elif event == "c_exception":
198 tracer_impl.cExceptionEvent(FrameFancy(frame),args)
199 return None
200
201def enable(t=None):
202 global tracer_impl
203 if t:
204 tracer_impl = t
205 sys.settrace(the_tracer_entrypoint)
206
207def disable():
208 sys.settrace(None)
209
210class LoggingTracer:
211 def callEvent(self,frame):
212 print "call " + frame.getName() + " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
213
214 def lineEvent(self,frame):
Enrico Granata78f05f12013-05-07 21:42:18 +0000215 print "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are " + str(frame.getLocals()) + " in " + frame.getFileName()
Enrico Granatac8b36f12013-05-07 19:49:59 +0000216
217 def returnEvent(self,frame,retval):
218 print "return from " + frame.getName() + " value is " + str(retval) + " locals are " + str(frame.getLocals())
219
220 def exceptionEvent(self,frame,exception):
221 print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())
222 print "tb: " + str(exception.getTraceback())
223
Enrico Granata78f05f12013-05-07 21:42:18 +0000224# the same functionality as LoggingTracer, but with a little more lldb-specific smarts
225class LLDBAwareTracer:
226 def callEvent(self,frame):
227 if frame.getName() == "<module>":
228 return
229 if frame.getName() == "run_one_line":
230 print "call run_one_line(%s)" % (frame.getArgumentInfo().getArgs()["input_string"])
231 return
232 if "Python.framework" in frame.getFileName():
233 print "call into Python at " + frame.getName()
234 return
235 if frame.getName() == "__init__" and frame.getCaller().getName() == "run_one_line" and frame.getCaller().getLineNumber() == 101:
236 return False
237 strout = "call " + frame.getName()
238 if (frame.getCaller().getFileName() == ""):
239 strout += " from LLDB - args are "
240 args = frame.getArgumentInfo().getArgs()
241 for arg in args:
242 if arg == "dict" or arg == "internal_dict":
243 continue
244 strout = strout + ("%s = %s " % (arg,args[arg]))
245 else:
246 strout += " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
247 print strout
248
249 def lineEvent(self,frame):
250 if frame.getName() == "<module>":
251 return
252 if frame.getName() == "run_one_line":
253 print "running run_one_line(%s) @ %s" % (frame.getArgumentInfo().getArgs()["input_string"],frame.getLineNumber())
254 return
255 if "Python.framework" in frame.getFileName():
256 print "running into Python at " + frame.getName() + " @ " + str(frame.getLineNumber())
257 return
258 strout = "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are "
259 if (frame.getCaller().getFileName() == ""):
260 locals = frame.getLocals()
261 for local in locals:
262 if local == "dict" or local == "internal_dict":
263 continue
264 strout = strout + ("%s = %s " % (local,locals[local]))
265 else:
266 strout = strout + str(frame.getLocals())
267 strout = strout + " in " + frame.getFileName()
268 print strout
269
270 def returnEvent(self,frame,retval):
271 if frame.getName() == "<module>":
272 return
273 if frame.getName() == "run_one_line":
274 print "return from run_one_line(%s) return value is %s" % (frame.getArgumentInfo().getArgs()["input_string"],retval)
275 return
276 if "Python.framework" in frame.getFileName():
277 print "return from Python at " + frame.getName() + " return value is " + str(retval)
278 return
279 strout = "return from " + frame.getName() + " return value is " + str(retval) + " locals are "
280 if (frame.getCaller().getFileName() == ""):
281 locals = frame.getLocals()
282 for local in locals:
283 if local == "dict" or local == "internal_dict":
284 continue
285 strout = strout + ("%s = %s " % (local,locals[local]))
286 else:
287 strout = strout + str(frame.getLocals())
288 strout = strout + " in " + frame.getFileName()
289 print strout
290
291 def exceptionEvent(self,frame,exception):
292 if frame.getName() == "<module>":
293 return
294 print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())
295 print "tb: " + str(exception.getTraceback())
296
Enrico Granatac8b36f12013-05-07 19:49:59 +0000297def f(x,y=None):
298 if x > 0:
299 return 2 + f(x-2)
300 return 35
301
302def g(x):
303 return 1.134 / x
304
305def print_keyword_args(**kwargs):
306 # kwargs is a dict of the keyword args passed to the function
307 for key, value in kwargs.iteritems():
308 print "%s = %s" % (key, value)
309
310def total(initial=5, *numbers, **keywords):
311 count = initial
312 for number in numbers:
313 count += number
314 for key in keywords:
315 count += keywords[key]
316 return count
317
318if __name__ == "__main__":
319 enable(LoggingTracer())
320 f(5)
321 f(5,1)
322 print_keyword_args(first_name="John", last_name="Doe")
323 total(10, 1, 2, 3, vegetables=50, fruits=100)
324 try:
325 g(0)
326 except:
327 pass
328 disable()