forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			361 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			361 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
import sys
 | 
						|
import inspect
 | 
						|
from collections import OrderedDict
 | 
						|
 | 
						|
 | 
						|
class TracebackFancy:
 | 
						|
 | 
						|
    def __init__(self, traceback):
 | 
						|
        self.t = traceback
 | 
						|
 | 
						|
    def getFrame(self):
 | 
						|
        return FrameFancy(self.t.tb_frame)
 | 
						|
 | 
						|
    def getLineNumber(self):
 | 
						|
        return self.t.tb_lineno if self.t is not None else None
 | 
						|
 | 
						|
    def getNext(self):
 | 
						|
        return TracebackFancy(self.t.tb_next)
 | 
						|
 | 
						|
    def __str__(self):
 | 
						|
        if self.t is None:
 | 
						|
            return ""
 | 
						|
        str_self = "%s @ %s" % (
 | 
						|
            self.getFrame().getName(), self.getLineNumber())
 | 
						|
        return str_self + "\n" + self.getNext().__str__()
 | 
						|
 | 
						|
 | 
						|
class ExceptionFancy:
 | 
						|
 | 
						|
    def __init__(self, frame):
 | 
						|
        self.etraceback = frame.f_exc_traceback
 | 
						|
        self.etype = frame.exc_type
 | 
						|
        self.evalue = frame.f_exc_value
 | 
						|
 | 
						|
    def __init__(self, tb, ty, va):
 | 
						|
        self.etraceback = tb
 | 
						|
        self.etype = ty
 | 
						|
        self.evalue = va
 | 
						|
 | 
						|
    def getTraceback(self):
 | 
						|
        return TracebackFancy(self.etraceback)
 | 
						|
 | 
						|
    def __nonzero__(self):
 | 
						|
        return self.etraceback is not None or self.etype is not None or self.evalue is not None
 | 
						|
 | 
						|
    def getType(self):
 | 
						|
        return str(self.etype)
 | 
						|
 | 
						|
    def getValue(self):
 | 
						|
        return self.evalue
 | 
						|
 | 
						|
 | 
						|
class CodeFancy:
 | 
						|
 | 
						|
    def __init__(self, code):
 | 
						|
        self.c = code
 | 
						|
 | 
						|
    def getArgCount(self):
 | 
						|
        return self.c.co_argcount if self.c is not None else 0
 | 
						|
 | 
						|
    def getFilename(self):
 | 
						|
        return self.c.co_filename if self.c is not None else ""
 | 
						|
 | 
						|
    def getVariables(self):
 | 
						|
        return self.c.co_varnames if self.c is not None else []
 | 
						|
 | 
						|
    def getName(self):
 | 
						|
        return self.c.co_name if self.c is not None else ""
 | 
						|
 | 
						|
    def getFileName(self):
 | 
						|
        return self.c.co_filename if self.c is not None else ""
 | 
						|
 | 
						|
 | 
						|
class ArgsFancy:
 | 
						|
 | 
						|
    def __init__(self, frame, arginfo):
 | 
						|
        self.f = frame
 | 
						|
        self.a = arginfo
 | 
						|
 | 
						|
    def __str__(self):
 | 
						|
        args, varargs, kwargs = self.getArgs(), self.getVarArgs(), self.getKWArgs()
 | 
						|
        ret = ""
 | 
						|
        count = 0
 | 
						|
        size = len(args)
 | 
						|
        for arg in args:
 | 
						|
            ret = ret + ("%s = %s" % (arg, args[arg]))
 | 
						|
            count = count + 1
 | 
						|
            if count < size:
 | 
						|
                ret = ret + ", "
 | 
						|
        if varargs:
 | 
						|
            if size > 0:
 | 
						|
                ret = ret + " "
 | 
						|
            ret = ret + "varargs are " + str(varargs)
 | 
						|
        if kwargs:
 | 
						|
            if size > 0:
 | 
						|
                ret = ret + " "
 | 
						|
            ret = ret + "kwargs are " + str(kwargs)
 | 
						|
        return ret
 | 
						|
 | 
						|
    def getNumArgs(wantVarargs=False, wantKWArgs=False):
 | 
						|
        args, varargs, keywords, values = self.a
 | 
						|
        size = len(args)
 | 
						|
        if varargs and wantVarargs:
 | 
						|
            size = size + len(self.getVarArgs())
 | 
						|
        if keywords and wantKWArgs:
 | 
						|
            size = size + len(self.getKWArgs())
 | 
						|
        return size
 | 
						|
 | 
						|
    def getArgs(self):
 | 
						|
        args, _, _, values = self.a
 | 
						|
        argWValues = OrderedDict()
 | 
						|
        for arg in args:
 | 
						|
            argWValues[arg] = values[arg]
 | 
						|
        return argWValues
 | 
						|
 | 
						|
    def getVarArgs(self):
 | 
						|
        _, vargs, _, _ = self.a
 | 
						|
        if vargs:
 | 
						|
            return self.f.f_locals[vargs]
 | 
						|
        return ()
 | 
						|
 | 
						|
    def getKWArgs(self):
 | 
						|
        _, _, kwargs, _ = self.a
 | 
						|
        if kwargs:
 | 
						|
            return self.f.f_locals[kwargs]
 | 
						|
        return {}
 | 
						|
 | 
						|
 | 
						|
class FrameFancy:
 | 
						|
 | 
						|
    def __init__(self, frame):
 | 
						|
        self.f = frame
 | 
						|
 | 
						|
    def getCaller(self):
 | 
						|
        return FrameFancy(self.f.f_back)
 | 
						|
 | 
						|
    def getLineNumber(self):
 | 
						|
        return self.f.f_lineno if self.f is not None else 0
 | 
						|
 | 
						|
    def getCodeInformation(self):
 | 
						|
        return CodeFancy(self.f.f_code) if self.f is not None else None
 | 
						|
 | 
						|
    def getExceptionInfo(self):
 | 
						|
        return ExceptionFancy(self.f) if self.f is not None else None
 | 
						|
 | 
						|
    def getName(self):
 | 
						|
        return self.getCodeInformation().getName() if self.f is not None else ""
 | 
						|
 | 
						|
    def getFileName(self):
 | 
						|
        return self.getCodeInformation().getFileName() if self.f is not None else ""
 | 
						|
 | 
						|
    def getLocals(self):
 | 
						|
        return self.f.f_locals if self.f is not None else {}
 | 
						|
 | 
						|
    def getArgumentInfo(self):
 | 
						|
        return ArgsFancy(
 | 
						|
            self.f, inspect.getargvalues(
 | 
						|
                self.f)) if self.f is not None else None
 | 
						|
 | 
						|
 | 
						|
class TracerClass:
 | 
						|
 | 
						|
    def callEvent(self, frame):
 | 
						|
        pass
 | 
						|
 | 
						|
    def lineEvent(self, frame):
 | 
						|
        pass
 | 
						|
 | 
						|
    def returnEvent(self, frame, retval):
 | 
						|
        pass
 | 
						|
 | 
						|
    def exceptionEvent(self, frame, exception, value, traceback):
 | 
						|
        pass
 | 
						|
 | 
						|
    def cCallEvent(self, frame, cfunct):
 | 
						|
        pass
 | 
						|
 | 
						|
    def cReturnEvent(self, frame, cfunct):
 | 
						|
        pass
 | 
						|
 | 
						|
    def cExceptionEvent(self, frame, cfunct):
 | 
						|
        pass
 | 
						|
 | 
						|
tracer_impl = TracerClass()
 | 
						|
 | 
						|
 | 
						|
