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")