Ejemplo n.º 1
0
 def _subscribe_to_block(self, block_name):
     self.client_comms = self.process.get_client_comms(block_name)
     assert self.client_comms, \
         "Process doesn't know about block %s" % block_name
     request = Subscribe(None, self, [block_name], delta=True)
     request.set_id(self.BLOCK_ID)
     self.client_comms.q.put(request)
Ejemplo n.º 2
0
    def subscribe(self, attr, callback, *args):
        """Subscribe to changes in a given attribute and call
        ``callback(value, *args)`` when it changes

            Returns:
                int: an id for the subscription
        """
        assert isinstance(attr, Attribute), \
            "Expected Attribute, got %r" % (attr,)

        endpoint = attr.process_path + ["value"]
        self.log_debug("Subscribing to %s", endpoint)
        request = Subscribe(None, self.q, endpoint, False)
        # If self is in args, then make weak version of it
        saved_args = []
        for arg in args:
            if arg is self:
                saved_args.append(weakref.proxy(self))
            else:
                saved_args.append(arg)
        new_id = self._get_next_id()
        self._subscriptions[new_id] = (endpoint, callback, args)
        request.set_id(new_id)
        self.process.q.put(request)

        return new_id
Ejemplo n.º 3
0
    def test_unsubscribe(self):
        # Test that we remove the relevant subscription only and that
        # updates are no longer sent
        block = MagicMock(to_dict=MagicMock(return_value={
            "attr": "0",
            "inner": {
                "attr2": "other"
            }
        }))
        p = Process("proc", MagicMock())
        sub_1 = Subscribe(MagicMock(), MagicMock(), ["block"], False)
        sub_2 = Subscribe(MagicMock(), MagicMock(), ["block"], False)
        sub_1.set_id(1234)
        sub_2.set_id(4321)
        change_1 = BlockChanges([[["block", "attr"], "1"]])
        change_2 = BlockChanges([[["block", "attr"], "2"]])
        unsub_1 = Unsubscribe(MagicMock(), MagicMock())
        unsub_1.set_id(1234)

        p.q.get = MagicMock(side_effect=[
            sub_1, sub_2, change_1, unsub_1, change_2, PROCESS_STOP
        ])
        p._handle_block_add(BlockAdd(block, "block"))
        p.recv_loop()

        self.assertEqual([sub_2], p._subscriptions)
        self.assertEquals(1, len(unsub_1.response_queue.put.call_args_list))
        response = unsub_1.response_queue.put.call_args_list[0][0][0]
        self.assertIsNone(response.value)
        self.assertIs(unsub_1.context, response.context)

        sub_1_responses = sub_1.response_queue.put.call_args_list
        sub_2_responses = sub_2.response_queue.put.call_args_list
        self.assertEquals(2, len(sub_1_responses))
        self.assertEquals(3, len(sub_2_responses))
Ejemplo n.º 4
0
 def send_subscription(self):
     endpoints = [self._block]
     endpoints = endpoints + self.dict_to_path(self._request.toDict())
     self.log_debug("Endpoints: %s", endpoints)
     msg = Subscribe(response_queue=self._server.q, endpoint=endpoints, delta=True)
     msg.set_id(self._id)
     self._server.send_to_process(msg)
Ejemplo n.º 5
0
    def __init__(self, process, _=None):
        super(PvaServerComms, self).__init__(process)

        self.name = "PvaServerComms"
        self.set_logger_name(self.name)

        self._lock = RLock()

        self._current_id = 1
        self._root_id = 0
        self._blocklist = {}
        self._cache = Cache()

        self._server = None
        self._endpoints = {}
        self._cb = None

        self._rpcs = {}
        self._puts = {}
        self._dead_rpcs = []

        # Create the V4 PVA server object
        self.create_pva_server()

        # Add a thread for executing the V4 PVA server
        self.add_spawn_function(self.start_pva_server)

        # Set up the subscription for everything (root down)
        request = Subscribe(None, self.q, [], True)
        request.set_id(self._root_id)
        self.process.q.put(request)
