-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_trace.py
More file actions
133 lines (96 loc) · 3.47 KB
/
Copy pathtest_trace.py
File metadata and controls
133 lines (96 loc) · 3.47 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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import sys
# import traceback
import inspect
import linecache
# file.func:var
tracked_info = ['test_trace.b:z']
def check_tracked_info( frame, only_assignments = False):
"""should work only for assignments"""
co = frame.f_code
func_name = co.co_name
lineno = frame.f_lineno
filename = co.co_filename[:-len(".py")]
line = linecache.getline(filename, lineno-1 )
if only_assignments:
is_assignment = "=" in line and "==" not in line
if not is_assignment:
return
lhs = line[:line.index("=")].strip()
locals_ = {name: frame.f_locals[name] for name in lhs.split(',')}
else:
locals_ = frame.f_locals
for inf in tracked_info:
inf = inf.replace(':', '.')
mod, func, var = inf.split('.')
if ( mod, func ) == (filename, func_name ):
for lvar in locals_:
if var == lvar:
print(f"Tracked_var: {var}: {locals_[var]}")
start_frame = None
def format_inspect_stack(stack, start_frame, end_frame):
# FrameInfo(frame, filename, lineno, function, code_context, index)
calls = []
for fi in stack:
# line = open(fi.filename).readlines()[ fi.lineno-1 ]
line = linecache.getline(fi.filename, fi.lineno-1 )
func_name = fi.frame.f_code.co_name
calls.insert(0, f'{fi.filename}:{fi.lineno}:{func_name}: {line}' )
if fi.frame is start_frame:
break
calls = [' '*i + "-> " + line for i, line in enumerate( calls ) ] # add indents
return ''.join( calls )
def trace_calls(frame, event, arg):
co = frame.f_code
func_name = co.co_name
func_line_no = line_no = frame.f_lineno
func_filename = filename = co.co_filename
if func_name == 'trace_calls':
return
if event == 'return':
print ('%s => %s' % (func_name, arg))
if func_name == 'b':
print( "LOCAL x", frame.f_locals['x'] )
if event == 'call':
caller = frame.f_back
if caller is None:
return
caller_line_no = caller.f_lineno
caller_filename = caller.f_code.co_filename
if func_name == 'a':
global start_frame
start_frame = caller
if func_name == 'write':
# Ignore write() calls from print statements
return
# print ('Call to %s on line %s of %s from line %s of %s' % \
# (func_name, func_line_no, func_filename,
# caller_line_no, caller_filename)
# )
caller_line = open(caller_filename).readlines()[ caller_line_no-1 ]
print( caller_line )
return trace_calls
if event == 'line':
line = open(filename).readlines()[ line_no-1 ]
check_tracked_info( frame )
if 'return' in line:
print ("!!!", line)
# traceback.print_stack()
# print("traceback STACK: ", ''.join( traceback.format_stack()[:-1]))
print("inspect STACK\n")
print(format_inspect_stack( inspect.stack()[1:], start_frame, end_frame=frame ) )
def c():
print("in c()")
pass # HERE
def b(x):
print ('in b()')
z = x
c()
return "ret b"
def a():
print ('in a()')
b(4)
return "ret a"
def start():
a()
sys.settrace(trace_calls)
start()