2022-03-20 10:34:56 +01:00
import sys , traceback , threading
2022-02-15 20:03:45 +01:00
EXIT_SUCCESS = 0
EXIT_ERROR = 1
2022-03-19 08:51:52 +01:00
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 )
2022-03-19 08:37:43 +01:00
# easy way to communicate across events
2022-03-19 11:42:31 +01:00
#TODO: make thread safe
2022-03-19 08:37:43 +01:00
class Communication :
def __init__ ( self ) :
2022-03-20 10:34:56 +01:00
self . lock = threading . Lock ( )
2022-03-19 08:37:43 +01:00
self . __messages = { }
2022-03-19 11:42:31 +01:00
# 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 ) :
2022-03-20 10:34:56 +01:00
self . lock . acquire ( )
2022-03-19 08:37:43 +01:00
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 ]
2022-03-19 11:42:31 +01:00
if additional_action == None :
pass
else :
additional_action ( )
2022-03-20 10:34:56 +01:00
self . lock . release ( )
2022-03-19 08:37:43 +01:00
# get the content of the first message tagged with name, removes the returned message by default
def get ( self , name , remove = True ) :
2022-03-20 10:34:56 +01:00
self . lock . acquire ( )
2022-03-19 08:37:43 +01:00
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 ]
2022-03-20 10:34:56 +01:00
self . lock . release ( )
2022-03-19 08:37:43 +01:00
return content
else :
2022-03-20 10:34:56 +01:00
self . lock . release ( )
2022-03-19 08:37:43 +01:00
return self . __messages [ name ] [ 0 ]
else :
2022-03-20 10:34:56 +01:00
self . lock . release ( )
2022-03-19 08:37:43 +01:00
return None
# get the contents for all messages tagged with name
def get_all ( self , name , clear = False ) :
2022-03-20 10:34:56 +01:00
self . lock . acquire ( )
2022-03-19 08:37:43 +01:00
if name in self . __messages and len ( self . __messages [ name ] ) > 0 :
contents = self . __messages [ name ]
if clear :
del self . __messages [ name ]
2022-03-20 10:34:56 +01:00
self . lock . release ( )
2022-03-19 08:37:43 +01:00
return contents
2022-03-20 10:34:56 +01:00
else :
self . lock . release ( )
return None
2022-03-19 08:37:43 +01:00
# deletes all messages tagged with name
def clear ( self , name ) :
2022-03-20 10:34:56 +01:00
self . lock . acquire ( )
2022-03-19 08:37:43 +01:00
if name in self . __messages :
del self . __messages [ name ]
2022-03-20 10:34:56 +01:00
self . lock . release ( )
2022-03-19 08:37:43 +01:00
def __del__ ( self ) :
if len ( self . __messages ) > 0 :
2022-03-19 11:42:31 +01:00
warn ( " __messages not empty upon destruction of Communication object: \n " + str ( self . __messages ) )