Ejemplo n.º 6
0
    def subscribe(self, attr, callback, *args):
        """Subscribe to changes in a given attribute and call
        ``callback(value, *args)`` when it changes

            Returns:
                int: an id for the subscription
        """
        assert isinstance(attr, Attribute), \
            "Expected Attribute, got %r" % (attr,)

        endpoint = attr.process_path + ["value"]
        self.log_debug("Subscribing to %s", endpoint)
        request = Subscribe(None, self.q, endpoint, False)
        # If self is in args, then make weak version of it
        saved_args = []
        for arg in args:
            if arg is self:
                saved_args.append(weakref.proxy(self))
            else:
                saved_args.append(arg)
        new_id = self._get_next_id()
        self._subscriptions[new_id] = (endpoint, callback, args)
        request.set_id(new_id)
        self.process.q.put(request)

        return new_id
Ejemplo n.º 7
0
 def do_initial_reset(self):
     self.state.set_value("Resetting")
     self.status.set_value("Waiting for connection...")
     self.busy.set_value(True)
     request = Subscribe(None, self,
                         [self.process.name, "remoteBlocks", "value"])
     request.set_id(self.REMOTE_BLOCKS_ID)
     self.process.q.put(request)
Ejemplo n.º 8
0
 def send_subscription(self):
     endpoints = [self._block]
     endpoints = endpoints + self.dict_to_path(self._request.toDict())
     self.log_debug("Endpoints: %s", endpoints)
     msg = Subscribe(response_queue=self._server.q,
                     endpoint=endpoints,
                     delta=True)
     msg.set_id(self._id)
     self._server.send_to_process(msg)
Ejemplo n.º 9
0
    def subscribe(self, attr, callback, *args):
        """Subscribe to changes in a given attribute and call callback
        with (\*args) when it changes

            Returns:
                int: an id for the subscription
        """

        endpoint = [attr.parent.name, attr.name]
        request = Subscribe(None, self.q, endpoint, False)
        new_id = self._save_subscription(endpoint, callback, *args)
        request.set_id(new_id)
        self.process.q.put(request)

        return new_id
Ejemplo n.º 10
0
    def subscribe(self, attr, callback, *args):
        """Subscribe to changes in a given attribute and call
        ``callback(value, *args)`` when it changes

            Returns:
                int: an id for the subscription
        """
        assert isinstance(attr, Attribute), \
            "Expected Attribute, got %r" % (attr,)

        endpoint = attr.path_relative_to(self.process) + ["value"]
        self.log_debug("Subscribing to %s", endpoint)
        request = Subscribe(None, self.q, endpoint, False)
        new_id = self._save_subscription(endpoint, callback, *args)
        request.set_id(new_id)
        self.process.q.put(request)

        return new_id
Ejemplo n.º 11
0
 def test_send_subscribe_to_server(self):
     self.PVA = PvaClientComms(self.p)
     self.PVA.send_to_caller = MagicMock()
     request = Subscribe(endpoint=["ep1", "ep2"])
     request.set_id(1)
     self.PVA.send_to_server(request)
     pvaccess.Channel.assert_called_once()
     self.ch.subscribe.assert_called_once()
     self.ch.startMonitor.assert_called_once()
     mon = self.PVA._monitors[1]
     mon_val = MagicMock()
     mon_val.toDict = MagicMock(return_value={'typeid': 'malcolm:core/Error:1.0', 'message': 'test error'})
     self.PVA.send_to_caller.reset_mock()
     mon.monitor_update(mon_val)
     self.PVA.send_to_caller.assert_called_once()
     self.PVA.send_to_caller.reset_mock()
     mon_val = MagicMock()
     mon_val.toDict = MagicMock(return_value={'typeid': 'malcolm:core/Update:1.0'})
     mon.monitor_update(mon_val)
     self.PVA.send_to_caller.assert_called_once()
Ejemplo n.º 12
0
    def __init__(self, process, _=None):
        super(PvaServerComms, self).__init__(process)

        self.name = "PvaServerComms"
        self.set_logger_name(self.name)

        self._lock = RLock()

        self._current_id = 1
        self._root_id = 0
        self._local_block_list = {}
        self._local_block_id = self._get_unique_id()
        self._remote_block_list = {}
        self._remote_block_id = self._get_unique_id()

        self._server = None
        self._endpoints = {}
        self._cb = None

        self._gets = {}
        self._rpcs = {}
        self._puts = {}
        self._monitors = {}
        self._dead_rpcs = []

        # Create the V4 PVA server object
        self.create_pva_server()

        # Add a thread for executing the V4 PVA server
        self.add_spawn_function(self.start_pva_server)
        self.log_debug("Process name: %s", process.name)
        # Set up the subscription for local blocks
        request = Subscribe(None, self.q, [process.name, 'blocks', 'value'],
                            False)
        request.set_id(self._local_block_id)
        self.process.q.put(request)
        # Set up the subscription for remote blocks
        request = Subscribe(None, self.q,
                            [process.name, 'remoteBlocks', 'value'], False)
        request.set_id(self._remote_block_id)
        self.process.q.put(request)