def the_tracer_entrypoint(frame, event, args):
 | 
						|
    if tracer_impl is None:
 | 
						|
        return None
 | 
						|
    if event == "call":
 | 
						|
        call_retval = tracer_impl.callEvent(FrameFancy(frame))
 | 
						|
        if not call_retval:
 | 
						|
            return None
 | 
						|
        return the_tracer_entrypoint
 | 
						|
    elif event == "line":
 | 
						|
        line_retval = tracer_impl.lineEvent(FrameFancy(frame))
 | 
						|
        if not line_retval:
 | 
						|
            return None
 | 
						|
        return the_tracer_entrypoint
 | 
						|
    elif event == "return":
 | 
						|
        tracer_impl.returnEvent(FrameFancy(frame), args)
 | 
						|
    elif event == "exception":
 | 
						|
        exty, exva, extb = args
 | 
						|
        exception_retval = tracer_impl.exceptionEvent(
 | 
						|
            FrameFancy(frame), ExceptionFancy(extb, exty, exva))
 | 
						|
        if not exception_retval:
 | 
						|
            return None
 | 
						|
        return the_tracer_entrypoint
 | 
						|
    elif event == "c_call":
 | 
						|
        tracer_impl.cCallEvent(FrameFancy(frame), args)
 | 
						|
    elif event == "c_return":
 | 
						|
        tracer_impl.cReturnEvent(FrameFancy(frame), args)
 | 
						|
    elif event == "c_exception":
 | 
						|
        tracer_impl.cExceptionEvent(FrameFancy(frame), args)
 | 
						|
    return None
 | 
						|
 | 
						|
 | 
						|
def enable(t=None):
 | 
						|
    global tracer_impl
 | 
						|
    if t:
 | 
						|
        tracer_impl = t
 | 
						|
    sys.settrace(the_tracer_entrypoint)
 | 
						|
 | 
						|
 | 
						|
def disable():
 | 
						|
    sys.settrace(None)
 | 
						|
 | 
						|
 | 
						|
class LoggingTracer:
 | 
						|
 | 
						|
    def callEvent(self, frame):
 | 
						|
        print "call " + frame.getName() + " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
 | 
						|
 | 
						|
    def lineEvent(self, frame):
 | 
						|
        print "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are " + str(frame.getLocals()) + " in " + frame.getFileName()
 | 
						|
 | 
						|
    def returnEvent(self, frame, retval):
 | 
						|
        print "return from " + frame.getName() + " value is " + str(retval) + " locals are " + str(frame.getLocals())
 | 
						|
 | 
						|
    def exceptionEvent(self, frame, exception):
 | 
						|
        print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())
 | 
						|
        print "tb: " + str(exception.getTraceback())
 | 
						|
 | 
						|
# the same functionality as LoggingTracer, but with a little more
 | 
						|
# lldb-specific smarts
 | 
						|
 | 
						|
 | 
						|
