1*525cd59fSSerge Gueltonfrom __future__ import print_function 2c8b36f16SEnrico Granataimport sys 3c8b36f16SEnrico Granataimport inspect 4c8b36f16SEnrico Granatafrom collections import OrderedDict 5c8b36f16SEnrico Granata 6b9c1b51eSKate Stone 7c8b36f16SEnrico Granataclass TracebackFancy: 8b9c1b51eSKate Stone 9c8b36f16SEnrico Granata def __init__(self, traceback): 10c8b36f16SEnrico Granata self.t = traceback 11c8b36f16SEnrico Granata 12c8b36f16SEnrico Granata def getFrame(self): 13c8b36f16SEnrico Granata return FrameFancy(self.t.tb_frame) 14c8b36f16SEnrico Granata 15c8b36f16SEnrico Granata def getLineNumber(self): 16b9c1b51eSKate Stone return self.t.tb_lineno if self.t is not None else None 17c8b36f16SEnrico Granata 18c8b36f16SEnrico Granata def getNext(self): 19c8b36f16SEnrico Granata return TracebackFancy(self.t.tb_next) 20c8b36f16SEnrico Granata 21c8b36f16SEnrico Granata def __str__(self): 22b9c1b51eSKate Stone if self.t is None: 23c8b36f16SEnrico Granata return "" 24b9c1b51eSKate Stone str_self = "%s @ %s" % ( 25b9c1b51eSKate Stone self.getFrame().getName(), self.getLineNumber()) 26c8b36f16SEnrico Granata return str_self + "\n" + self.getNext().__str__() 27c8b36f16SEnrico Granata 28b9c1b51eSKate Stone 29c8b36f16SEnrico Granataclass ExceptionFancy: 30b9c1b51eSKate Stone 31c8b36f16SEnrico Granata def __init__(self, frame): 32c8b36f16SEnrico Granata self.etraceback = frame.f_exc_traceback 33c8b36f16SEnrico Granata self.etype = frame.exc_type 34c8b36f16SEnrico Granata self.evalue = frame.f_exc_value 35c8b36f16SEnrico Granata 36c8b36f16SEnrico Granata def __init__(self, tb, ty, va): 37c8b36f16SEnrico Granata self.etraceback = tb 38c8b36f16SEnrico Granata self.etype = ty 39c8b36f16SEnrico Granata self.evalue = va 40c8b36f16SEnrico Granata 41c8b36f16SEnrico Granata def getTraceback(self): 42c8b36f16SEnrico Granata return TracebackFancy(self.etraceback) 43c8b36f16SEnrico Granata 44c8b36f16SEnrico Granata def __nonzero__(self): 45b9c1b51eSKate Stone return self.etraceback is not None or self.etype is not None or self.evalue is not None 46c8b36f16SEnrico Granata 47c8b36f16SEnrico Granata def getType(self): 48c8b36f16SEnrico Granata return str(self.etype) 49c8b36f16SEnrico Granata 50c8b36f16SEnrico Granata def getValue(self): 51c8b36f16SEnrico Granata return self.evalue 52c8b36f16SEnrico Granata 53b9c1b51eSKate Stone 54c8b36f16SEnrico Granataclass CodeFancy: 55b9c1b51eSKate Stone 56c8b36f16SEnrico Granata def __init__(self, code): 57c8b36f16SEnrico Granata self.c = code 58c8b36f16SEnrico Granata 59c8b36f16SEnrico Granata def getArgCount(self): 60b9c1b51eSKate Stone return self.c.co_argcount if self.c is not None else 0 61c8b36f16SEnrico Granata 62c8b36f16SEnrico Granata def getFilename(self): 63b9c1b51eSKate Stone return self.c.co_filename if self.c is not None else "" 64c8b36f16SEnrico Granata 65c8b36f16SEnrico Granata def getVariables(self): 66b9c1b51eSKate Stone return self.c.co_varnames if self.c is not None else [] 67c8b36f16SEnrico Granata 68c8b36f16SEnrico Granata def getName(self): 69b9c1b51eSKate Stone return self.c.co_name if self.c is not None else "" 7078f05f13SEnrico Granata 7178f05f13SEnrico Granata def getFileName(self): 72b9c1b51eSKate Stone return self.c.co_filename if self.c is not None else "" 73b9c1b51eSKate Stone 74c8b36f16SEnrico Granata 75c8b36f16SEnrico Granataclass ArgsFancy: 76b9c1b51eSKate Stone 77c8b36f16SEnrico Granata def __init__(self, frame, arginfo): 78c8b36f16SEnrico Granata self.f = frame 79c8b36f16SEnrico Granata self.a = arginfo 80c8b36f16SEnrico Granata 81c8b36f16SEnrico Granata def __str__(self): 82c8b36f16SEnrico Granata args, varargs, kwargs = self.getArgs(), self.getVarArgs(), self.getKWArgs() 83c8b36f16SEnrico Granata ret = "" 84c8b36f16SEnrico Granata count = 0 85c8b36f16SEnrico Granata size = len(args) 86c8b36f16SEnrico Granata for arg in args: 87c8b36f16SEnrico Granata ret = ret + ("%s = %s" % (arg, args[arg])) 88c8b36f16SEnrico Granata count = count + 1 89c8b36f16SEnrico Granata if count < size: 90c8b36f16SEnrico Granata ret = ret + ", " 91c8b36f16SEnrico Granata if varargs: 92c8b36f16SEnrico Granata if size > 0: 93c8b36f16SEnrico Granata ret = ret + " " 94c8b36f16SEnrico Granata ret = ret + "varargs are " + str(varargs) 95c8b36f16SEnrico Granata if kwargs: 96c8b36f16SEnrico Granata if size > 0: 97c8b36f16SEnrico Granata ret = ret + " " 98c8b36f16SEnrico Granata ret = ret + "kwargs are " + str(kwargs) 99c8b36f16SEnrico Granata return ret 100c8b36f16SEnrico Granata 101c8b36f16SEnrico Granata def getNumArgs(wantVarargs=False, wantKWArgs=False): 102c8b36f16SEnrico Granata args, varargs, keywords, values = self.a 103c8b36f16SEnrico Granata size = len(args) 104c8b36f16SEnrico Granata if varargs and wantVarargs: 105c8b36f16SEnrico Granata size = size + len(self.getVarArgs()) 106c8b36f16SEnrico Granata if keywords and wantKWArgs: 107c8b36f16SEnrico Granata size = size + len(self.getKWArgs()) 108c8b36f16SEnrico Granata return size 109c8b36f16SEnrico Granata 110c8b36f16SEnrico Granata def getArgs(self): 111c8b36f16SEnrico Granata args, _, _, values = self.a 112c8b36f16SEnrico Granata argWValues = OrderedDict() 113c8b36f16SEnrico Granata for arg in args: 114c8b36f16SEnrico Granata argWValues[arg] = values[arg] 115c8b36f16SEnrico Granata return argWValues 116c8b36f16SEnrico Granata 117c8b36f16SEnrico Granata def getVarArgs(self): 118c8b36f16SEnrico Granata _, vargs, _, _ = self.a 119c8b36f16SEnrico Granata if vargs: 120c8b36f16SEnrico Granata return self.f.f_locals[vargs] 121c8b36f16SEnrico Granata return () 122c8b36f16SEnrico Granata 123c8b36f16SEnrico Granata def getKWArgs(self): 124c8b36f16SEnrico Granata _, _, kwargs, _ = self.a 125c8b36f16SEnrico Granata if kwargs: 126c8b36f16SEnrico Granata return self.f.f_locals[kwargs] 127c8b36f16SEnrico Granata return {} 128c8b36f16SEnrico Granata 129b9c1b51eSKate Stone 130c8b36f16SEnrico Granataclass FrameFancy: 131b9c1b51eSKate Stone 132c8b36f16SEnrico Granata def __init__(self, frame): 133c8b36f16SEnrico Granata self.f = frame 134c8b36f16SEnrico Granata 135c8b36f16SEnrico Granata def getCaller(self): 136c8b36f16SEnrico Granata return FrameFancy(self.f.f_back) 137c8b36f16SEnrico Granata 138c8b36f16SEnrico Granata def getLineNumber(self): 139b9c1b51eSKate Stone return self.f.f_lineno if self.f is not None else 0 140c8b36f16SEnrico Granata 141c8b36f16SEnrico Granata def getCodeInformation(self): 142b9c1b51eSKate Stone return CodeFancy(self.f.f_code) if self.f is not None else None 143c8b36f16SEnrico Granata 144c8b36f16SEnrico Granata def getExceptionInfo(self): 145b9c1b51eSKate Stone return ExceptionFancy(self.f) if self.f is not None else None 146c8b36f16SEnrico Granata 147c8b36f16SEnrico Granata def getName(self): 148b9c1b51eSKate Stone return self.getCodeInformation().getName() if self.f is not None else "" 14978f05f13SEnrico Granata 15078f05f13SEnrico Granata def getFileName(self): 151b9c1b51eSKate Stone return self.getCodeInformation().getFileName() if self.f is not None else "" 152c8b36f16SEnrico Granata 153c8b36f16SEnrico Granata def getLocals(self): 154b9c1b51eSKate Stone return self.f.f_locals if self.f is not None else {} 155c8b36f16SEnrico Granata 156c8b36f16SEnrico Granata def getArgumentInfo(self): 157b9c1b51eSKate Stone return ArgsFancy( 158b9c1b51eSKate Stone self.f, inspect.getargvalues( 159b9c1b51eSKate Stone self.f)) if self.f is not None else None 160b9c1b51eSKate Stone 161c8b36f16SEnrico Granata 162c8b36f16SEnrico Granataclass TracerClass: 163b9c1b51eSKate Stone 164c8b36f16SEnrico Granata def callEvent(self, frame): 165c8b36f16SEnrico Granata pass 166c8b36f16SEnrico Granata 167c8b36f16SEnrico Granata def lineEvent(self, frame): 168c8b36f16SEnrico Granata pass 169c8b36f16SEnrico Granata 170c8b36f16SEnrico Granata def returnEvent(self, frame, retval): 171c8b36f16SEnrico Granata pass 172c8b36f16SEnrico Granata 173c8b36f16SEnrico Granata def exceptionEvent(self, frame, exception, value, traceback): 174c8b36f16SEnrico Granata pass 175c8b36f16SEnrico Granata 176c8b36f16SEnrico Granata def cCallEvent(self, frame, cfunct): 177c8b36f16SEnrico Granata pass 178c8b36f16SEnrico Granata 179c8b36f16SEnrico Granata def cReturnEvent(self, frame, cfunct): 180c8b36f16SEnrico Granata pass 181c8b36f16SEnrico Granata 182c8b36f16SEnrico Granata def cExceptionEvent(self, frame, cfunct): 183c8b36f16SEnrico Granata pass 184c8b36f16SEnrico Granata 185c8b36f16SEnrico Granatatracer_impl = TracerClass() 186c8b36f16SEnrico Granata 187c8b36f16SEnrico Granata 188c8b36f16SEnrico Granatadef the_tracer_entrypoint(frame, event, args): 189b9c1b51eSKate Stone if tracer_impl is None: 190c8b36f16SEnrico Granata return None 191c8b36f16SEnrico Granata if event == "call": 192c8b36f16SEnrico Granata call_retval = tracer_impl.callEvent(FrameFancy(frame)) 193b9c1b51eSKate Stone if not call_retval: 194c8b36f16SEnrico Granata return None 195c8b36f16SEnrico Granata return the_tracer_entrypoint 196c8b36f16SEnrico Granata elif event == "line": 197c8b36f16SEnrico Granata line_retval = tracer_impl.lineEvent(FrameFancy(frame)) 198b9c1b51eSKate Stone if not line_retval: 199c8b36f16SEnrico Granata return None 200c8b36f16SEnrico Granata return the_tracer_entrypoint 201c8b36f16SEnrico Granata elif event == "return": 202c8b36f16SEnrico Granata tracer_impl.returnEvent(FrameFancy(frame), args) 203c8b36f16SEnrico Granata elif event == "exception": 204c8b36f16SEnrico Granata exty, exva, extb = args 205b9c1b51eSKate Stone exception_retval = tracer_impl.exceptionEvent( 206b9c1b51eSKate Stone FrameFancy(frame), ExceptionFancy(extb, exty, exva)) 207b9c1b51eSKate Stone if not exception_retval: 208c8b36f16SEnrico Granata return None 209c8b36f16SEnrico Granata return the_tracer_entrypoint 210c8b36f16SEnrico Granata elif event == "c_call": 211c8b36f16SEnrico Granata tracer_impl.cCallEvent(FrameFancy(frame), args) 212c8b36f16SEnrico Granata elif event == "c_return": 213c8b36f16SEnrico Granata tracer_impl.cReturnEvent(FrameFancy(frame), args) 214c8b36f16SEnrico Granata elif event == "c_exception": 215c8b36f16SEnrico Granata tracer_impl.cExceptionEvent(FrameFancy(frame), args) 216c8b36f16SEnrico Granata return None 217c8b36f16SEnrico Granata 218b9c1b51eSKate Stone 219c8b36f16SEnrico Granatadef enable(t=None): 220c8b36f16SEnrico Granata global tracer_impl 221c8b36f16SEnrico Granata if t: 222c8b36f16SEnrico Granata tracer_impl = t 223c8b36f16SEnrico Granata sys.settrace(the_tracer_entrypoint) 224c8b36f16SEnrico Granata 225b9c1b51eSKate Stone 226c8b36f16SEnrico Granatadef disable(): 227c8b36f16SEnrico Granata sys.settrace(None) 228c8b36f16SEnrico Granata 229b9c1b51eSKate Stone 230c8b36f16SEnrico Granataclass LoggingTracer: 231b9c1b51eSKate Stone 232c8b36f16SEnrico Granata def callEvent(self, frame): 233*525cd59fSSerge Guelton print("call " + frame.getName() + " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())) 234c8b36f16SEnrico Granata 235c8b36f16SEnrico Granata def lineEvent(self, frame): 236*525cd59fSSerge Guelton print("running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are " + str(frame.getLocals()) + " in " + frame.getFileName()) 237c8b36f16SEnrico Granata 238c8b36f16SEnrico Granata def returnEvent(self, frame, retval): 239*525cd59fSSerge Guelton print("return from " + frame.getName() + " value is " + str(retval) + " locals are " + str(frame.getLocals())) 240c8b36f16SEnrico Granata 241c8b36f16SEnrico Granata def exceptionEvent(self, frame, exception): 242*525cd59fSSerge Guelton print("exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())) 243*525cd59fSSerge Guelton print("tb: " + str(exception.getTraceback())) 244c8b36f16SEnrico Granata 245b9c1b51eSKate Stone# the same functionality as LoggingTracer, but with a little more 246b9c1b51eSKate Stone# lldb-specific smarts 247b9c1b51eSKate Stone 248b9c1b51eSKate Stone 24978f05f13SEnrico Granataclass LLDBAwareTracer: 250b9c1b51eSKate Stone 25178f05f13SEnrico Granata def callEvent(self, frame): 25278f05f13SEnrico Granata if frame.getName() == "<module>": 25378f05f13SEnrico Granata return 25478f05f13SEnrico Granata if frame.getName() == "run_one_line": 255*525cd59fSSerge Guelton print("call run_one_line(%s)" % (frame.getArgumentInfo().getArgs()["input_string"])) 25678f05f13SEnrico Granata return 25778f05f13SEnrico Granata if "Python.framework" in frame.getFileName(): 258*525cd59fSSerge Guelton print("call into Python at " + frame.getName()) 25978f05f13SEnrico Granata return 260b9c1b51eSKate Stone if frame.getName() == "__init__" and frame.getCaller().getName( 261b9c1b51eSKate Stone ) == "run_one_line" and frame.getCaller().getLineNumber() == 101: 26278f05f13SEnrico Granata return False 26378f05f13SEnrico Granata strout = "call " + frame.getName() 26478f05f13SEnrico Granata if (frame.getCaller().getFileName() == ""): 26578f05f13SEnrico Granata strout += " from LLDB - args are " 26678f05f13SEnrico Granata args = frame.getArgumentInfo().getArgs() 26778f05f13SEnrico Granata for arg in args: 26878f05f13SEnrico Granata if arg == "dict" or arg == "internal_dict": 26978f05f13SEnrico Granata continue 27078f05f13SEnrico Granata strout = strout + ("%s = %s " % (arg, args[arg])) 27178f05f13SEnrico Granata else: 272b9c1b51eSKate Stone strout += " from " + frame.getCaller().getName() + " @ " + \ 273b9c1b51eSKate Stone str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo()) 274*525cd59fSSerge Guelton print(strout) 27578f05f13SEnrico Granata 27678f05f13SEnrico Granata def lineEvent(self, frame): 27778f05f13SEnrico Granata if frame.getName() == "<module>": 27878f05f13SEnrico Granata return 27978f05f13SEnrico Granata if frame.getName() == "run_one_line": 280*525cd59fSSerge Guelton print("running run_one_line(%s) @ %s" % (frame.getArgumentInfo().getArgs()["input_string"], frame.getLineNumber())) 28178f05f13SEnrico Granata return 28278f05f13SEnrico Granata if "Python.framework" in frame.getFileName(): 283*525cd59fSSerge Guelton print("running into Python at " + frame.getName() + " @ " + str(frame.getLineNumber())) 28478f05f13SEnrico Granata return 285b9c1b51eSKate Stone strout = "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + \ 286b9c1b51eSKate Stone " locals are " 28778f05f13SEnrico Granata if (frame.getCaller().getFileName() == ""): 28878f05f13SEnrico Granata locals = frame.getLocals() 28978f05f13SEnrico Granata for local in locals: 29078f05f13SEnrico Granata if local == "dict" or local == "internal_dict": 29178f05f13SEnrico Granata continue 29278f05f13SEnrico Granata strout = strout + ("%s = %s " % (local, locals[local])) 29378f05f13SEnrico Granata else: 29478f05f13SEnrico Granata strout = strout + str(frame.getLocals()) 29578f05f13SEnrico Granata strout = strout + " in " + frame.getFileName() 296*525cd59fSSerge Guelton print(strout) 29778f05f13SEnrico Granata 29878f05f13SEnrico Granata def returnEvent(self, frame, retval): 29978f05f13SEnrico Granata if frame.getName() == "<module>": 30078f05f13SEnrico Granata return 30178f05f13SEnrico Granata if frame.getName() == "run_one_line": 302*525cd59fSSerge Guelton print("return from run_one_line(%s) return value is %s" % (frame.getArgumentInfo().getArgs()["input_string"], retval)) 30378f05f13SEnrico Granata return 30478f05f13SEnrico Granata if "Python.framework" in frame.getFileName(): 305*525cd59fSSerge Guelton print("return from Python at " + frame.getName() + " return value is " + str(retval)) 30678f05f13SEnrico Granata return 307b9c1b51eSKate Stone strout = "return from " + frame.getName() + " return value is " + \ 308b9c1b51eSKate Stone str(retval) + " locals are " 30978f05f13SEnrico Granata if (frame.getCaller().getFileName() == ""): 31078f05f13SEnrico Granata locals = frame.getLocals() 31178f05f13SEnrico Granata for local in locals: 31278f05f13SEnrico Granata if local == "dict" or local == "internal_dict": 31378f05f13SEnrico Granata continue 31478f05f13SEnrico Granata strout = strout + ("%s = %s " % (local, locals[local])) 31578f05f13SEnrico Granata else: 31678f05f13SEnrico Granata strout = strout + str(frame.getLocals()) 31778f05f13SEnrico Granata strout = strout + " in " + frame.getFileName() 318*525cd59fSSerge Guelton print(strout) 31978f05f13SEnrico Granata 32078f05f13SEnrico Granata def exceptionEvent(self, frame, exception): 32178f05f13SEnrico Granata if frame.getName() == "<module>": 32278f05f13SEnrico Granata return 323*525cd59fSSerge Guelton print("exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())) 324*525cd59fSSerge Guelton print("tb: " + str(exception.getTraceback())) 32578f05f13SEnrico Granata 326b9c1b51eSKate Stone 327c8b36f16SEnrico Granatadef f(x, y=None): 328c8b36f16SEnrico Granata if x > 0: 329c8b36f16SEnrico Granata return 2 + f(x - 2) 330c8b36f16SEnrico Granata return 35 331c8b36f16SEnrico Granata 332b9c1b51eSKate Stone 333c8b36f16SEnrico Granatadef g(x): 334c8b36f16SEnrico Granata return 1.134 / x 335c8b36f16SEnrico Granata 336b9c1b51eSKate Stone 337c8b36f16SEnrico Granatadef print_keyword_args(**kwargs): 338c8b36f16SEnrico Granata # kwargs is a dict of the keyword args passed to the function 339ce54fa18SSerge Guelton for key, value in kwargs.items(): 340*525cd59fSSerge Guelton print("%s = %s" % (key, value)) 341c8b36f16SEnrico Granata 342b9c1b51eSKate Stone 343c8b36f16SEnrico Granatadef total(initial=5, *numbers, **keywords): 344c8b36f16SEnrico Granata count = initial 345c8b36f16SEnrico Granata for number in numbers: 346c8b36f16SEnrico Granata count += number 347c8b36f16SEnrico Granata for key in keywords: 348c8b36f16SEnrico Granata count += keywords[key] 349c8b36f16SEnrico Granata return count 350c8b36f16SEnrico Granata 351c8b36f16SEnrico Granataif __name__ == "__main__": 352c8b36f16SEnrico Granata enable(LoggingTracer()) 353c8b36f16SEnrico Granata f(5) 354c8b36f16SEnrico Granata f(5, 1) 355c8b36f16SEnrico Granata print_keyword_args(first_name="John", last_name="Doe") 356c8b36f16SEnrico Granata total(10, 1, 2, 3, vegetables=50, fruits=100) 357c8b36f16SEnrico Granata try: 358c8b36f16SEnrico Granata g(0) 359c8b36f16SEnrico Granata except: 360c8b36f16SEnrico Granata pass 361c8b36f16SEnrico Granata disable() 362