Ejemplo n.º 13
0
    def __init__(self, process, _=None):
        super(PvaServerComms, self).__init__(process)

        self.name = "PvaServerComms"
        self.set_logger_name(self.name)

        self._lock = RLock()

        self._current_id = 1
        self._root_id = 0
        self._local_block_list = {}
        self._local_block_id = self._get_unique_id()
        self._remote_block_list = {}
        self._remote_block_id = self._get_unique_id()

        self._server = None
        self._endpoints = {}
        self._cb = None

        self._gets = {}
        self._rpcs = {}
        self._puts = {}
        self._monitors = {}
        self._dead_rpcs = []

        # Create the V4 PVA server object
        self.create_pva_server()

        # Add a thread for executing the V4 PVA server
        self.add_spawn_function(self.start_pva_server)
        self.log_debug("Process name: %s", process.name)
        # Set up the subscription for local blocks
        request = Subscribe(None, self.q, [process.name, 'blocks', 'value'], False)
        request.set_id(self._local_block_id)
        self.process.q.put(request)
        # Set up the subscription for remote blocks
        request = Subscribe(None, self.q, [process.name, 'remoteBlocks', 'value'], False)
        request.set_id(self._remote_block_id)
        self.process.q.put(request)
Ejemplo n.º 14
0
    def test_unsubscribe(self):
        # Test that we remove the relevant subscription only and that
        # updates are no longer sent
        block = MagicMock(to_dict=MagicMock(return_value={
            "attr": "0",
            "inner": {
                "attr2": "other"
            }
        }))
        p = Process("proc", MagicMock())
        sub_1 = Subscribe(MagicMock(), MagicMock(), ["block"], False)
        sub_1.response_queue.qsize.return_value = 0
        sub_2 = Subscribe(MagicMock(), MagicMock(), ["block"], False)
        sub_2.response_queue.qsize.return_value = 0
        sub_1.set_id(1234)
        sub_2.set_id(1234)
        change_1 = BlockChanges([[["block", "attr"], "1"]])
        change_2 = BlockChanges([[["block", "attr"], "2"]])
        unsub_1 = Unsubscribe(sub_1.context, sub_1.response_queue)
        unsub_1.set_id(sub_1.id)

        p.q.get = MagicMock(side_effect=[
            sub_1, sub_2, change_1, unsub_1, change_2, PROCESS_STOP
        ])
        p._handle_block_add(BlockAdd(block, "block", None))
        p.recv_loop()

        self.assertEqual([sub_2], list(p._subscriptions.values()))

        sub_1_responses = sub_1.response_queue.put.call_args_list
        sub_2_responses = sub_2.response_queue.put.call_args_list
        self.assertEquals(3, len(sub_1_responses))
        self.assertEquals(sub_1_responses[0][0][0].value["attr"], "0")
        self.assertEquals(sub_1_responses[1][0][0].value["attr"], "1")
        self.assertIsInstance(sub_1_responses[2][0][0], Return)
        self.assertEquals(3, len(sub_2_responses))
        self.assertEquals(sub_2_responses[0][0][0].value["attr"], "0")
        self.assertEquals(sub_2_responses[1][0][0].value["attr"], "1")
        self.assertEquals(sub_2_responses[2][0][0].value["attr"], "2")
