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