Example #1
0
    def call_method(self, method, *args, **kwargs):
        """Call a method."""
        # XXX: limiting the recusion depth needs more thought
        if len(self._method_calls) > 5:
            raise RuntimeError("recursion level too deep")
        message = jsonrpc.create_request(method, args)
        self.send_message(message)
        replies = []

        def method_response(message, client):
            replies.append(message)

        def method_timeout():
            reply = jsonrpc.create_error(message, jsonrpc.SERVER_ERROR, "Method call timed out")
            replies.append(reply)

        timeout = kwargs.pop("timeout", self.timeout)
        if timeout:
            timer = QTimer(self)
            timer.setInterval(timeout * 1000)
            timer.setSingleShot(True)
            timer.timeout.connect(method_timeout)
            timer.start()
        # Run an embedded event loop to process network events until we get a
        # response. We limit the call depth so that we don't run the risk of
        # overflowing the stack.
        self._method_calls[message["id"]] = method_response
        loop = QEventLoop()
        mask = QEventLoop.ExcludeUserInputEvents | QEventLoop.WaitForMoreEvents
        while True:
            loop.processEvents(mask)
            if replies:
                break
        if timeout:
            timer.stop()
        reply = replies[0]
        del self._method_calls[message["id"]]
        if reply.get("error"):
            raise QJsonRpcError(reply["error"])
        self.message = reply
        return reply.get("result")