def call(self, procedure, *args, **kwargs):
        if six.PY2 and type(procedure) == str:
            procedure = six.u(procedure)
        assert(isinstance(procedure, six.text_type))

        if not self._transport:
            raise exception.TransportLost()

        options = kwargs.pop('options', None)
        if options and not isinstance(options, types.CallOptions):
            raise Exception("options must be of type a.w.t.CallOptions")

        request_id = self._request_id_gen.next()

        encrypted_payload = None
        if self._keyring:
            encrypted_payload = self._keyring.encrypt(True, procedure, args, kwargs)

        if encrypted_payload:
            if options:
                msg = message.Call(request_id,
                                   procedure,
                                   payload=encrypted_payload.payload,
                                   enc_algo=encrypted_payload.algo,
                                   enc_key=encrypted_payload.pkey,
                                   enc_serializer=encrypted_payload.serializer,
                                   **options.message_attr())
            else:
                msg = message.Call(request_id,
                                   procedure,
                                   payload=encrypted_payload.payload,
                                   enc_algo=encrypted_payload.algo,
                                   enc_key=encrypted_payload.pkey,
                                   enc_serializer=encrypted_payload.serializer)
        else:
            if options:
                msg = message.Call(request_id,
                                   procedure,
                                   args=args,
                                   kwargs=kwargs,
                                   **options.message_attr())
            else:
                msg = message.Call(request_id,
                                   procedure,
                                   args=args,
                                   kwargs=kwargs)

        # FIXME: implement call canceling
        # def canceller(_d):
        #   cancel_msg = message.Cancel(request)
        #   self._transport.send(cancel_msg)
        # d = Deferred(canceller)

        on_reply = txaio.create_future()
        self._call_reqs[request_id] = CallRequest(request_id, procedure, on_reply, options)

        try:
            # Notes:
            #
            # * this might raise autobahn.wamp.exception.SerializationError
            #   when the user payload cannot be serialized
            # * we have to setup a CallRequest() in _call_reqs _before_
            #   calling transpor.send(), because a mock- or side-by-side transport
            #   will immediately lead on an incoming WAMP message in onMessage()
            #
            self._transport.send(msg)
        except:
            if request_id in self._call_reqs:
                del self._call_reqs[request_id]
            raise

        return on_reply
Implements :func:`autobahn.wamp.interfaces.ICaller.call`
dataset/ETHPy150Open crossbario/autobahn-python/autobahn/wamp/protocol.py/ApplicationSession.call