Exemple #1
0
 def test_hello_good_input(self):
     q = Queue()
     request = Post(id=44,
                    path=["hello_block", "greet"],
                    parameters=dict(name="thing"))
     request.set_callback(q.put)
     self.controller.handle_request(request)
     response = q.get(timeout=1.0)
     self.assertIsInstance(response, Return)
     assert response.id == 44
     assert response.value == "Hello thing"
    def rpc(self, pv, op):
        # type: (SharedPV, ServerOperation) -> None
        value = op.value()
        if value.getID() == "epics:nt/NTURI:1.0":
            # We got an NTURI, get path from path and parameters from query
            assert value.scheme == "pva", \
                "Can only handle NTURI with scheme=pva"
            prefix = self.controller.mri + "."
            assert value.path.startswith(prefix), \
                "NTURI path '%s' doesn't start with '%s'" % (value.path, prefix)
            method = value.path[len(prefix):]
            parameters = convert_value_to_dict(value.query)
        else:
            # We got something else, take path from pvRequest method and our mri
            # and parameters from the full value
            if self.field is not None:
                # We already know the method name
                method = self.field
            else:
                # Get the path and string "value" from the put value
                method = op.pvRequest().get("method")
                assert method, "No 'method' in pvRequest:\n%s" % op.pvRequest()
            parameters = convert_value_to_dict(value)
        path = [self.controller.mri, method]
        view = self.controller.block_view()[method]
        assert isinstance(view, Method), \
            "%s.%s is not a Method so cannot do RPC" % tuple(path)
        add_wrapper = method_return_unpacked() in view.tags

        post = Post(path=path, parameters=parameters)

        def handle_post_response(response):
            # type: (Response) -> None
            if isinstance(response, Return):
                if add_wrapper:
                    # Method gave us return unpacked (bare string or other type)
                    # so we must wrap it in a structure to send it
                    ret = {"return": response.value}
                else:
                    ret = response.value
                serialized = serialize_object(ret)
                v = convert_dict_to_value(serialized)
                op.done(v)
            else:
                if isinstance(response, Error):
                    message = stringify_error(response.message)
                else:
                    message = "BadResponse: %s" % response.to_dict()
                op.done(error=message)

        post.set_callback(handle_post_response)
        self.controller.handle_request(post).get()
Exemple #3
0
 def test_concurrent(self):
     q = Queue()
     request = Post(id=44,
                    path=["hello_block", "greet"],
                    parameters=dict(name="me", sleep=1))
     request.set_callback(q.put)
     self.controller.handle_request(request)
     request = Post(id=45, path=["hello_block", "error"])
     request.set_callback(q.put)
     self.controller.handle_request(request)
     response = q.get(timeout=1.0)
     self.assertIsInstance(response, Error)
     assert response.id == 45
     response = q.get(timeout=3.0)
     self.assertIsInstance(response, Return)
     assert response.id == 44
     assert response.value == "Hello me"
Exemple #4
0
 def test_counter_subscribe(self):
     q = Queue()
     # Subscribe to the value
     sub = Subscribe(id=20, path=["counting", "counter"], delta=False)
     sub.set_callback(q.put)
     self.controller.handle_request(sub)
     # Check initial return
     response = q.get(timeout=1.0)
     self.assertIsInstance(response, Update)
     assert response.id == 20
     assert response.value["typeid"] == "epics:nt/NTScalar:1.0"
     assert response.value["value"] == 0
     # Post increment()
     post = Post(id=21, path=["counting", "increment"])
     post.set_callback(q.put)
     self.controller.handle_request(post)
     # Check the value updates...
     response = q.get(timeout=1)
     self.assertIsInstance(response, Update)
     assert response.id == 20
     assert response.value["value"] == 1
     # ... then we get the return
     response = q.get(timeout=1)
     self.assertIsInstance(response, Return)
     assert response.id == 21
     assert response.value is None
     # Check we can put too
     put = Put(id=22, path=["counting", "counter", "value"], value=31)
     put.set_callback(q.put)
     self.controller.handle_request(put)
     # Check the value updates...
     response = q.get(timeout=1)
     self.assertIsInstance(response, Update)
     assert response.id == 20
     assert response.value["value"] == 31
     # ... then we get the return
     response = q.get(timeout=1)
     self.assertIsInstance(response, Return)
     assert response.id == 22
     assert response.value is None
     # And that there isn't anything else
     with self.assertRaises(TimeoutError):
         q.get(timeout=0.05)
Exemple #5
0
    def send_post(self, mri, method_name, **params):
        """Abstract method to dispatch a Post to the server

        Args:
            mri (str): The mri of the Block
            method_name (str): The name of the Method within the Block
            params: The parameters to send

        Returns:
            The return results from the server
        """
        q = Queue()
        request = Post(path=[mri, method_name], parameters=params)
        request.set_callback(q.put)
        IOLoopHelper.call(self._send_request, request)
        response = q.get()
        if isinstance(response, Error):
            raise response.message
        else:
            return response.value
Exemple #6
0
    def rpc(self, pv: SharedPV, op: ServerOperation) -> None:
        value = op.value()
        if value.getID() == "epics:nt/NTURI:1.0":
            # We got an NTURI, get path from path and parameters from query
            assert value.scheme == "pva", "Can only handle NTURI with scheme=pva"
            prefix = self.controller.mri + "."
            assert value.path.startswith(
                prefix
            ), f"NTURI path '{value.path}' doesn't start with '{prefix}'"
            method = value.path[len(prefix):]
            parameters = convert_value_to_dict(value.query)
        else:
            # We got something else, take path from pvRequest method and our mri
            # and parameters from the full value
            if self.field is not None:
                # We already know the method name
                method = self.field
            else:
                # Get the path and string "value" from the put value
                method = op.pvRequest().get("method")
                assert method, f"No 'method' in pvRequest:\n{op.pvRequest()}"
            parameters = convert_value_to_dict(value)
        path = [self.controller.mri, method]
        view = self.controller.block_view()[method]
        assert isinstance(
            view,
            Method), "%s.%s is not a Method so cannot do RPC" % tuple(path)
        add_wrapper = method_return_unpacked() in view.meta.tags

        self.controller.log.debug(
            f"{self.controller.mri}: RPC method {method} called with "
            f"params {parameters}")
        post = Post(path=path, parameters=parameters)

        def handle_post_response(response: Response) -> None:
            if isinstance(response, Return):
                ret: Any
                if add_wrapper:
                    # Method gave us return unpacked (bare string or other type)
                    # so we must wrap it in a structure to send it
                    ret = {"return": response.value}
                else:
                    ret = response.value
                v = convert_dict_to_value(ret)
                if ret:
                    self.controller.log.debug(
                        f"{self.controller.mri}: RPC method {method} returned with "
                        f"value {ret}")
                else:
                    self.controller.log.debug(
                        f"{self.controller.mri}: RPC method {method} returned")
                op.done(v)
            else:
                if isinstance(response, Error):
                    message = stringify_error(response.message)
                    self.controller.log.debug(
                        f"{self.controller.mri}: RPC method {method} resulted in "
                        f"error ({message})")
                else:
                    message = f"BadResponse: {response.to_dict()}"
                    self.controller.log.debug(
                        f"{self.controller.mri}: RPC method {method} got a bad "
                        f"response ({message})")
                op.done(error=message)

        post.set_callback(handle_post_response)
        self.controller.handle_request(post).get()