22import sys
33import pprint
44import json
5+ import runpy
6+ from pathlib import Path
57from typing import NewType , List , Any , Dict
68from dataclasses import dataclass
79
@@ -63,7 +65,7 @@ class TraceRecord:
6365 calls : List [Call ]
6466 types : List [Type ]
6567 events : List [Any ]
66- variables : List [List [Value ]]
68+ variables : List [List [ArgRecord ]]
6769 flow : List [Any ]
6870 paths : List [str ]
6971
@@ -90,6 +92,12 @@ def __init__(self) -> None:
9092 # self.path_map = {}
9193 self .current_call_key = CallKey (top_level .key + 1 )
9294
95+ def register_variables (self , frame ):
96+ vars_snapshot = []
97+ for name , val in frame .f_locals .items ():
98+ vars_snapshot .append (ArgRecord (name , self .load_value (val )))
99+ self .variables .append (vars_snapshot )
100+
93101 def register_step (self , path : str , line_arg : Any ):
94102 try :
95103 line = int (line_arg )
@@ -179,25 +187,37 @@ def path_id(self, path: str) -> PathId:
179187
180188
181189def trace_func (frame , event : str , arg ):
190+ filename = frame .f_code .co_filename
191+ if not filename .startswith (PROGRAM_DIR ):
192+ return
182193 if event == 'call' :
183- if not frame .f_code .co_filename . startswith ( '<frozen ' ):
184- TRACE .register_call (frame . f_code . co_filename , frame . f_code . co_name , frame . f_lineno )
194+ TRACE . register_call ( filename , frame . f_lineno , frame .f_code .co_name )
195+ TRACE .register_variables (frame )
185196 return trace_in_func
186197
187198def trace_in_func (frame , event : str , arg ):
188- # print(dir(frame.f_code))
189- if not frame .f_code .co_filename .startswith ('<frozen ' ):
190- if event == 'line' :
191- TRACE .register_step (frame .f_code .co_filename , frame .f_lineno )
192- elif event == 'call' :
193- print ('CALL' )
194- elif event == 'return' :
195- TRACE .register_return (frame .f_code .co_filename , frame .f_lineno , arg )
199+ filename = frame .f_code .co_filename
200+ if not filename .startswith (PROGRAM_DIR ):
201+ return
202+ if event == 'line' :
203+ TRACE .register_step (filename , frame .f_lineno )
204+ TRACE .register_variables (frame )
205+ elif event == 'call' :
206+ pass
207+ elif event == 'return' :
208+ TRACE .register_return (filename , frame .f_lineno , arg )
209+ TRACE .register_variables (frame )
196210 return trace_in_func
197211
212+ if len (sys .argv ) < 2 :
213+ raise SystemExit ("Usage: trace.py <program.py>" )
214+
215+ program_path = os .path .abspath (sys .argv [1 ])
216+ PROGRAM_DIR = str (Path (program_path ).parent )
217+
198218sys .settrace (trace_func )
199219
200- import calc
220+ runpy . run_path ( program_path , run_name = "__main__" )
201221
202222sys .settrace (None )
203223
0 commit comments