Ejemplo n.º 1
0
    def enter_main_loop(self):
        """
        Wait for requests from the other side.

        The communication protocol for remote procedure calls is as follows:

        - Every request is a dictionary containing at least a ``command`` key
          with a string value (the name of the method to invoke).

        - The value of the optional ``arguments`` key gives a list of
          positional arguments to pass to the method.

        - The value of the optional ``keyword-arguments`` key gives a
          dictionary of keyword arguments to pass to the method.

        Responses are structured as follows:

        - Every response is a dictionary containing at least a ``success`` key
          with a boolean value.

        - If ``success=True`` the key ``result`` gives the return value of the
          method.

        - If ``success=False`` the key ``error`` gives a string explaining what
          went wrong.

        :raises: :py:exc:`ProtocolError` when the remote side violates the
                 defined protocol.
        """
        while True:
            request = self.read()
            method_name = request.get('method')
            method = getattr(self, method_name, None)
            args = request.get('args', [])
            kw = request.get('kw', {})
            if method and not method_name.startswith('_'):
                try:
                    logger.info("Remote is calling local method %s ..",
                                format_call(method_name, *args, **kw))
                    result = method(*args, **kw)
                    logger.info(
                        "Local method call was successful and returned result %r.",
                        result)
                    self.write(dict(success=True, result=result))
                except Exception as e:
                    logger.exception(
                        "Swallowing unexpected exception during local method call so we don't crash!"
                    )
                    self.write(dict(success=False, error=str(e)))
            else:
                logger.warning("Remote tried to call unsupported method %s!",
                               method_name)
                self.write(
                    dict(success=False,
                         error="Method %s not supported" % method_name))
Ejemplo n.º 2
0
    def enter_main_loop(self):
        """
        Wait for requests from the other side.

        The communication protocol for remote procedure calls is as follows:

        - Every request is a dictionary containing at least a ``command`` key
          with a string value (the name of the method to invoke).

        - The value of the optional ``arguments`` key gives a list of
          positional arguments to pass to the method.

        - The value of the optional ``keyword-arguments`` key gives a
          dictionary of keyword arguments to pass to the method.

        Responses are structured as follows:

        - Every response is a dictionary containing at least a ``success`` key
          with a boolean value.

        - If ``success=True`` the key ``result`` gives the return value of the
          method.

        - If ``success=False`` the key ``error`` gives a string explaining what
          went wrong.

        :raises: :exc:`ProtocolError` when the remote side violates the
                 defined protocol.
        """
        while True:
            request = self.read()
            method_name = request.get('method')
            method = getattr(self, method_name, None)
            args = request.get('args', [])
            kw = request.get('kw', {})
            if method and not method_name.startswith('_'):
                try:
                    logger.info("Remote is calling local method %s ..", format_call(method_name, *args, **kw))
                    result = method(*args, **kw)
                    logger.info("Local method call was successful and returned result %r.", result)
                    self.write(dict(success=True, result=result))
                except Exception as e:
                    logger.exception("Swallowing unexpected exception during local method call so we don't crash!")
                    self.write(dict(success=False, error=str(e)))
            else:
                logger.warning("Remote tried to call unsupported method %s!", method_name)
                self.write(dict(success=False, error="Method %s not supported" % method_name))
Ejemplo n.º 3
0
    def call_remote_method(self, method, *args, **kw):
        """
        Call a method on the remote object.

        :param method: The name of the method to call (a string).
        :param args: The positional arguments for the method.
        :param kw: The keyword arguments for the method.
        :returns: The return value of the remote method.
        """
        timer = Timer()
        logger.debug("Calling remote method %s ..", format_call(method, *args, **kw))
        self.write(dict(method=method, args=args, kw=kw))
        response = self.read()
        if response['success']:
            logger.debug("Remote method call succeeded in %s and returned %r!", timer, response['result'])
            return response['result']
        else:
            logger.warning("Remote method call failed after %s: %s", timer, response['error'])
            raise RemoteMethodFailed(response['error'])