forked from ManageIQ/integration_tests
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtracer.py
99 lines (83 loc) · 3.07 KB
/
tracer.py
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
"""
To use the function tracer, simply import the trace object and wrap a function with it
from utils.tracer import trace::
@trace(scope=3)
def func():
print("something")
"""
import sys
from utils.log import logger
from functools32 import wraps
class FileStore(object):
def __init__(self):
"""Simple file cacher
A file store object is simple a cache of the file so that it doesn't have
to be read each time. the __getitem__ function simple checks to see if the file is
already present in the cache, if it is it serves it, if not it caches the file or
returns a blank list if the file could not be read.
"""
self._store = {}
def __getitem__(self, name):
if name in self._store:
return self._store[name]
else:
try:
self._store[name] = open(name, "r").readlines()
return self._store[name]
except IOError:
return []
file_store = FileStore()
def trace(scope=1):
""" Very simple tracer for functions and tests
The tracer module is a very simple tracer that prints out lines of code as they are
executed. It is useful when debugging tests so that you can actually see the lines of
code being executed and hence determine where blocks are happening. This is not a
substitute for good logging but a simple enhancement.
Args:
scope: This determines the depth of nested functions to go down, defaults to 1
"""
frames = []
def globaltrace(frame, why, arg):
if frame.f_code.co_filename.endswith("tracer.py"):
return globaltrace
if why == "line":
# line execution event
filename = frame.f_code.co_filename
lineno = frame.f_lineno - 1
try:
padding = " " * (len(str(len(file_store[filename]))) - len(str(lineno)))
line = file_store[filename][lineno].strip("\n")
except IndexError:
line = ""
if len(frames) <= scope:
logger.trace("{}:{}{} {}".format(len(frames), frame.f_lineno, padding, line))
if why == "call":
frames.append(frame)
if len(frames) <= scope:
s = "-" * len(frames)
c = ">" * len(frames)
logger.trace("{}{} call".format(s, c))
if why == "return":
if len(frames) <= scope:
s = "-" * len(frames)
c = "<" * len(frames)
logger.trace("{}{} call".format(s, c))
frames.pop()
return globaltrace
# def wrap(func):
# def _f(func, *args, **kwds):
# sys.settrace(globaltrace)
# result = func(*args, **kwds)
# sys.settrace(None)
# return result
# return decorator(_f)(func)
# return wrap
def wrap(func):
@wraps(func)
def _f(*args, **kwds):
sys.settrace(globaltrace)
result = func(*args, **kwds)
sys.settrace(None)
return result
return _f
return wrap