예제 #1
0
    def _prepare(cls, base,
                 exchange=_marker, topic=_marker, namespace=_marker,
                 version=_marker, server=_marker, fanout=_marker,
                 timeout=_marker, version_cap=_marker, retry=_marker):
        """Prepare a method invocation context. See RPCClient.prepare()."""
        if version is not None and version is not cls._marker:
            # quick sanity check to make sure parsable version numbers are used
            try:
                utils.version_is_compatible(version, version)
            except (IndexError, ValueError):
                raise exceptions.MessagingException(
                    "Version must contain a major and minor integer. Got %s"
                    % version)
        kwargs = dict(
            exchange=exchange,
            topic=topic,
            namespace=namespace,
            version=version,
            server=server,
            fanout=fanout)
        kwargs = dict([(k, v) for k, v in kwargs.items()
                       if v is not cls._marker])
        target = base.target(**kwargs)

        if timeout is cls._marker:
            timeout = base.timeout
        if retry is cls._marker:
            retry = base.retry
        if version_cap is cls._marker:
            version_cap = base.version_cap

        return _CallContext(base.transport, target,
                            base.serializer,
                            timeout, version_cap, retry)
예제 #2
0
    def _prepare(cls, base,
                 exchange=_marker, topic=_marker, namespace=_marker,
                 version=_marker, server=_marker, fanout=_marker,
                 timeout=_marker, version_cap=_marker, retry=_marker):
        """Prepare a method invocation context. See RPCClient.prepare()."""
        if version is not None and version is not cls._marker:
            # quick sanity check to make sure parsable version numbers are used
            try:
                utils.version_is_compatible(version, version)
            except (IndexError, ValueError):
                raise exceptions.MessagingException(
                    "Version must contain a major and minor integer. Got %s"
                    % version)
        kwargs = dict(
            exchange=exchange,
            topic=topic,
            namespace=namespace,
            version=version,
            server=server,
            fanout=fanout)
        kwargs = dict([(k, v) for k, v in kwargs.items()
                       if v is not cls._marker])
        target = base.target(**kwargs)

        if timeout is cls._marker:
            timeout = base.timeout
        if retry is cls._marker:
            retry = base.retry
        if version_cap is cls._marker:
            version_cap = base.version_cap

        return _CallContext(base.transport, target,
                            base.serializer,
                            timeout, version_cap, retry)
예제 #3
0
 def _check_version(cls, version):
     if version is not cls._marker:
         # quick sanity check to make sure parsable version numbers are used
         try:
             utils.version_is_compatible(version, version)
         except (IndexError, ValueError):
             raise exceptions.MessagingException(
                 "Version must contain a major and minor integer. Got %s"
                 % version)
예제 #4
0
 def _check_version(cls, version):
     if version is not cls._marker:
         # quick sanity check to make sure parsable version numbers are used
         try:
             utils.version_is_compatible(version, version)
         except (IndexError, ValueError):
             raise exceptions.MessagingException(
                 "Version must contain a major and minor integer. Got %s"
                 % version)
예제 #5
0
    def __init__(self, pika_engine, channel, method, properties, body):
        """Parse RabbitMQ message

        :param pika_engine: PikaEngine, shared object with configuration and
            shared driver functionality
        :param channel: Channel, RabbitMQ channel which was used for
            this message delivery, used for sending ack back.
            If None - ack is not required
        :param method: Method, RabbitMQ message method
        :param properties: Properties, RabbitMQ message properties
        :param body: Bytes, RabbitMQ message body
        """
        headers = getattr(properties, "headers", {})
        version = headers.get(_VERSION_HEADER, None)
        if not utils.version_is_compatible(version, _VERSION):
            raise pika_drv_exc.UnsupportedDriverVersion(
                "Message's version: {} is not compatible with driver version: "
                "{}".format(version, _VERSION))

        self._pika_engine = pika_engine
        self._channel = channel
        self._delivery_tag = method.delivery_tag

        self._version = version

        self._content_type = properties.content_type
        self._content_encoding = properties.content_encoding
        self.unique_id = properties.message_id

        self.expiration_time = (
            None if properties.expiration is None else
            time.time() + float(properties.expiration) / 1000
        )

        if self._content_type != "application/json":
            raise NotImplementedError(
                "Content-type['{}'] is not valid, "
                "'application/json' only is supported.".format(
                    self._content_type
                )
            )

        message_dict = jsonutils.loads(body, encoding=self._content_encoding)

        context_dict = {}

        for key in list(message_dict.keys()):
            key = six.text_type(key)
            if key.startswith('_$_'):
                value = message_dict.pop(key)
                context_dict[key[3:]] = value

        super(PikaIncomingMessage, self).__init__(context_dict, message_dict)
예제 #6
0
    def __init__(self, pika_engine, channel, method, properties, body):
        """Parse RabbitMQ message

        :param pika_engine: PikaEngine, shared object with configuration and
            shared driver functionality
        :param channel: Channel, RabbitMQ channel which was used for
            this message delivery, used for sending ack back.
            If None - ack is not required
        :param method: Method, RabbitMQ message method
        :param properties: Properties, RabbitMQ message properties
        :param body: Bytes, RabbitMQ message body
        """
        headers = getattr(properties, "headers", {})
        version = headers.get(_VERSION_HEADER, None)
        if not utils.version_is_compatible(version, _VERSION):
            raise pika_drv_exc.UnsupportedDriverVersion(
                "Message's version: {} is not compatible with driver version: "
                "{}".format(version, _VERSION))

        self._pika_engine = pika_engine
        self._channel = channel
        self._delivery_tag = method.delivery_tag

        self._version = version

        self._content_type = properties.content_type
        self.unique_id = properties.message_id

        self.expiration_time = (
            None if properties.expiration is None else
            time.time() + float(properties.expiration) / 1000
        )

        try:
            serializer = pika_drv_cmns.MESSAGE_SERIALIZERS[self._content_type]
        except KeyError:
            raise NotImplementedError(
                "Content-type['{}'] is not supported.".format(
                    self._content_type
                )
            )

        message_dict = serializer.load_from_bytes(body)

        context_dict = {}

        for key in list(message_dict.keys()):
            key = six.text_type(key)
            if key.startswith('_$_'):
                value = message_dict.pop(key)
                context_dict[key[3:]] = value

        super(PikaIncomingMessage, self).__init__(context_dict, message_dict)
예제 #7
0
def deserialize_msg(msg):
    # NOTE(russellb): Hang on to your hats, this road is about to
    # get a little bumpy.
    #
    # Robustness Principle:
    #    "Be strict in what you send, liberal in what you accept."
    #
    # At this point we have to do a bit of guessing about what it
    # is we just received.  Here is the set of possibilities:
    #
    # 1) We received a dict.  This could be 2 things:
    #
    #   a) Inspect it to see if it looks like a standard message envelope.
    #      If so, great!
    #
    #   b) If it doesn't look like a standard message envelope, it could either
    #      be a notification, or a message from before we added a message
    #      envelope (referred to as version 1.0).
    #      Just return the message as-is.
    #
    # 2) It's any other non-dict type.  Just return it and hope for the best.
    #    This case covers return values from rpc.call() from before message
    #    envelopes were used.  (messages to call a method were always a dict)

    if not isinstance(msg, dict):
        # See #2 above.
        return msg

    base_envelope_keys = (_VERSION_KEY, _MESSAGE_KEY)
    if not all(map(lambda key: key in msg, base_envelope_keys)):
        #  See #1.b above.
        return msg

    # At this point we think we have the message envelope
    # format we were expecting. (#1.a above)

    if not utils.version_is_compatible(_RPC_ENVELOPE_VERSION,
                                       msg[_VERSION_KEY]):
        raise UnsupportedRpcEnvelopeVersion(version=msg[_VERSION_KEY])

    raw_msg = jsonutils.loads(msg[_MESSAGE_KEY])

    return raw_msg