Ejemplo n.º 15
0
    def test_unsubscribe(self):
        # Test that we remove the relevant subscription only and that
        # updates are no longer sent
        block = MagicMock(
            to_dict=MagicMock(
                return_value={"attr": "0", "inner": {"attr2": "other"}}))
        p = Process("proc", MagicMock())
        sub_1 = Subscribe(
            MagicMock(), MagicMock(), ["block"], False)
        sub_1.response_queue.qsize.return_value = 0
        sub_2 = Subscribe(
            MagicMock(), MagicMock(), ["block"], False)
        sub_2.response_queue.qsize.return_value = 0
        sub_1.set_id(1234)
        sub_2.set_id(1234)
        change_1 = BlockChanges([[["block", "attr"], "1"]])
        change_2 = BlockChanges([[["block", "attr"], "2"]])
        unsub_1 = Unsubscribe(sub_1.context, sub_1.response_queue)
        unsub_1.set_id(sub_1.id)

        p.q.get = MagicMock(side_effect=[sub_1, sub_2, change_1,
                                         unsub_1, change_2, PROCESS_STOP])
        p._handle_block_add(BlockAdd(block, "block", None))
        p.recv_loop()

        self.assertEqual([sub_2], list(p._subscriptions.values()))

        sub_1_responses = sub_1.response_queue.put.call_args_list
        sub_2_responses = sub_2.response_queue.put.call_args_list
        self.assertEquals(3, len(sub_1_responses))
        self.assertEquals(sub_1_responses[0][0][0].value["attr"], "0")
        self.assertEquals(sub_1_responses[1][0][0].value["attr"], "1")
        self.assertIsInstance(sub_1_responses[2][0][0], Return)
        self.assertEquals(3, len(sub_2_responses))
        self.assertEquals(sub_2_responses[0][0][0].value["attr"], "0")
        self.assertEquals(sub_2_responses[1][0][0].value["attr"], "1")
        self.assertEquals(sub_2_responses[2][0][0].value["attr"], "2")
Ejemplo n.º 16
0
 def test_send_subscribe_to_server(self):
     self.PVA = PvaClientComms(self.p)
     self.PVA.send_to_caller = MagicMock()
     request = Subscribe(endpoint=["ep1", "ep2"])
     request.set_id(1)
     self.PVA.send_to_server(request)
     pvaccess.Channel.assert_called_once()
     self.ch.subscribe.assert_called_once()
     self.ch.startMonitor.assert_called_once()
     mon = self.PVA._monitors[1]
     mon_val = MagicMock()
     mon_val.toDict = MagicMock(return_value={
         'typeid': 'malcolm:core/Error:1.0',
         'message': 'test error'
     })
     self.PVA.send_to_caller.reset_mock()
     mon.monitor_update(mon_val)
     self.PVA.send_to_caller.assert_called_once()
     self.PVA.send_to_caller.reset_mock()
     mon_val = MagicMock()
     mon_val.toDict = MagicMock(
         return_value={'typeid': 'malcolm:core/Update:1.0'})
     mon.monitor_update(mon_val)
     self.PVA.send_to_caller.assert_called_once()
Ejemplo n.º 17
0
class TestSubscribe(unittest.TestCase):
    def setUp(self):
        self.callback = MagicMock()
        self.path = ["BL18I:XSPRESS3"]
        self.delta = True
        self.o = Subscribe(11, self.path, self.delta, self.callback)

    def test_init(self):
        assert self.o.typeid == "malcolm:core/Subscribe:1.0"
        assert self.o.id == 11
        assert self.o.callback == self.callback
        assert self.path == self.o.path
        assert self.delta == self.o.delta

    def test_respond_with_update(self):
        cb, response = self.o.update_response(value=5)
        assert cb == self.callback
        assert response == Update(id=11, value=5)

    def test_respond_with_delta(self):
        changes = [[["path"], "value"]]
        cb, response = self.o.delta_response(changes)
        assert cb == self.callback
        assert response == Delta(id=11, changes=changes)

    def test_setters(self):
        self.o.set_delta(False)
        assert not self.o.delta
        self.o.set_path(["BL18I:XSPRESS3", "state", "value"])
        self.o.set_id(19)
        d = self.o.to_dict()
        del d["delta"]
        assert get_doc_json("subscribe_xspress3_state_value") == d

    def test_doc(self):
        assert get_doc_json("subscribe_xspress3") == self.o.to_dict()
