Skip to content
Snippets Groups Projects
Commit 53bcc702 authored by Stefano Borini's avatar Stefano Borini Committed by GitHub
Browse files

Merge pull request #84 from force-h2020/move-ui-notification

Removed UI notification plugin, moved to UI.
parents ad83b56f c8ef4f36
No related branches found
No related tags found
No related merge requests found
Showing
with 0 additions and 377 deletions
...@@ -2,7 +2,6 @@ from force_bdss.api import BaseExtensionPlugin, plugin_id ...@@ -2,7 +2,6 @@ from force_bdss.api import BaseExtensionPlugin, plugin_id
from .dummy_notification_listener.dummy_notification_listener_factory import ( from .dummy_notification_listener.dummy_notification_listener_factory import (
DummyNotificationListenerFactory DummyNotificationListenerFactory
) )
from .ui_notification.ui_notification_factory import UINotificationFactory
from .csv_extractor.csv_extractor_factory import CSVExtractorFactory from .csv_extractor.csv_extractor_factory import CSVExtractorFactory
from .kpi_adder.kpi_adder_factory import KPIAdderFactory from .kpi_adder.kpi_adder_factory import KPIAdderFactory
from .dummy_dakota.dakota_factory import DummyDakotaFactory from .dummy_dakota.dakota_factory import DummyDakotaFactory
...@@ -28,5 +27,4 @@ class DummyPlugin(BaseExtensionPlugin): ...@@ -28,5 +27,4 @@ class DummyPlugin(BaseExtensionPlugin):
def _notification_listener_factories_default(self): def _notification_listener_factories_default(self):
return [DummyNotificationListenerFactory(self), return [DummyNotificationListenerFactory(self),
UINotificationFactory(self)
] ]
import unittest
from testfixtures import LogCapture
from force_bdss.core_plugins.dummy.ui_notification.ui_notification import \
UINotification
from force_bdss.core_plugins.dummy.ui_notification.ui_notification_factory \
import \
UINotificationFactory
from force_bdss.core_plugins.dummy.ui_notification.ui_notification_model \
import \
UINotificationModel
from force_bdss.mco.events import MCOStartEvent, MCOProgressEvent, \
MCOFinishEvent
try:
import mock
except ImportError:
from unittest import mock
import zmq
class TestUINotification(unittest.TestCase):
def setUp(self):
factory = mock.Mock(spec=UINotificationFactory)
self.model = UINotificationModel(factory)
self.model.identifier = "an_id"
listener = UINotification(factory)
self.sync_socket = mock.Mock(spec=zmq.Socket)
self.sync_socket.recv_string = mock.Mock()
self.sync_socket.recv_string.side_effect = [
"HELLO\nan_id\n1",
"GOODBYE\nan_id\n1"
]
self.pub_socket = mock.Mock(spec=zmq.Socket)
self.context = mock.Mock(spec=zmq.Context)
self.context.socket.side_effect = [self.pub_socket,
self.sync_socket]
listener.__class__._create_context = mock.Mock(
return_value=self.context)
self.listener = listener
def test_deliver(self):
listener = self.listener
listener.initialize(self.model)
self.assertEqual(
self.sync_socket.send_string.call_args[0][0],
'HELLO\nan_id\n1')
listener.deliver(MCOStartEvent())
self.assertEqual(
self.pub_socket.send_string.call_args[0][0],
'EVENT\nan_id\nMCO_START')
listener.deliver(MCOProgressEvent(input=(1, 2, 3), output=(4, 5)))
self.assertEqual(
self.pub_socket.send_string.call_args[0][0],
'EVENT\nan_id\nMCO_PROGRESS\n1 2 3\n4 5')
listener.deliver(MCOFinishEvent())
self.assertEqual(
self.pub_socket.send_string.call_args[0][0],
'EVENT\nan_id\nMCO_FINISH')
def test_finalize(self):
listener = self.listener
listener.initialize(self.model)
listener.finalize()
self.assertTrue(self.context.term.called)
self.assertTrue(self.sync_socket.close.called)
self.assertTrue(self.pub_socket.close.called)
self.assertIsNone(listener._context)
self.assertIsNone(listener._sync_socket)
self.assertIsNone(listener._pub_socket)
def test_initialize(self):
listener = self.listener
listener.initialize(self.model)
self.assertEqual(
self.sync_socket.send_string.call_args[0][0],
'HELLO\nan_id\n1')
def test_polling(self):
self.sync_socket.poll.return_value = 0
listener = self.listener
with LogCapture() as capture:
listener.initialize(self.model)
capture.check(
("force_bdss.core_plugins.dummy.ui_notification.ui_notification", # noqa
"INFO",
"Could not connect to UI server after 1000 ms. Continuing without UI notification." # noqa
),
)
self.assertIsNone(listener._context)
def test_wrong_init_recv_string(self):
listener = self.listener
self.sync_socket.recv_string.side_effect = [
"HELLO\nnot_the_right_id\n1",
"GOODBYE\nan_id\n1"
]
with LogCapture() as capture:
listener.initialize(self.model)
capture.check(
("force_bdss.core_plugins.dummy.ui_notification.ui_notification", # noqa
"ERROR",
"Unexpected reply in sync negotiation with UI server. "
"'HELLO\nnot_the_right_id\n1'" # noqa
),
)
self.assertIsNone(listener._context)
def test_deliver_without_context(self):
self.listener.deliver(MCOStartEvent())
self.assertFalse(self.pub_socket.send_string.called)
def test_finalize_without_context(self):
self.listener.finalize()
self.assertFalse(self.sync_socket.send_string.called)
def test_finalize_no_response(self):
self.sync_socket.poll.side_effect = [1, 0]
listener = self.listener
listener.initialize(self.model)
with LogCapture() as capture:
listener.finalize()
capture.check(
("force_bdss.core_plugins.dummy.ui_notification.ui_notification", # noqa
"INFO",
"Could not close connection to UI server after 1000 ms." # noqa
),
)
self.assertIsNone(listener._context)
def test_wrong_finalize_recv_string(self):
listener = self.listener
self.sync_socket.poll.side_effect = [1, 1]
self.sync_socket.recv_string.side_effect = [
"HELLO\nan_id\n1",
"GOODBYE\nnot_the_right_id\n1"
]
listener.initialize(self.model)
with LogCapture() as capture:
listener.finalize()
capture.check(
("force_bdss.core_plugins.dummy.ui_notification.ui_notification", # noqa
"ERROR",
"Unexpected reply in goodbye sync negotiation with UI server. " # noqa
"'GOODBYE\nnot_the_right_id\n1'" # noqa
),
)
self.assertIsNone(listener._context)
import unittest
from envisage.plugin import Plugin
from force_bdss.core_plugins.dummy.ui_notification.ui_notification import \
UINotification
from force_bdss.core_plugins.dummy.ui_notification.ui_notification_factory \
import \
UINotificationFactory
from force_bdss.core_plugins.dummy.ui_notification.ui_notification_model \
import \
UINotificationModel
try:
import mock
except ImportError:
from unittest import mock
class TestUINotificationFactory(unittest.TestCase):
def test_initialization(self):
factory = UINotificationFactory(mock.Mock(spec=Plugin))
self.assertEqual(
factory.id,
"force.bdss.enthought.factory.ui_notification")
def test_create_model(self):
factory = UINotificationFactory(mock.Mock(spec=Plugin))
model = factory.create_model()
self.assertIsInstance(model, UINotificationModel)
self.assertEqual(model.factory, factory)
model = factory.create_model({})
self.assertIsInstance(model, UINotificationModel)
self.assertEqual(model.factory, factory)
def test_create_listener(self):
factory = UINotificationFactory(mock.Mock(spec=Plugin))
listener = factory.create_listener()
self.assertIsInstance(listener, UINotification)
import logging
from traits.api import Instance, String
from force_bdss.api import (
BaseNotificationListener,
MCOStartEvent,
MCOFinishEvent,
MCOProgressEvent
)
import zmq
log = logging.getLogger(__name__)
class UINotification(BaseNotificationListener):
"""
Notification engine for the UI. Uses zeromq for the traffic handling.
"""
#: The ZMQ context. If None, it means that the service is unavailable.
_context = Instance(zmq.Context)
#: The pubsub socket.
_pub_socket = Instance(zmq.Socket)
#: The synchronization socket to communicate with the server (UI)
_sync_socket = Instance(zmq.Socket)
#: Unique identifier from the UI. To be returned in the protocol.
_identifier = String()
#: The protocol version that this plugin delivers
_proto_version = "1"
def initialize(self, model):
self._identifier = model.identifier
self._context = self._create_context()
self._pub_socket = self._context.socket(zmq.PUB)
self._pub_socket.setsockopt(zmq.LINGER, 0)
self._pub_socket.connect(model.pub_url)
self._sync_socket = self._context.socket(zmq.REQ)
self._sync_socket.setsockopt(zmq.LINGER, 0)
self._sync_socket.connect(model.sync_url)
msg = "HELLO\n{}\n{}".format(self._identifier, self._proto_version)
self._sync_socket.send_string(msg)
events = self._sync_socket.poll(1000, zmq.POLLIN)
if events == 0:
log.info("Could not connect to UI server after 1000 ms. "
"Continuing without UI notification.")
self._close_and_clear_sockets()
return
recv = self._sync_socket.recv_string()
if recv != msg:
log.error(
("Unexpected reply in sync"
" negotiation with UI server. '{}'".format(recv)))
self._close_and_clear_sockets()
return
def deliver(self, event):
if not self._context:
return
msg = _format_event(event, self._identifier)
if msg is not None:
self._pub_socket.send_string(msg)
def finalize(self):
if not self._context:
return
msg = "GOODBYE\n{}\n{}".format(self._identifier, self._proto_version)
self._sync_socket.send_string(msg)
events = self._sync_socket.poll(1000, zmq.POLLIN)
if events == 0:
log.info("Could not close connection to UI server after "
"1000 ms.")
self._close_and_clear_sockets()
return
recv = self._sync_socket.recv_string()
if recv != msg:
log.error(
("Unexpected reply in goodbye sync"
" negotiation with UI server. '{}'".format(recv)))
self._close_and_clear_sockets()
def _close_and_clear_sockets(self):
if self._pub_socket:
self._pub_socket.close()
if self._sync_socket:
self._sync_socket.close()
if self._context:
self._context.term()
self._pub_socket = None
self._sync_socket = None
self._context = None
def _create_context(self):
return zmq.Context()
def _format_event(event, identifier):
"""Converts the event into a byte sequence to be transferred via zmq"""
if isinstance(event, MCOStartEvent):
data = "MCO_START"
elif isinstance(event, MCOFinishEvent):
data = "MCO_FINISH"
elif isinstance(event, MCOProgressEvent):
data = "MCO_PROGRESS\n{}\n{}".format(
" ".join([str(x) for x in event.input]),
" ".join([str(x) for x in event.output]))
else:
return None
return "EVENT\n{}\n{}".format(identifier, data)
from traits.api import String
from force_bdss.api import factory_id, BaseNotificationListenerFactory
from .ui_notification import UINotification
from .ui_notification_model import UINotificationModel
class UINotificationFactory(BaseNotificationListenerFactory):
id = String(factory_id("enthought", "ui_notification"))
name = String("UI Notification")
def create_model(self, model_data=None):
if model_data is None:
model_data = {}
return UINotificationModel(self, **model_data)
def create_listener(self):
return UINotification(self)
from traits.api import String
from force_bdss.api import (
BaseNotificationListenerModel, ZMQSocketURL)
class UINotificationModel(BaseNotificationListenerModel):
#: The socket URL where the UI will be found. Synchronization port.
sync_url = ZMQSocketURL()
#: The socket URL where the UI will be found. PubSub port.
pub_url = ZMQSocketURL()
#: Unique identifier assigned by the UI to recognize the connection.
identifier = String()
...@@ -72,14 +72,6 @@ ...@@ -72,14 +72,6 @@
} }
], ],
"notification_listeners": [ "notification_listeners": [
{
"id": "force.bdss.enthought.factory.ui_notification",
"model_data": {
"sync_url": "tcp://127.0.0.1:12346",
"pub_url": "tcp://127.0.0.1:12345",
"identifier": "vfdjlkadfkljfsd"
}
}
] ]
} }
} }
...@@ -2,4 +2,3 @@ envisage==4.6.0 ...@@ -2,4 +2,3 @@ envisage==4.6.0
click==6.7 click==6.7
six==1.10.0 six==1.10.0
stevedore==1.24.0 stevedore==1.24.0
pyzmq==16.0.2
...@@ -38,6 +38,5 @@ setup( ...@@ -38,6 +38,5 @@ setup(
"click >= 6.7", "click >= 6.7",
"stevedore >= 1.24.0", "stevedore >= 1.24.0",
"six >= 1.10.0", "six >= 1.10.0",
"pyzmq >= 16.0.0"
] ]
) )
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment