91 lines
3.0 KiB
Python
91 lines
3.0 KiB
Python
import sys, traceback, threading
|
||
|
||
EXIT_SUCCESS=0
|
||
EXIT_ERROR=1
|
||
|
||
def info(message):
|
||
# print info to sys.stderr because it isn’t really output, just debug information
|
||
print("INFO: "+str(message), file=sys.stderr)
|
||
traceback.print_stack()
|
||
|
||
def warn(message, is_exception=False):
|
||
print("WARNING: "+str(message), file=sys.stderr)
|
||
if is_exception:
|
||
traceback.print_exc()
|
||
else:
|
||
traceback.print_stack()
|
||
|
||
def error(message, is_exception=True, handle_gracefully=True):
|
||
print("ERROR: "+str(message), file=sys.stderr)
|
||
if is_exception:
|
||
traceback.print_exc()
|
||
else:
|
||
traceback.print_stack()
|
||
if handle_gracefully:
|
||
pass
|
||
else:
|
||
sys.exit(EXIT_ERROR)
|
||
|
||
# easy way to communicate across events
|
||
class Communication:
|
||
def __init__(self):
|
||
self.lock = threading.Lock()
|
||
self.__messages = {}
|
||
|
||
# send a message tagged with name and containing content, adds to the beginning of the list of messages with the same tag by default, a function to run as an additional action can be provided
|
||
def send(self, name, content, reverse_order=True, additional_action=None):
|
||
self.lock.acquire()
|
||
if name in self.__messages:
|
||
if reverse_order:
|
||
self.__messages[name] = [content] + self.__messages[name]
|
||
else:
|
||
self.__messages[name] = self.__messages[name] + [content]
|
||
else:
|
||
self.__messages[name] = [content]
|
||
if additional_action == None:
|
||
pass
|
||
else:
|
||
additional_action()
|
||
self.lock.release()
|
||
|
||
# get the content of the first message tagged with name, removes the returned message by default
|
||
def get(self, name, remove=True):
|
||
self.lock.acquire()
|
||
if name in self.__messages and len(self.__messages[name])>0:
|
||
if remove:
|
||
content = self.__messages[name].pop(0)
|
||
if len(self.__messages[name])==0:
|
||
del self.__messages[name]
|
||
self.lock.release()
|
||
return content
|
||
else:
|
||
self.lock.release()
|
||
return self.__messages[name][0]
|
||
else:
|
||
self.lock.release()
|
||
return None
|
||
|
||
# get the contents for all messages tagged with name
|
||
def get_all(self, name, clear=False):
|
||
self.lock.acquire()
|
||
if name in self.__messages and len(self.__messages[name])>0:
|
||
contents = self.__messages[name]
|
||
if clear:
|
||
del self.__messages[name]
|
||
self.lock.release()
|
||
return contents
|
||
else:
|
||
self.lock.release()
|
||
return None
|
||
|
||
# deletes all messages tagged with name
|
||
def clear(self, name):
|
||
self.lock.acquire()
|
||
if name in self.__messages:
|
||
del self.__messages[name]
|
||
self.lock.release()
|
||
|
||
def __del__(self):
|
||
if len(self.__messages)>0:
|
||
warn("__messages not empty upon destruction of Communication object:\n"+str(self.__messages))
|