def call_method(self, ident, params):
        # TODO timeout for reply

        if __debug__:
            self.log.debug("%s method ident=%r obj=%r method=%r req_id=%r" %
                   (params["command"], ident, params["object"], params["method"],
                   b2a_hex(params["req_id"])))

        has_signal_attr = True  # implicit is no reply on exception
        try:
            objname = params["object"]
            try:
                instance = self.instances[objname]
            except KeyError:
                raise NoInstanceError(objname)

            try:
                method = getattr(instance, params["method"])
            except KeyError:
                raise NoMethodError(params["method"])

            has_signal_attr = hasattr(method, METHOD_RPC_AS_SIGNAL_ATTR)
            if ((params["command"] == "signal" and not has_signal_attr) or
                (params["command"] == "call" or has_signal_attr)):
                warnings.warn("wrong command match for %r" % method,
                              SignalCallWarning)

            ret = method(*params["args"], **params["kwargs"])

            # signals have no return value
            if params["command"] == "call":
                self.send_return(ident, params["req_id"], ret)
        except Exception as exc:
            if self.transfer_exceptions and not has_signal_attr:
                self.send_exception(ident, params["req_id"], exc)
            else:
                raise

    ######################################################
dataset/ETHPy150Open dsiroky/snakemq/snakemq/rpc.py/RpcServer.call_method/operator `and` -> `or`