blob: a166f21e98392a6f8c06062c1c581e6545bce4c8 [file] [log] [blame]
Enrico Granatac8b36f12013-05-07 19:49:59 +00001import sys
2import inspect
3from collections import OrderedDict
4
Kate Stoneb9c1b512016-09-06 20:57:50 +00005
Enrico Granatac8b36f12013-05-07 19:49:59 +00006class TracebackFancy:
Enrico Granatac8b36f12013-05-07 19:49:59 +00007
Kate Stoneb9c1b512016-09-06 20:57:50 +00008 def __init__(self, traceback):
9 self.t = traceback
Enrico Granatac8b36f12013-05-07 19:49:59 +000010
Kate Stoneb9c1b512016-09-06 20:57:50 +000011 def getFrame(self):
12 return FrameFancy(self.t.tb_frame)
Enrico Granatac8b36f12013-05-07 19:49:59 +000013
Kate Stoneb9c1b512016-09-06 20:57:50 +000014 def getLineNumber(self):
15 return self.t.tb_lineno if self.t is not None else None
Enrico Granatac8b36f12013-05-07 19:49:59 +000016
Kate Stoneb9c1b512016-09-06 20:57:50 +000017 def getNext(self):
18 return TracebackFancy(self.t.tb_next)
19
20 def __str__(self):
21 if self.t is None:
22 return ""
23 str_self = "%s @ %s" % (
24 self.getFrame().getName(), self.getLineNumber())
25 return str_self + "\n" + self.getNext().__str__()
26
Enrico Granatac8b36f12013-05-07 19:49:59 +000027
28class ExceptionFancy:
Enrico Granatac8b36f12013-05-07 19:49:59 +000029
Kate Stoneb9c1b512016-09-06 20:57:50 +000030 def __init__(self, frame):
31 self.etraceback = frame.f_exc_traceback
32 self.etype = frame.exc_type
33 self.evalue = frame.f_exc_value
Enrico Granatac8b36f12013-05-07 19:49:59 +000034
Kate Stoneb9c1b512016-09-06 20:57:50 +000035 def __init__(self, tb, ty, va):
36 self.etraceback = tb
37 self.etype = ty
38 self.evalue = va
Enrico Granatac8b36f12013-05-07 19:49:59 +000039
Kate Stoneb9c1b512016-09-06 20:57:50 +000040 def getTraceback(self):
41 return TracebackFancy(self.etraceback)
Enrico Granatac8b36f12013-05-07 19:49:59 +000042
Kate Stoneb9c1b512016-09-06 20:57:50 +000043 def __nonzero__(self):
44 return self.etraceback is not None or self.etype is not None or self.evalue is not None
Enrico Granatac8b36f12013-05-07 19:49:59 +000045
Kate Stoneb9c1b512016-09-06 20:57:50 +000046 def getType(self):
47 return str(self.etype)
48
49 def getValue(self):
50 return self.evalue
51
Enrico Granatac8b36f12013-05-07 19:49:59 +000052
53class CodeFancy:
Enrico Granatac8b36f12013-05-07 19:49:59 +000054
Kate Stoneb9c1b512016-09-06 20:57:50 +000055 def __init__(self, code):
56 self.c = code
Enrico Granatac8b36f12013-05-07 19:49:59 +000057
Kate Stoneb9c1b512016-09-06 20:57:50 +000058 def getArgCount(self):
59 return self.c.co_argcount if self.c is not None else 0
Enrico Granatac8b36f12013-05-07 19:49:59 +000060
Kate Stoneb9c1b512016-09-06 20:57:50 +000061 def getFilename(self):
62 return self.c.co_filename if self.c is not None else ""
Enrico Granatac8b36f12013-05-07 19:49:59 +000063
Kate Stoneb9c1b512016-09-06 20:57:50 +000064 def getVariables(self):
65 return self.c.co_varnames if self.c is not None else []
Enrico Granata78f05f12013-05-07 21:42:18 +000066
Kate Stoneb9c1b512016-09-06 20:57:50 +000067 def getName(self):
68 return self.c.co_name if self.c is not None else ""
69
70 def getFileName(self):
71 return self.c.co_filename if self.c is not None else ""
72
Enrico Granatac8b36f12013-05-07 19:49:59 +000073
74class ArgsFancy:
Enrico Granatac8b36f12013-05-07 19:49:59 +000075
Kate Stoneb9c1b512016-09-06 20:57:50 +000076 def __init__(self, frame, arginfo):
77 self.f = frame
78 self.a = arginfo
Enrico Granatac8b36f12013-05-07 19:49:59 +000079
Kate Stoneb9c1b512016-09-06 20:57:50 +000080 def __str__(self):
81 args, varargs, kwargs = self.getArgs(), self.getVarArgs(), self.getKWArgs()
82 ret = ""
83 count = 0
84 size = len(args)
85 for arg in args:
86 ret = ret + ("%s = %s" % (arg, args[arg]))
87 count = count + 1
88 if count < size:
89 ret = ret + ", "
90 if varargs:
91 if size > 0:
92 ret = ret + " "
93 ret = ret + "varargs are " + str(varargs)
94 if kwargs:
95 if size > 0:
96 ret = ret + " "
97 ret = ret + "kwargs are " + str(kwargs)
98 return ret
Enrico Granatac8b36f12013-05-07 19:49:59 +000099
Kate Stoneb9c1b512016-09-06 20:57:50 +0000100 def getNumArgs(wantVarargs=False, wantKWArgs=False):
101 args, varargs, keywords, values = self.a
102 size = len(args)
103 if varargs and wantVarargs:
104 size = size + len(self.getVarArgs())
105 if keywords and wantKWArgs:
106 size = size + len(self.getKWArgs())
107 return size
Enrico Granatac8b36f12013-05-07 19:49:59 +0000108
Kate Stoneb9c1b512016-09-06 20:57:50 +0000109 def getArgs(self):
110 args, _, _, values = self.a
111 argWValues = OrderedDict()
112 for arg in args:
113 argWValues[arg] = values[arg]
114 return argWValues
Enrico Granatac8b36f12013-05-07 19:49:59 +0000115
Kate Stoneb9c1b512016-09-06 20:57:50 +0000116 def getVarArgs(self):
117 _, vargs, _, _ = self.a
118 if vargs:
119 return self.f.f_locals[vargs]
120 return ()
121
122 def getKWArgs(self):
123 _, _, kwargs, _ = self.a
124 if kwargs:
125 return self.f.f_locals[kwargs]
126 return {}
127
Enrico Granatac8b36f12013-05-07 19:49:59 +0000128
129class FrameFancy:
Enrico Granatac8b36f12013-05-07 19:49:59 +0000130
Kate Stoneb9c1b512016-09-06 20:57:50 +0000131 def __init__(self, frame):
132 self.f = frame
Enrico Granatac8b36f12013-05-07 19:49:59 +0000133
Kate Stoneb9c1b512016-09-06 20:57:50 +0000134 def getCaller(self):
135 return FrameFancy(self.f.f_back)
Enrico Granatac8b36f12013-05-07 19:49:59 +0000136
Kate Stoneb9c1b512016-09-06 20:57:50 +0000137 def getLineNumber(self):
138 return self.f.f_lineno if self.f is not None else 0
Enrico Granatac8b36f12013-05-07 19:49:59 +0000139
Kate Stoneb9c1b512016-09-06 20:57:50 +0000140 def getCodeInformation(self):
141 return CodeFancy(self.f.f_code) if self.f is not None else None
Enrico Granatac8b36f12013-05-07 19:49:59 +0000142
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 def getExceptionInfo(self):
144 return ExceptionFancy(self.f) if self.f is not None else None
Enrico Granata78f05f12013-05-07 21:42:18 +0000145
Kate Stoneb9c1b512016-09-06 20:57:50 +0000146 def getName(self):
147 return self.getCodeInformation().getName() if self.f is not None else ""
Enrico Granatac8b36f12013-05-07 19:49:59 +0000148
Kate Stoneb9c1b512016-09-06 20:57:50 +0000149 def getFileName(self):
150 return self.getCodeInformation().getFileName() if self.f is not None else ""
151
152 def getLocals(self):
153 return self.f.f_locals if self.f is not None else {}
154
155 def getArgumentInfo(self):
156 return ArgsFancy(
157 self.f, inspect.getargvalues(
158 self.f)) if self.f is not None else None
159
Enrico Granatac8b36f12013-05-07 19:49:59 +0000160
161class TracerClass:
Enrico Granatac8b36f12013-05-07 19:49:59 +0000162
Kate Stoneb9c1b512016-09-06 20:57:50 +0000163 def callEvent(self, frame):
164 pass
Enrico Granatac8b36f12013-05-07 19:49:59 +0000165
Kate Stoneb9c1b512016-09-06 20:57:50 +0000166 def lineEvent(self, frame):
167 pass
Enrico Granatac8b36f12013-05-07 19:49:59 +0000168
Kate Stoneb9c1b512016-09-06 20:57:50 +0000169 def returnEvent(self, frame, retval):
170 pass
Enrico Granatac8b36f12013-05-07 19:49:59 +0000171
Kate Stoneb9c1b512016-09-06 20:57:50 +0000172 def exceptionEvent(self, frame, exception, value, traceback):
173 pass
Enrico Granatac8b36f12013-05-07 19:49:59 +0000174
Kate Stoneb9c1b512016-09-06 20:57:50 +0000175 def cCallEvent(self, frame, cfunct):
176 pass
Enrico Granatac8b36f12013-05-07 19:49:59 +0000177
Kate Stoneb9c1b512016-09-06 20:57:50 +0000178 def cReturnEvent(self, frame, cfunct):
179 pass
180
181 def cExceptionEvent(self, frame, cfunct):
182 pass
Enrico Granatac8b36f12013-05-07 19:49:59 +0000183
184tracer_impl = TracerClass()
185
186
Kate Stoneb9c1b512016-09-06 20:57:50 +0000187def the_tracer_entrypoint(frame, event, args):
188 if tracer_impl is None:
189 return None
190 if event == "call":
191 call_retval = tracer_impl.callEvent(FrameFancy(frame))
192 if not call_retval:
193 return None
194 return the_tracer_entrypoint
195 elif event == "line":
196 line_retval = tracer_impl.lineEvent(FrameFancy(frame))
197 if not line_retval:
198 return None
199 return the_tracer_entrypoint
200 elif event == "return":
201 tracer_impl.returnEvent(FrameFancy(frame), args)
202 elif event == "exception":
203 exty, exva, extb = args
204 exception_retval = tracer_impl.exceptionEvent(
205 FrameFancy(frame), ExceptionFancy(extb, exty, exva))
206 if not exception_retval:
207 return None
208 return the_tracer_entrypoint
209 elif event == "c_call":
210 tracer_impl.cCallEvent(FrameFancy(frame), args)
211 elif event == "c_return":
212 tracer_impl.cReturnEvent(FrameFancy(frame), args)
213 elif event == "c_exception":
214 tracer_impl.cExceptionEvent(FrameFancy(frame), args)
215 return None
216
Enrico Granatac8b36f12013-05-07 19:49:59 +0000217
218def enable(t=None):
Kate Stoneb9c1b512016-09-06 20:57:50 +0000219 global tracer_impl
220 if t:
221 tracer_impl = t
222 sys.settrace(the_tracer_entrypoint)
223
Enrico Granatac8b36f12013-05-07 19:49:59 +0000224
225def disable():
Kate Stoneb9c1b512016-09-06 20:57:50 +0000226 sys.settrace(None)
227
Enrico Granatac8b36f12013-05-07 19:49:59 +0000228
229class LoggingTracer:
Enrico Granatac8b36f12013-05-07 19:49:59 +0000230
Kate Stoneb9c1b512016-09-06 20:57:50 +0000231 def callEvent(self, frame):
232 print "call " + frame.getName() + " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
Enrico Granatac8b36f12013-05-07 19:49:59 +0000233
Kate Stoneb9c1b512016-09-06 20:57:50 +0000234 def lineEvent(self, frame):
235 print "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are " + str(frame.getLocals()) + " in " + frame.getFileName()
Enrico Granatac8b36f12013-05-07 19:49:59 +0000236
Kate Stoneb9c1b512016-09-06 20:57:50 +0000237 def returnEvent(self, frame, retval):
238 print "return from " + frame.getName() + " value is " + str(retval) + " locals are " + str(frame.getLocals())
Enrico Granatac8b36f12013-05-07 19:49:59 +0000239
Kate Stoneb9c1b512016-09-06 20:57:50 +0000240 def exceptionEvent(self, frame, exception):
241 print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())
242 print "tb: " + str(exception.getTraceback())
243
244# the same functionality as LoggingTracer, but with a little more
245# lldb-specific smarts
246
247
Enrico Granata78f05f12013-05-07 21:42:18 +0000248class LLDBAwareTracer:
Enrico Granata78f05f12013-05-07 21:42:18 +0000249
Kate Stoneb9c1b512016-09-06 20:57:50 +0000250 def callEvent(self, frame):
251 if frame.getName() == "<module>":
252 return
253 if frame.getName() == "run_one_line":
254 print "call run_one_line(%s)" % (frame.getArgumentInfo().getArgs()["input_string"])
255 return
256 if "Python.framework" in frame.getFileName():
257 print "call into Python at " + frame.getName()
258 return
259 if frame.getName() == "__init__" and frame.getCaller().getName(
260 ) == "run_one_line" and frame.getCaller().getLineNumber() == 101:
261 return False
262 strout = "call " + frame.getName()
263 if (frame.getCaller().getFileName() == ""):
264 strout += " from LLDB - args are "
265 args = frame.getArgumentInfo().getArgs()
266 for arg in args:
267 if arg == "dict" or arg == "internal_dict":
268 continue
269 strout = strout + ("%s = %s " % (arg, args[arg]))
270 else:
271 strout += " from " + frame.getCaller().getName() + " @ " + \
272 str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
273 print strout
Enrico Granata78f05f12013-05-07 21:42:18 +0000274
Kate Stoneb9c1b512016-09-06 20:57:50 +0000275 def lineEvent(self, frame):
276 if frame.getName() == "<module>":
277 return
278 if frame.getName() == "run_one_line":
279 print "running run_one_line(%s) @ %s" % (frame.getArgumentInfo().getArgs()["input_string"], frame.getLineNumber())
280 return
281 if "Python.framework" in frame.getFileName():
282 print "running into Python at " + frame.getName() + " @ " + str(frame.getLineNumber())
283 return
284 strout = "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + \
285 " locals are "
286 if (frame.getCaller().getFileName() == ""):
287 locals = frame.getLocals()
288 for local in locals:
289 if local == "dict" or local == "internal_dict":
290 continue
291 strout = strout + ("%s = %s " % (local, locals[local]))
292 else:
293 strout = strout + str(frame.getLocals())
294 strout = strout + " in " + frame.getFileName()
295 print strout
Enrico Granata78f05f12013-05-07 21:42:18 +0000296
Kate Stoneb9c1b512016-09-06 20:57:50 +0000297 def returnEvent(self, frame, retval):
298 if frame.getName() == "<module>":
299 return
300 if frame.getName() == "run_one_line":
301 print "return from run_one_line(%s) return value is %s" % (frame.getArgumentInfo().getArgs()["input_string"], retval)
302 return
303 if "Python.framework" in frame.getFileName():
304 print "return from Python at " + frame.getName() + " return value is " + str(retval)
305 return
306 strout = "return from " + frame.getName() + " return value is " + \
307 str(retval) + " locals are "
308 if (frame.getCaller().getFileName() == ""):
309 locals = frame.getLocals()
310 for local in locals:
311 if local == "dict" or local == "internal_dict":
312 continue
313 strout = strout + ("%s = %s " % (local, locals[local]))
314 else:
315 strout = strout + str(frame.getLocals())
316 strout = strout + " in " + frame.getFileName()
317 print strout
Enrico Granata78f05f12013-05-07 21:42:18 +0000318
Kate Stoneb9c1b512016-09-06 20:57:50 +0000319 def exceptionEvent(self, frame, exception):
320 if frame.getName() == "<module>":
321 return
322 print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())
323 print "tb: " + str(exception.getTraceback())
324
325
326def f(x, y=None):
327 if x > 0:
328 return 2 + f(x - 2)
329 return 35
330
Enrico Granatac8b36f12013-05-07 19:49:59 +0000331
332def g(x):
Kate Stoneb9c1b512016-09-06 20:57:50 +0000333 return 1.134 / x
334
Enrico Granatac8b36f12013-05-07 19:49:59 +0000335
336def print_keyword_args(**kwargs):
Kate Stoneb9c1b512016-09-06 20:57:50 +0000337 # kwargs is a dict of the keyword args passed to the function
338 for key, value in kwargs.iteritems():
339 print "%s = %s" % (key, value)
340
Enrico Granatac8b36f12013-05-07 19:49:59 +0000341
342def total(initial=5, *numbers, **keywords):
343 count = initial
344 for number in numbers:
345 count += number
346 for key in keywords:
347 count += keywords[key]
348 return count
349
350if __name__ == "__main__":
Kate Stoneb9c1b512016-09-06 20:57:50 +0000351 enable(LoggingTracer())
352 f(5)
353 f(5, 1)
354 print_keyword_args(first_name="John", last_name="Doe")
355 total(10, 1, 2, 3, vegetables=50, fruits=100)
356 try:
357 g(0)
358 except:
359 pass
360 disable()