blob: 497a49ccb69c2ba47b3b839c02b6be9a368b3af6 [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):
13 return self.t.tb_lineno
14
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):
52 return self.c.co_argcount
53
54 def getFilename(self):
55 return self.c.co_filename
56
57 def getVariables(self):
58 return self.c.co_varnames
59
60 def getName(self):
61 return self.c.co_name
62
63class ArgsFancy:
64 def __init__(self,frame,arginfo):
65 self.f = frame
66 self.a = arginfo
67
68 def __str__(self):
69 args, varargs, kwargs = self.getArgs(), self.getVarArgs(), self.getKWArgs()
70 ret = ""
71 count = 0
72 size = len(args)
73 for arg in args:
74 ret = ret + ("%s = %s" % (arg, args[arg]))
75 count = count + 1
76 if count < size:
77 ret = ret + ", "
78 if varargs:
79 if size > 0:
80 ret = ret + " "
81 ret = ret + "varargs are " + str(varargs)
82 if kwargs:
83 if size > 0:
84 ret = ret + " "
85 ret = ret + "kwargs are " + str(kwargs)
86 return ret
87
88 def getNumArgs(wantVarargs = False, wantKWArgs=False):
89 args, varargs, keywords, values = self.a
90 size = len(args)
91 if varargs and wantVarargs:
92 size = size+len(self.getVarArgs())
93 if keywords and wantKWArgs:
94 size = size+len(self.getKWArgs())
95 return size
96
97 def getArgs(self):
98 args, _, _, values = self.a
99 argWValues = OrderedDict()
100 for arg in args:
101 argWValues[arg] = values[arg]
102 return argWValues
103
104 def getVarArgs(self):
105 _, vargs, _, _ = self.a
106 if vargs:
107 return self.f.f_locals[vargs]
108 return ()
109
110 def getKWArgs(self):
111 _, _, kwargs, _ = self.a
112 if kwargs:
113 return self.f.f_locals[kwargs]
114 return {}
115
116class FrameFancy:
117 def __init__(self,frame):
118 self.f = frame
119
120 def getCaller(self):
121 return FrameFancy(self.f.f_back)
122
123 def getLineNumber(self):
124 return self.f.f_lineno
125
126 def getCodeInformation(self):
127 return CodeFancy(self.f.f_code)
128
129 def getExceptionInfo(self):
130 return ExceptionFancy(self.f)
131
132 def getName(self):
133 return self.f.f_code.co_name
134
135 def getLocals(self):
136 return self.f.f_locals
137
138 def getArgumentInfo(self):
139 return ArgsFancy(self.f,inspect.getargvalues(self.f))
140
141class TracerClass:
142 def callEvent(self,frame):
143 pass
144
145 def lineEvent(self,frame):
146 pass
147
148 def returnEvent(self,frame,retval):
149 pass
150
151 def exceptionEvent(self,frame,exception,value,traceback):
152 pass
153
154 def cCallEvent(self,frame,cfunct):
155 pass
156
157 def cReturnEvent(self,frame,cfunct):
158 pass
159
160 def cExceptionEvent(self,frame,cfunct):
161 pass
162
163tracer_impl = TracerClass()
164
165
166def the_tracer_entrypoint(frame,event,args):
167 if tracer_impl == None:
168 return None
169 if event == "call":
170 call_retval = tracer_impl.callEvent(FrameFancy(frame))
171 if call_retval == False:
172 return None
173 return the_tracer_entrypoint
174 elif event == "line":
175 line_retval = tracer_impl.lineEvent(FrameFancy(frame))
176 if line_retval == False:
177 return None
178 return the_tracer_entrypoint
179 elif event == "return":
180 tracer_impl.returnEvent(FrameFancy(frame),args)
181 elif event == "exception":
182 exty,exva,extb = args
183 exception_retval = tracer_impl.exceptionEvent(FrameFancy(frame),ExceptionFancy(extb,exty,exva))
184 if exception_retval == False:
185 return None
186 return the_tracer_entrypoint
187 elif event == "c_call":
188 tracer_impl.cCallEvent(FrameFancy(frame),args)
189 elif event == "c_return":
190 tracer_impl.cReturnEvent(FrameFancy(frame),args)
191 elif event == "c_exception":
192 tracer_impl.cExceptionEvent(FrameFancy(frame),args)
193 return None
194
195def enable(t=None):
196 global tracer_impl
197 if t:
198 tracer_impl = t
199 sys.settrace(the_tracer_entrypoint)
200
201def disable():
202 sys.settrace(None)
203
204class LoggingTracer:
205 def callEvent(self,frame):
206 print "call " + frame.getName() + " from " + frame.getCaller().getName() + " @ " + str(frame.getCaller().getLineNumber()) + " args are " + str(frame.getArgumentInfo())
207
208 def lineEvent(self,frame):
209 print "running " + frame.getName() + " @ " + str(frame.getLineNumber()) + " locals are " + str(frame.getLocals())
210
211 def returnEvent(self,frame,retval):
212 print "return from " + frame.getName() + " value is " + str(retval) + " locals are " + str(frame.getLocals())
213
214 def exceptionEvent(self,frame,exception):
215 print "exception %s %s raised from %s @ %s" % (exception.getType(), str(exception.getValue()), frame.getName(), frame.getLineNumber())
216 print "tb: " + str(exception.getTraceback())
217
218def f(x,y=None):
219 if x > 0:
220 return 2 + f(x-2)
221 return 35
222
223def g(x):
224 return 1.134 / x
225
226def print_keyword_args(**kwargs):
227 # kwargs is a dict of the keyword args passed to the function
228 for key, value in kwargs.iteritems():
229 print "%s = %s" % (key, value)
230
231def total(initial=5, *numbers, **keywords):
232 count = initial
233 for number in numbers:
234 count += number
235 for key in keywords:
236 count += keywords[key]
237 return count
238
239if __name__ == "__main__":
240 enable(LoggingTracer())
241 f(5)
242 f(5,1)
243 print_keyword_args(first_name="John", last_name="Doe")
244 total(10, 1, 2, 3, vegetables=50, fruits=100)
245 try:
246 g(0)
247 except:
248 pass
249 disable()