-
Notifications
You must be signed in to change notification settings - Fork 1
/
messaging.py
160 lines (136 loc) · 4.97 KB
/
messaging.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
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#messaging.py
# -*- coding: utf-8 -*-
#this is a module used for messaging. It allows multiple classes
#to handle various types of messages. It should work on all python
#versions >= 1.5.2
#source:
#http://code.activestate.com/recipes/144838-include-function-name-and-line-number-automaticall/
# $Rev: 76 $:
# $Author: ewald $:
# $Date: 2022-10-28 12:14:34 +0200 (Fr, 28. Okt 2022) $:
# $Id: messaging.py 76 2022-10-28 10:14:34Z ewald $
__version__ = "$Revision: 76 $"
import sys, string, builtins
#this flag determines whether debug output is sent to debug handlers themselves
debug = 1
def setDebugging(debugging):
global debug
debug = debugging
#print "resetted debug %d %d:" % (debug, debugging)
class MessagingException(builtins.Exception):
"""an exception class for any errors that may occur in
a messaging function"""
def __init__(self, args=None):
self.args = args
class FakeException(builtins.Exception):
"""an exception that is thrown and then caught
to get a reference to the current execution frame"""
pass
class MessageHandler:
"""All message handlers should inherit this class. Each method will be
passed a string when the executing program passes calls a messaging function"""
def handleStdMsg(self, msg):
"""do something with a standard message from the program"""
pass
def handleErrMsg(self, msg):
"""do something with an error message. This will already include the
class, method, and line of the call"""
pass
def handleDbgMsg(self, msg):
"""do something with a debug message. This will already include the
class, method, and line of the call"""
pass
class defaultMessageHandler(MessageHandler):
"""This is a default message handler. It simply spits all strings to
standard out"""
def handleStdMsg(self, msg):
sys.stdout.write(msg + "\n")
def handleErrMsg(self, msg):
sys.stderr.write(msg + "\n")
def handleDbgMsg(self, msg):
sys.stdout.write(msg + "\n")
#this keeps track of the handlers
_messageHandlers = []
#call this with the handler to register it for receiving messages
def registerMessageHandler(handler):
"""we're not going to check for inheritance, but we should check to make
sure that it has the correct methods"""
for methodName in ["handleStdMsg", "handleErrMsg", "handleDbgMsg"]:
try:
getattr(handler, methodName)
except:
raise MessagingException ( "The class " + handler.__class__.__name__ + " is missing a " + methodName + " method" )
_messageHandlers.append(handler)
def getCallString(level):
#this gets us the frame of the caller and will work
#in python versions 1.5.2 and greater (there are better
#ways starting in 2.1
try:
raise FakeException("this is fake")
except Exception as e :
#get the current execution frame
f = sys.exc_info()[2].tb_frame
#go back as many call-frames as was specified
while level >= 0:
f = f.f_back
level = level-1
#if there is a self variable in the caller's local namespace then
#we'll make the assumption that the caller is a class method
obj = f.f_locals.get("self", None)
functionName = f.f_code.co_name
if obj:
callStr = obj.__class__.__name__+"::"+functionName+" (line "+str(f.f_lineno)+")"
else:
callStr = f.f_code.co_name+" (line "+str(f.f_lineno)+")"
return callStr
#send this message to all handlers of std messages
def stdMsg(*args):
stdStr = " ".join(map(str, args))
for handler in _messageHandlers:
handler.handleStdMsg(stdStr)
#send this message to all handlers of error messages
def errMsg(*args):
errStr = "Error in "+getCallString(1)+" : "+" ".join(map(str, args))
for handler in _messageHandlers:
handler.handleErrMsg(errStr)
#send this message to all handlers of warning messages
def warnMsg(*args):
warnStr = "Warning in "+getCallString(1)+" : "+" ".join(map(str, args))
for handler in _messageHandlers:
handler.handleErrMsg(warnStr)
#send this message to all handlers of debug messages
def dbgMsg(*args):
if not debug:
return
errStr = getCallString(1)+" : "+" ".join(map(str, args))
for handler in _messageHandlers:
handler.handleDbgMsg(errStr)
registerMessageHandler(defaultMessageHandler())
#end of messaging.py
##test.py
##here is a simple use case for the above module
#from messaging import stdMsg, dbgMsg, errMsg, setDebugging
#
#setDebugging(0)
#
#dbgMsg("this won't be printed")
#stdMsg("but this will")
#
#setDebugging(1)
#
#def foo():
# dbgMsg("this is a debug message in", "foo")
#
#class bar:
# def baz(self):
# errMsg("this is an error message in bar")
#
#foo()
#b = bar()
#b.baz()
##end of test.py
#
#output is :
#but this will
#foo (line 12) : this is a debug message in foo
#Error in bar::baz (line 16) : this is an error message in bar