From 577db32468f4f12a705b3c653ce50c1f5f9ae11e Mon Sep 17 00:00:00 2001 From: Stefano Borini <sborini@enthought.com> Date: Wed, 9 Aug 2017 16:08:04 +0100 Subject: [PATCH] Introduced initialize and finalize --- force_bdss/core_mco_driver.py | 25 +++++++++++++-- .../dummy_notification_listener.py | 5 ++- .../dummy/ui_notification/ui_notification.py | 8 ++++- .../base_notification_listener.py | 32 ++++++++++++++++--- .../base_notification_listener_factory.py | 24 +++++++++++--- .../i_notification_listener_factory.py | 9 ++---- 6 files changed, 82 insertions(+), 21 deletions(-) diff --git a/force_bdss/core_mco_driver.py b/force_bdss/core_mco_driver.py index 36e0450..6e17888 100644 --- a/force_bdss/core_mco_driver.py +++ b/force_bdss/core_mco_driver.py @@ -1,6 +1,7 @@ from __future__ import print_function import sys +import logging from traits.api import on_trait_change, Instance, List @@ -31,6 +32,17 @@ class CoreMCODriver(BaseCoreDriver): def application_started(self): self.mco.run(self.workflow.mco) + @on_trait_change("application:stopping") + def application_stopping(self): + for listener in self.listeners: + try: + listener.finalize(None) + except Exception as e: + logging.error( + "Failed to finalize " + "listener {}: {}".format( + listener.__class__.__name__, str(e))) + def _mco_default(self): try: workflow = self.workflow @@ -51,8 +63,15 @@ class CoreMCODriver(BaseCoreDriver): listeners = [] for factory in self.factory_registry.notification_listener_factories: - listener = factory.create_listener() - listener.init_persistent_state(None) - listeners.append(listener) + try: + listener = factory.create_listener() + listener.initialize(None) + except Exception as e: + logging.error( + "Failed to create or initialize " + "listener with id {}: {}".format( + factory.id, str(e))) + else: + listeners.append(listener) return listeners diff --git a/force_bdss/core_plugins/dummy/dummy_notification_listener/dummy_notification_listener.py b/force_bdss/core_plugins/dummy/dummy_notification_listener/dummy_notification_listener.py index 6efc45a..dbd0ed7 100644 --- a/force_bdss/core_plugins/dummy/dummy_notification_listener/dummy_notification_listener.py +++ b/force_bdss/core_plugins/dummy/dummy_notification_listener/dummy_notification_listener.py @@ -10,5 +10,8 @@ class DummyNotificationListener(BaseNotificationListener): elif isinstance(event, MCOProgressEvent): print(event.__class__.__name__, event.input, event.output) - def init_persistent_state(self, model): + def initialize(self, model): print("Initializing persistent state") + + def finalize(self, model): + print("Finalizing persistent state") diff --git a/force_bdss/core_plugins/dummy/ui_notification/ui_notification.py b/force_bdss/core_plugins/dummy/ui_notification/ui_notification.py index 48cb2af..c8fe935 100644 --- a/force_bdss/core_plugins/dummy/ui_notification/ui_notification.py +++ b/force_bdss/core_plugins/dummy/ui_notification/ui_notification.py @@ -41,7 +41,7 @@ class UINotification(BaseNotificationListener): self._msg_cache.append(msg) self._pub_socket.send(msg) - def init_persistent_state(self, model): + def initialize(self, model): self._context = zmq.Context() self._pub_socket = self._context.socket(zmq.PUB) self._pub_socket.bind("tcp://*:12345") @@ -62,3 +62,9 @@ class UINotification(BaseNotificationListener): return None return ("EVENT\n{}".format(data)).encode("utf-8") + + def finalize(self, model): + self._context.destroy() + self._pub_socket = None + self._rep_socket = None + self._context = None diff --git a/force_bdss/notification_listeners/base_notification_listener.py b/force_bdss/notification_listeners/base_notification_listener.py index a43d4f2..64b8243 100644 --- a/force_bdss/notification_listeners/base_notification_listener.py +++ b/force_bdss/notification_listeners/base_notification_listener.py @@ -24,9 +24,33 @@ class BaseNotificationListener(ABCHasStrictTraits): self.factory = factory super(BaseNotificationListener, self).__init__(*args, **kwargs) + def initialize(self, model): + """ + Method used to initialize persistent state of the listener using + information from the model. + + Reimplement it in your Notification Listener to perform special + initialization of state that survives across deliver() invocations, + such as setting up a connection, or opening a file. + """ + + def finalize(self, model): + """ + Method used to finalize state of the listener. + + Reimplement it in your Notification Listener to perform special + finalization of state that survives across deliver() invocations, + such as closing a connection, or closing a file. + """ + @abc.abstractmethod - def deliver(self, model, message): - pass + def deliver(self, model, event): + """Delivers the event to the recipient - def init_persistent_state(self, model): - pass + Parameters + ---------- + model: + The model + event: MCOEvent + The event to notify. + """ diff --git a/force_bdss/notification_listeners/base_notification_listener_factory.py b/force_bdss/notification_listeners/base_notification_listener_factory.py index ffbe464..08e2b59 100644 --- a/force_bdss/notification_listeners/base_notification_listener_factory.py +++ b/force_bdss/notification_listeners/base_notification_listener_factory.py @@ -1,6 +1,6 @@ import abc -from traits.api import ABCHasStrictTraits, Instance, String, provides, Any +from traits.api import ABCHasStrictTraits, Instance, String, provides from envisage.plugin import Plugin from .i_notification_listener_factory import INotificationListenerFactory @@ -8,14 +8,19 @@ from .i_notification_listener_factory import INotificationListenerFactory @provides(INotificationListenerFactory) class BaseNotificationListenerFactory(ABCHasStrictTraits): + """Base class for notification listeners. + Notification listeners are extensions that receive event notifications + from the MCO and perform an associated action. + """ + #: identifier of the factory id = String() + #: Name of the factory. User friendly for UI name = String() + #: A reference to the containing plugin plugin = Instance(Plugin) - persistent_state = Any() - def __init__(self, plugin, *args, **kwargs): """Initializes the instance. @@ -29,8 +34,17 @@ class BaseNotificationListenerFactory(ABCHasStrictTraits): @abc.abstractmethod def create_listener(self): - """""" + """ + Creates an instance of the listener. + """ @abc.abstractmethod def create_model(self, model_data=None): - """""" + """ + Creates an instance of the model. + + Parameters + ---------- + model_data: dict + Data to use to fill the model. + """ diff --git a/force_bdss/notification_listeners/i_notification_listener_factory.py b/force_bdss/notification_listeners/i_notification_listener_factory.py index a269f8c..c4240d8 100644 --- a/force_bdss/notification_listeners/i_notification_listener_factory.py +++ b/force_bdss/notification_listeners/i_notification_listener_factory.py @@ -1,4 +1,4 @@ -from traits.api import Interface, String, Instance, Any +from traits.api import Interface, String, Instance from envisage.plugin import Plugin @@ -6,7 +6,7 @@ class INotificationListenerFactory(Interface): """Envisage required interface for the BaseNotificationListenerFactory. You should not need to use this directly. - Refer to the BaseNotifier for documentation. + Refer to the BaseNotificationListenerFactory for documentation. """ id = String() @@ -14,13 +14,8 @@ class INotificationListenerFactory(Interface): plugin = Instance(Plugin) - persistent_state = Any - def create_listener(self): """""" def create_model(self, model_data=None): """""" - - def init_persistent_state(self): - pass -- GitLab