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)
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)
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)
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)
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
def test_version_is_compatible_no_rev_is_zero(self): self.assertTrue(utils.version_is_compatible('1.23.0', '1.23'))
def test_version_is_compatible_older_rev(self): self.assertTrue(utils.version_is_compatible('1.24', '1.23.1'))
def test_version_is_compatible_newer_rev_both(self): self.assertFalse(utils.version_is_compatible('1.23.1', '1.23.2'))
def test_version_is_compatible_major_difference2(self): self.assertFalse(utils.version_is_compatible('1.23', '2.23'))
def test_version_is_compatible_older_minor(self): self.assertFalse(utils.version_is_compatible('1.22', '1.23'))
def test_version_is_compatible_newer_minor(self): self.assertTrue(utils.version_is_compatible('1.24', '1.23'))
def test_version_is_compatible_same(self): self.assertTrue(utils.version_is_compatible('1.23', '1.23'))
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)
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)
def _is_compatible(target, version): endpoint_version = target.version or '1.0' return utils.version_is_compatible(endpoint_version, version)
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))
def _fake_can_send_version_method(version): return messaging_utils.version_is_compatible( rpcapi.RPC_API_VERSION, version)