-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstack_tracer.py
More file actions
45 lines (38 loc) · 1.63 KB
/
stack_tracer.py
File metadata and controls
45 lines (38 loc) · 1.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# stack_tracer.py
# before every line of code runs, get stack frames and call render.py
# user presses Enter to move to run next line of code (otherwise execution is too fast)
import sys
import os
import types
import io
from time import sleep
from render import update_ui
stdout_buffer = io.StringIO()
user_program = ""
comprehensive_flag = False # if True: can see import module & functions in <module>'s frame's LOCALs
def start_tracing(path_to_user_program, comprehensive):
global user_program # need global keyword to assign to global var
user_program = path_to_user_program
global comprehensive_flag
comprehensive_flag = comprehensive
sys.stdout = stdout_buffer # redirect stdout into our buffer
sys.settrace(trace) # trace gets called before every line of code runs
def stop_tracing():
sys.settrace(None)
sys.stdout = sys.__stdout__
# event = "line" / "call" / "return" / "exception"
# 1 frame = 1 function call
def trace(curr_frame, event, arg):
filename = os.path.abspath(curr_frame.f_code.co_filename)
if filename != user_program:
return trace
if event == "line": # when a line is about to execute (we care about this)
# print_stack(curr_frame)
update_ui(curr_frame, stdout_buf=stdout_buffer.getvalue())
input() # click Enter to step through code line by line
# elif event == "call":
# print(f"\n>>> CALL {curr_frame.f_code.co_name}()")
# print_local_vars(curr_frame)
# elif event == "return":
# print(f"\n<<< RETURN {curr_frame.f_code.co_name}() = {arg}")
return trace # return itself to keep using this when next event hits