class LLDBAwareTracer:
 | 
						|
 | 
						|
    def callEvent(self, frame):
 | 
						|
        if frame.getName() == "<module>":
 | 
						|
            return
 | 
						|
        if frame.getName() == "run_one_line":
 | 
						|
            print "call run_one_line(%s)" % (frame.getArgumentInfo().getArgs()["input_string"])
 | 
						|
            return
 | 
						|
        if "Python.framework" in frame.getFileName():
 | 
						|
            print "call into Python at " + frame.getName()
 | 
						|
            return
 | 
						|
        if frame.getName() == "__init__" and frame.getCaller().getName(
 | 
						|
        ) == "run_one_line" and frame.getCaller().getLineNumber() == 101:
 | 
						|
            return False
 | 
						|
        strout = "call " + frame.getName()
 | 
						|
        if (frame.getCaller().getFileName() == ""):
 | 
						|
            strout += " from LLDB - args are "
 | 
						|
            args = frame.getArgumentInfo().getArgs()
 | 
						|
            for arg in args:
 | 
						|
                if arg == "dict" or arg == "internal_dict":
 | 
						|
                    continue
 | 
						|
                strout = strout + ("%s = %s " % (arg, args[arg]))
 | 
						|
        else:
 | 
						|
            strout += " from " + frame.getCaller().getName() + " @ " + \
 | 
						|
                str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
 | 
						|
        print strout
 | 
						|
 | 
						|
    def lineEvent(self, frame):
 | 
						|
        if frame.getName() == "<module>":
 | 
						|
            return
 | 
						|
        if frame.getName() == "run_one_line":
 | 
						|
            print "running run_one_line(%s) @ %s" % (frame.getArgumentInfo().getArgs()["input_string"], frame.getLineNumber())
 | 
						|
            return
 | 
						|
        if "Python.framework" in frame.getFileName():
 | 
						|
            print "running into Python at " + frame.getName() + " @ " + str(frame.getLineNumber())
 | 
						|
            return
 | 
						|
        strout = "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + \
 | 
						|
            " locals are "
 | 
						|
        if (frame.getCaller().getFileName() == ""):
 | 
						|
            locals = frame.getLocals()
 | 
						|
            for local in locals:
 | 
						|
                if local == "dict" or local == "internal_dict":
 | 
						|
                    continue
 | 
						|
                strout = strout + ("%s = %s " % (local, locals[local]))
 | 
						|
        else:
 | 
						|
            strout = strout + str(frame.getLocals())
 | 
						|
        strout = strout + " in " + frame.getFileName()
 | 
						|
        print strout
 | 
						|
 | 
						|
    def returnEvent(self, frame, retval):
 | 
						|
        if frame.getName() == "<module>":
 | 
						|
            return
 | 
						|
        if frame.getName() == "run_one_line":
 | 
						|
            print "return from run_one_line(%s) return value is %s" % (frame.getArgumentInfo().getArgs()["input_string"], retval)
 | 
						|
            return
 | 
						|
        if "Python.framework" in frame.getFileName():
 | 
						|
            print "return from Python at " + frame.getName() + " return value is " + str(retval)
 | 
						|
            return
 | 
						|
        strout = "return from " + frame.getName() + " return value is " + \
 | 
						|
            str(retval) + " locals are "
 | 
						|
        if (frame.getCaller().getFileName() == ""):
 | 
						|
            locals = frame.getLocals()
 | 
						|
            for local in locals:
 | 
						|
                if local == "dict" or local == "internal_dict":
 | 
						|
                    continue
 | 
						|
                strout = strout + ("%s = %s " % (local, locals[local]))
 | 
						|
        else:
 | 
						|
            strout = strout + str(frame.getLocals())
 | 
						|
        strout = strout + " in " + frame.getFileName()
 | 
						|
        print strout
 | 
						|
 | 
						|
    def exceptionEvent(self, frame, exception):
 | 
						|
        if frame.getName() == "<module>":
 | 
						|
            return
 | 
						|
        print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())
 | 
						|
        print "tb: " + str(exception.getTraceback())
 | 
						|
 | 
						|
 | 
						|
def f(x, y=None):
 | 
						|
    if x > 0:
 | 
						|
        return 2 + f(x - 2)
 | 
						|
    return 35
 | 
						|
 | 
						|
 | 
						|
def g(x):
 | 
						|
    return 1.134 / x
 | 
						|
 | 
						|
 | 
						|
def print_keyword_args(**kwargs):
 | 
						|
    # kwargs is a dict of the keyword args passed to the function
 | 
						|
    for key, value in kwargs.iteritems():
 | 
						|
        print "%s = %s" % (key, value)
 | 
						|
 | 
						|
 | 
						|
def total(initial=5, *numbers, **keywords):
 | 
						|
    count = initial
 | 
						|
    for number in numbers:
 | 
						|
        count += number
 | 
						|
    for key in keywords:
 | 
						|
        count += keywords[key]
 | 
						|
    return count
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    enable(LoggingTracer())
 | 
						|
    f(5)
 | 
						|
    f(5, 1)
 | 
						|
    print_keyword_args(first_name="John", last_name="Doe")
 | 
						|
    total(10, 1, 2, 3, vegetables=50, fruits=100)
 | 
						|
    try:
 | 
						|
        g(0)
 | 
						|
    except:
 | 
						|
        pass
 | 
						|
    disable()
 |