예제 #8
0
def deserialize_msg(msg):
    # NOTE(russellb): Hang on to your hats, this road is about to
    # get a little bumpy.
    #
    # Robustness Principle:
    #    "Be strict in what you send, liberal in what you accept."
    #
    # At this point we have to do a bit of guessing about what it
    # is we just received.  Here is the set of possibilities:
    #
    # 1) We received a dict.  This could be 2 things:
    #
    #   a) Inspect it to see if it looks like a standard message envelope.
    #      If so, great!
    #
    #   b) If it doesn't look like a standard message envelope, it could either
    #      be a notification, or a message from before we added a message
    #      envelope (referred to as version 1.0).
    #      Just return the message as-is.
    #
    # 2) It's any other non-dict type.  Just return it and hope for the best.
    #    This case covers return values from rpc.call() from before message
    #    envelopes were used.  (messages to call a method were always a dict)

    if not isinstance(msg, dict):
        # See #2 above.
        return msg

    base_envelope_keys = (_VERSION_KEY, _MESSAGE_KEY)
    if not all(map(lambda key: key in msg, base_envelope_keys)):
        #  See #1.b above.
        return msg

    # At this point we think we have the message envelope
    # format we were expecting. (#1.a above)

    if not utils.version_is_compatible(_RPC_ENVELOPE_VERSION,
                                       msg[_VERSION_KEY]):
        raise UnsupportedRpcEnvelopeVersion(version=msg[_VERSION_KEY])

    raw_msg = jsonutils.loads(msg[_MESSAGE_KEY])

    return raw_msg
예제 #9
0
 def test_version_is_compatible_no_rev_is_zero(self):
     self.assertTrue(utils.version_is_compatible('1.23.0', '1.23'))
예제 #10
0
 def test_version_is_compatible_older_rev(self):
     self.assertTrue(utils.version_is_compatible('1.24', '1.23.1'))
예제 #11
0
 def test_version_is_compatible_newer_rev_both(self):
     self.assertFalse(utils.version_is_compatible('1.23.1', '1.23.2'))
예제 #12
0
 def test_version_is_compatible_major_difference2(self):
     self.assertFalse(utils.version_is_compatible('1.23', '2.23'))
예제 #13
0
 def test_version_is_compatible_older_minor(self):
     self.assertFalse(utils.version_is_compatible('1.22', '1.23'))
예제 #14
0
 def test_version_is_compatible_newer_minor(self):
     self.assertTrue(utils.version_is_compatible('1.24', '1.23'))
예제 #15
0
 def test_version_is_compatible_same(self):
     self.assertTrue(utils.version_is_compatible('1.23', '1.23'))
예제 #16
0
 def can_send_version(self, version=_marker):
     """Check to see if a version is compatible with the version cap."""
     version = self.target.version if version is self._marker else version
     return utils.version_is_compatible(self.version_cap, version)
예제 #17
0
 def _check_version_cap(self, version):
     if not utils.version_is_compatible(self.version_cap, version):
         raise RPCVersionCapError(version=version,
                                  version_cap=self.version_cap)
예제 #18
0
 def _is_compatible(target, version):
     endpoint_version = target.version or '1.0'
     return utils.version_is_compatible(endpoint_version, version)
예제 #19
0
 def can_send_version(self, version=_marker):
     """Check to see if a version is compatible with the version cap."""
     version = self.target.version if version is self._marker else version
     return (not self.version_cap or
             utils.version_is_compatible(self.version_cap,
                                         self.target.version))
예제 #20
0
 def _check_version_cap(self, version):
     if not utils.version_is_compatible(self.version_cap, version):
         raise RPCVersionCapError(version=version,
                                  version_cap=self.version_cap)
예제 #21
0
 def _is_compatible(target, version):
     endpoint_version = target.version or '1.0'
     return utils.version_is_compatible(endpoint_version, version)
예제 #22
0
 def _fake_can_send_version_method(version):
     return messaging_utils.version_is_compatible(
         rpcapi.RPC_API_VERSION, version)