-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathprint_hook.py
104 lines (87 loc) · 3 KB
/
print_hook.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
100
101
102
103
104
import sys
# this class gets all output directed to stdout(e.g by print statements)
# and stderr and redirects it to a user defined function
class PrintHook:
# out = 1 means stdout will be hooked
# out = 0 means stderr will be hooked
def __init__(self, out=1):
self.func = None ##self.func is userdefined function
self.origOut = None
self.out = out
# user defined hook must return three variables
# proceed, lineNoMode, newText
def TestHook(self, text):
f = open('hook_log.txt', 'a')
f.write(text)
f.close()
return 0, 0, text
def Start(self, func=None):
if self.out:
sys.stdout = self
self.origOut = sys.__stdout__
else:
sys.stderr = self
self.origOut = sys.__stderr__
if func:
self.func = func
else:
self.func = self.TestHook
# Stop will stop routing of print statements thru this class
def Stop(self):
self.origOut.flush()
if self.out:
sys.stdout = sys.__stdout__
else:
sys.stderr = sys.__stderr__
self.func = None
# override write of stdout
def write(self, text):
bProceed = 1
bLineNo = 0
newText = ''
if self.func != None:
bProceed, bLineNo, newText = self.func(text)
if bProceed:
if text.split() == []:
self.origOut.write(text)
else:
# if goint to stdout then only add line no file etc
# for stderr it is already there
if self.out:
if bLineNo:
try:
raise Exception("Dummy")
except:
lineNo = 'line(' + str(sys.exc_info()[2].tb_frame.f_back.f_lineno) + '):'
codeObject = sys.exc_info()[2].tb_frame.f_back.f_code
fileName = codeObject.co_filename
funcName = codeObject.co_name
self.origOut.write('file ' + fileName + ',' + 'func ' + funcName + ':' + lineNo)
self.origOut.write(newText)
# pass all other methods to __stdout__ so that we don't have to override them
def __getattr__(self, name):
# return self.origOut.__getattr__(name)
return getattr(self.origOut, name)
if __name__ == '__main__':
def MyHookOut(text):
f = open('log.txt', 'a')
f.write(text)
f.close()
return 1, 1, 'Out Hooked:' + text
def MyHookErr(text):
f = open('hook_log.txt', 'a')
f.write(text)
f.close()
return 1, 1, 'Err Hooked:' + text
print('Hook Start')
phOut = PrintHook()
phOut.Start(MyHookOut)
phErr = PrintHook(0)
phErr.Start(MyHookErr)
print('Is this working?')
print('It seems so!')
phOut.Stop()
print('STDOUT Hook end')
compile(',', '<string>', 'exec')
phErr.Stop()
print('Hook end')