[mlir][python] Update minimal version of pybind11 to 2.10. (#117314)
[llvm-project.git] / lldb / examples / python / pytracer.py
blob88bf612755d55fcefb7233c1e269b0e49f39d5c7
1 import sys
2 import inspect
3 from collections import OrderedDict
6 class TracebackFancy:
7 def __init__(self, traceback):
8 self.t = traceback
10 def getFrame(self):
11 return FrameFancy(self.t.tb_frame)
13 def getLineNumber(self):
14 return self.t.tb_lineno if self.t is not None else None
16 def getNext(self):
17 return TracebackFancy(self.t.tb_next)
19 def __str__(self):
20 if self.t is None:
21 return ""
22 str_self = "%s @ %s" % (self.getFrame().getName(), self.getLineNumber())
23 return str_self + "\n" + self.getNext().__str__()
26 class ExceptionFancy:
27 def __init__(self, frame):
28 self.etraceback = frame.f_exc_traceback
29 self.etype = frame.exc_type
30 self.evalue = frame.f_exc_value
32 def __init__(self, tb, ty, va):
33 self.etraceback = tb
34 self.etype = ty
35 self.evalue = va
37 def getTraceback(self):
38 return TracebackFancy(self.etraceback)
40 def __nonzero__(self):
41 return (
42 self.etraceback is not None
43 or self.etype is not None
44 or self.evalue is not None
47 def getType(self):
48 return str(self.etype)
50 def getValue(self):
51 return self.evalue
54 class CodeFancy:
55 def __init__(self, code):
56 self.c = code
58 def getArgCount(self):
59 return self.c.co_argcount if self.c is not None else 0
61 def getFilename(self):
62 return self.c.co_filename if self.c is not None else ""
64 def getVariables(self):
65 return self.c.co_varnames if self.c is not None else []
67 def getName(self):
68 return self.c.co_name if self.c is not None else ""
70 def getFileName(self):
71 return self.c.co_filename if self.c is not None else ""
74 class ArgsFancy:
75 def __init__(self, frame, arginfo):
76 self.f = frame
77 self.a = arginfo
79 def __str__(self):
80 args, varargs, kwargs = self.getArgs(), self.getVarArgs(), self.getKWArgs()
81 ret = ""
82 count = 0
83 size = len(args)
84 for arg in args:
85 ret = ret + ("%s = %s" % (arg, args[arg]))
86 count = count + 1
87 if count < size:
88 ret = ret + ", "
89 if varargs:
90 if size > 0:
91 ret = ret + " "
92 ret = ret + "varargs are " + str(varargs)
93 if kwargs:
94 if size > 0:
95 ret = ret + " "
96 ret = ret + "kwargs are " + str(kwargs)
97 return ret
99 def getNumArgs(wantVarargs=False, wantKWArgs=False):
100 args, varargs, keywords, values = self.a
101 size = len(args)
102 if varargs and wantVarargs:
103 size = size + len(self.getVarArgs())
104 if keywords and wantKWArgs:
105 size = size + len(self.getKWArgs())
106 return size
108 def getArgs(self):
109 args, _, _, values = self.a
110 argWValues = OrderedDict()
111 for arg in args:
112 argWValues[arg] = values[arg]
113 return argWValues
115 def getVarArgs(self):
116 _, vargs, _, _ = self.a
117 if vargs:
118 return self.f.f_locals[vargs]
119 return ()
121 def getKWArgs(self):
122 _, _, kwargs, _ = self.a
123 if kwargs:
124 return self.f.f_locals[kwargs]
125 return {}
128 class FrameFancy:
129 def __init__(self, frame):
130 self.f = frame
132 def getCaller(self):
133 return FrameFancy(self.f.f_back)
135 def getLineNumber(self):
136 return self.f.f_lineno if self.f is not None else 0
138 def getCodeInformation(self):
139 return CodeFancy(self.f.f_code) if self.f is not None else None
141 def getExceptionInfo(self):
142 return ExceptionFancy(self.f) if self.f is not None else None
144 def getName(self):
145 return self.getCodeInformation().getName() if self.f is not None else ""
147 def getFileName(self):
148 return self.getCodeInformation().getFileName() if self.f is not None else ""
150 def getLocals(self):
151 return self.f.f_locals if self.f is not None else {}
153 def getArgumentInfo(self):
154 return (
155 ArgsFancy(self.f, inspect.getargvalues(self.f))
156 if self.f is not None
157 else None
161 class TracerClass:
162 def callEvent(self, frame):
163 pass
165 def lineEvent(self, frame):
166 pass
168 def returnEvent(self, frame, retval):
169 pass
171 def exceptionEvent(self, frame, exception, value, traceback):
172 pass
174 def cCallEvent(self, frame, cfunct):
175 pass
177 def cReturnEvent(self, frame, cfunct):
178 pass
180 def cExceptionEvent(self, frame, cfunct):
181 pass
184 tracer_impl = TracerClass()
187 def 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)
207 if not exception_retval:
208 return None
209 return the_tracer_entrypoint
210 elif event == "c_call":
211 tracer_impl.cCallEvent(FrameFancy(frame), args)
212 elif event == "c_return":
213 tracer_impl.cReturnEvent(FrameFancy(frame), args)
214 elif event == "c_exception":
215 tracer_impl.cExceptionEvent(FrameFancy(frame), args)
216 return None
219 def enable(t=None):
220 global tracer_impl
221 if t:
222 tracer_impl = t
223 sys.settrace(the_tracer_entrypoint)
226 def disable():
227 sys.settrace(None)
230 class LoggingTracer:
231 def callEvent(self, frame):
232 print(
233 "call "
234 + frame.getName()
235 + " from "
236 + frame.getCaller().getName()
237 + " @ "
238 + str(frame.getCaller().getLineNumber())
239 + " args are "
240 + str(frame.getArgumentInfo())
243 def lineEvent(self, frame):
244 print(
245 "running "
246 + frame.getName()
247 + " @ "
248 + str(frame.getLineNumber())
249 + " locals are "
250 + str(frame.getLocals())
251 + " in "
252 + frame.getFileName()
255 def returnEvent(self, frame, retval):
256 print(
257 "return from "
258 + frame.getName()
259 + " value is "
260 + str(retval)
261 + " locals are "
262 + str(frame.getLocals())
265 def exceptionEvent(self, frame, exception):
266 print(
267 "exception %s %s raised from %s @ %s"
269 exception.getType(),
270 str(exception.getValue()),
271 frame.getName(),
272 frame.getLineNumber(),
275 print("tb: " + str(exception.getTraceback()))
278 # the same functionality as LoggingTracer, but with a little more
279 # lldb-specific smarts
282 class LLDBAwareTracer:
283 def callEvent(self, frame):
284 if frame.getName() == "<module>":
285 return
286 if frame.getName() == "run_one_line":
287 print(
288 "call run_one_line(%s)"
289 % (frame.getArgumentInfo().getArgs()["input_string"])
291 return
292 if "Python.framework" in frame.getFileName():
293 print("call into Python at " + frame.getName())
294 return
295 if (
296 frame.getName() == "__init__"
297 and frame.getCaller().getName() == "run_one_line"
298 and frame.getCaller().getLineNumber() == 101
300 return False
301 strout = "call " + frame.getName()
302 if frame.getCaller().getFileName() == "":
303 strout += " from LLDB - args are "
304 args = frame.getArgumentInfo().getArgs()
305 for arg in args:
306 if arg == "dict" or arg == "internal_dict":
307 continue
308 strout = strout + ("%s = %s " % (arg, args[arg]))
309 else:
310 strout += (
311 " from "
312 + frame.getCaller().getName()
313 + " @ "
314 + str(frame.getCaller().getLineNumber())
315 + " args are "
316 + str(frame.getArgumentInfo())
318 print(strout)
320 def lineEvent(self, frame):
321 if frame.getName() == "<module>":
322 return
323 if frame.getName() == "run_one_line":
324 print(
325 "running run_one_line(%s) @ %s"
327 frame.getArgumentInfo().getArgs()["input_string"],
328 frame.getLineNumber(),
331 return
332 if "Python.framework" in frame.getFileName():
333 print(
334 "running into Python at "
335 + frame.getName()
336 + " @ "
337 + str(frame.getLineNumber())
339 return
340 strout = (
341 "running "
342 + frame.getName()
343 + " @ "
344 + str(frame.getLineNumber())
345 + " locals are "
347 if frame.getCaller().getFileName() == "":
348 locals = frame.getLocals()
349 for local in locals:
350 if local == "dict" or local == "internal_dict":
351 continue
352 strout = strout + ("%s = %s " % (local, locals[local]))
353 else:
354 strout = strout + str(frame.getLocals())
355 strout = strout + " in " + frame.getFileName()
356 print(strout)
358 def returnEvent(self, frame, retval):
359 if frame.getName() == "<module>":
360 return
361 if frame.getName() == "run_one_line":
362 print(
363 "return from run_one_line(%s) return value is %s"
364 % (frame.getArgumentInfo().getArgs()["input_string"], retval)
366 return
367 if "Python.framework" in frame.getFileName():
368 print(
369 "return from Python at "
370 + frame.getName()
371 + " return value is "
372 + str(retval)
374 return
375 strout = (
376 "return from "
377 + frame.getName()
378 + " return value is "
379 + str(retval)
380 + " locals are "
382 if frame.getCaller().getFileName() == "":
383 locals = frame.getLocals()
384 for local in locals:
385 if local == "dict" or local == "internal_dict":
386 continue
387 strout = strout + ("%s = %s " % (local, locals[local]))
388 else:
389 strout = strout + str(frame.getLocals())
390 strout = strout + " in " + frame.getFileName()
391 print(strout)
393 def exceptionEvent(self, frame, exception):
394 if frame.getName() == "<module>":
395 return
396 print(
397 "exception %s %s raised from %s @ %s"
399 exception.getType(),
400 str(exception.getValue()),
401 frame.getName(),
402 frame.getLineNumber(),
405 print("tb: " + str(exception.getTraceback()))
408 def f(x, y=None):
409 if x > 0:
410 return 2 + f(x - 2)
411 return 35
414 def g(x):
415 return 1.134 / x
418 def print_keyword_args(**kwargs):
419 # kwargs is a dict of the keyword args passed to the function
420 for key, value in kwargs.items():
421 print("%s = %s" % (key, value))
424 def total(initial=5, *numbers, **keywords):
425 count = initial
426 for number in numbers:
427 count += number
428 for key in keywords:
429 count += keywords[key]
430 return count
433 if __name__ == "__main__":
434 enable(LoggingTracer())
435 f(5)
436 f(5, 1)
437 print_keyword_args(first_name="John", last_name="Doe")
438 total(10, 1, 2, 3, vegetables=50, fruits=100)
439 try:
440 g(0)
441 except:
442 pass
443 disable()