baseimage-tutorial-framework/lib/tfw/event_handlers/event_handler_base.py

116 lines
3.4 KiB
Python
Raw Normal View History

2019-06-10 13:32:45 +00:00
import logging
from inspect import currentframe
from typing import Iterable
LOG = logging.getLogger(__name__)
2019-06-28 13:11:02 +00:00
class EventHandlerBase:
2018-04-18 17:44:26 +00:00
"""
Abstract base class for all Python based EventHandlers. Useful implementation template
for other languages.
Derived classes must implement the handle_event() method
"""
def __init__(self, key, server_connector, scope):
2019-06-28 13:11:02 +00:00
self.server_connector = server_connector
self.scope = scope
self.keys = []
if isinstance(key, str):
self.keys.append(key)
elif isinstance(key, Iterable):
self.keys = list(key)
self.subscribe(*self.keys)
2018-01-26 14:16:34 +00:00
self.server_connector.register_callback(self.event_handler_callback)
def subscribe(self, *keys):
"""
Subscribe this EventHandler to receive events for given keys.
Note that you can subscribe to the same key several times in which
case you will need to unsubscribe multiple times in order to stop
receiving events.
:param keys: list of keys to subscribe to
"""
for key in keys:
self.server_connector.subscribe(key)
self.keys.append(key)
def event_handler_callback(self, message):
"""
Callback that is invoked when receiving a message.
Dispatches messages to handler methods and sends
a response back in case the handler returned something.
This is subscribed in __init__().
"""
if self.check_key(message):
self.dispatch_handling(message)
def check_key(self, message):
"""
Checks whether the message is intended for this
EventHandler.
This is necessary because ZMQ handles PUB - SUB
connetions with pattern matching (e.g. someone
subscribed to 'fsm' will receive 'fsm_update'
messages as well.
"""
if '' in self.keys:
return True
return message['key'] in self.keys
def dispatch_handling(self, message):
"""
Used to dispatch messages to their specific handlers.
:param message: the message received
:returns: the message to send back
"""
self.handle_event(message)
def handle_event(self, message):
"""
Abstract method that implements the handling of messages.
:param message: the message received
:returns: the message to send back
"""
raise NotImplementedError
def send_message(self, message):
self.server_connector.send_message(message, self.scope)
def unsubscribe(self, *keys):
"""
Unsubscribe this eventhandler from the given keys.
:param keys: list of keys to unsubscribe from
"""
for key in keys:
self.server_connector.unsubscribe(key)
self.keys.remove(key)
2019-05-20 09:06:57 +00:00
def stop(self):
self.server_connector.close()
self.cleanup()
def cleanup(self):
"""
Perform cleanup actions such as releasing database
connections and stuff like that.
"""
@classmethod
def get_local_instances(cls):
frame = currentframe()
if frame is None:
raise EnvironmentError('inspect.currentframe() is not supported!')
locals_values = frame.f_back.f_locals.values()
return {
instance for instance in locals_values
if isinstance(instance, cls)
}