Ejemplo n.º 18
0
    def test_partial_structure_subscriptions(self):
        block_1 = MagicMock(to_dict=MagicMock(return_value={
            "attr": "value",
            "inner": {
                "attr2": "value"
            }
        }))
        block_2 = MagicMock(to_dict=MagicMock(return_value={"attr": "value"}))

        sub_1 = Subscribe(None, MagicMock(), ["block_1", "inner"], delta=False)
        sub_1.set_id(1)
        sub_1.response_queue.qsize.return_value = 0

        sub_2 = Subscribe(None, MagicMock(), ["block_1"], delta=True)
        sub_2.set_id(2)
        sub_2.response_queue.qsize.return_value = 0

        sub_3 = Subscribe(None,
                          MagicMock(), ["block_1", "inner", "attr2"],
                          delta=False)
        sub_3.set_id(3)
        sub_3.response_queue.qsize.return_value = 0

        changes_1 = [[["block_1", "inner", "attr2"], "new_value"],
                     [["block_1", "attr"], "new_value"]]
        changes_2 = [[["block_2", "attr"], "block_2_value"]]
        request_1 = BlockChanges(changes_1)
        request_2 = BlockChanges(changes_2)
        p = Process("proc", MagicMock())
        p.q.get = MagicMock(side_effect=[
            sub_1, sub_2, sub_3, request_1, request_2, PROCESS_STOP
        ])

        p._handle_block_add(BlockAdd(block_1, "block_1", None))
        p._handle_block_add(BlockAdd(block_2, "block_2", None))
        p.recv_loop()

        response_1 = sub_1.response_queue.put.call_args_list[1][0][0]["value"]
        self.assertEquals({"attr2": "new_value"}, response_1)

        response_2 = sub_2.response_queue.put.call_args_list[1][0][0][
            "changes"]
        self.assertEquals(
            [[["inner", "attr2"], "new_value"], [["attr"], "new_value"]],
            response_2)

        response_3 = sub_3.response_queue.put.call_args_list[1][0][0]["value"]
        self.assertEquals("new_value", response_3)
Ejemplo n.º 19
0
    def test_partial_structure_subscriptions(self):
        block_1 = MagicMock(
            to_dict=MagicMock(
                return_value={"attr": "value", "inner": {"attr2": "value"}}))
        block_2 = MagicMock(
            to_dict=MagicMock(return_value={"attr": "value"}))

        sub_1 = Subscribe(None, MagicMock(), ["block_1", "inner"], delta=False)
        sub_1.set_id(1)
        sub_1.response_queue.qsize.return_value = 0

        sub_2 = Subscribe(None, MagicMock(), ["block_1"], delta=True)
        sub_2.set_id(2)
        sub_2.response_queue.qsize.return_value = 0

        sub_3 = Subscribe(None, MagicMock(), ["block_1", "inner", "attr2"],
                          delta=False)
        sub_3.set_id(3)
        sub_3.response_queue.qsize.return_value = 0

        changes_1 = [[["block_1", "inner", "attr2"], "new_value"],
                     [["block_1", "attr"], "new_value"]]
        changes_2 = [[["block_2", "attr"], "block_2_value"]]
        request_1 = BlockChanges(changes_1)
        request_2 = BlockChanges(changes_2)
        p = Process("proc", MagicMock())
        p.q.get = MagicMock(side_effect=[
            sub_1, sub_2, sub_3, request_1, request_2,
            PROCESS_STOP])

        p._handle_block_add(BlockAdd(block_1, "block_1", None))
        p._handle_block_add(BlockAdd(block_2, "block_2", None))
        p.recv_loop()

        response_1 = sub_1.response_queue.put.call_args_list[1][0][0]["value"]
        self.assertEquals({"attr2": "new_value"}, response_1)

        response_2 = sub_2.response_queue.put.call_args_list[1][0][0]["changes"]
        self.assertEquals([[["inner", "attr2"], "new_value"],
                           [["attr"], "new_value"]], response_2)

        response_3 = sub_3.response_queue.put.call_args_list[1][0][0]["value"]
        self.assertEquals("new_value", response_3)
Ejemplo n.º 20
0
 def subscribe_server_blocks(self, _):
     """Subscribe to process blocks"""
     request = Subscribe(None, None, [".", "blocks", "value"])
     request.set_id(self.SERVER_BLOCKS_ID)
     self.loop.add_callback(self.send_to_server, request)
Ejemplo n.º 21
0
 def subscribe_server_blocks(self, _):
     """Subscribe to process blocks"""
     request = Subscribe(None, None, [".", "blocks", "value"])
     request.set_id(self.SERVER_BLOCKS_ID)
     self.loop.add_callback(self.send_to_server, request)