def publish(self, exchange, routing_key='', mandatory=False): """Publish the message to the exchange with the specified routing key. In Python 2 if the message is a ``unicode`` value it will be converted to a ``str`` using ``str.encode('UTF-8')``. If you do not want the auto-conversion to take place, set the body to a ``str`` or ``bytes`` value prior to publishing. In Python 3 if the message is a ``str`` value it will be converted to a ``bytes`` value using ``bytes(value.encode('UTF-8'))``. If you do not want the auto-conversion to take place, set the body to a ``bytes`` value prior to publishing. :param exchange: The exchange to publish the message to :type exchange: str or :class:`rabbitpy.Exchange` :param str routing_key: The routing key to use :param bool mandatory: Requires the message is published :return: bool or None :raises: rabbitpy.exceptions.MessageReturnedException """ if isinstance(exchange, base.AMQPClass): exchange = exchange.name # Coerce the body to the proper type payload = utils.maybe_utf8_encode(self.body) frames = [ specification.Basic.Publish(exchange=exchange, routing_key=routing_key or '', mandatory=mandatory), header.ContentHeader(body_size=len(payload), properties=self._properties) ] # Calculate how many body frames are needed pieces = int( math.ceil(len(payload) / float(self.channel.maximum_frame_size))) # Send the message for offset in range(0, pieces): start = self.channel.maximum_frame_size * offset end = start + self.channel.maximum_frame_size if end > len(payload): end = len(payload) frames.append(body.ContentBody(payload[start:end])) # Write the frames out self.channel._write_frames(frames) # If publisher confirmations are enabled, wait for the response if self.channel.publisher_confirms: response = self.channel._wait_for_confirmation() if isinstance(response, specification.Basic.Ack): return True elif isinstance(response, specification.Basic.Nack): return False else: raise exceptions.UnexpectedResponseError(response)
async def test_basic_return(self): async def on_return(msg: message.Message) -> None: self.assertEqual(msg.reply_code, 404) self.assertEqual(msg.reply_text, 'Not Found') self.assertEqual(msg.exchange, self.exchange) self.assertEqual(msg.body, self.body) self.test_finished.set() self.client.register_basic_return_callback(on_return) await self.connect() await self.client.publish(self.exchange, self.routing_key, self.body) # Fake the Basic.Return self.client._on_frame( self.client._channel, commands.Basic.Return(404, 'Not Found', self.exchange, self.routing_key)) self.client._on_frame( self.client._channel, header.ContentHeader(0, len(self.body), commands.Basic.Properties())) self.client._on_frame(self.client._channel, body.ContentBody(self.body)) await self.test_finished.wait()
def _unmarshal_body_frame(frame_data): """Attempt to unmarshal a body frame :param bytes frame_data: Raw frame data to assign to our body frame :return tuple: Amount of data consumed and the frame object """ content_body = body.ContentBody() content_body.unmarshal(frame_data) return content_body
def _create_content_body(body): """Split body based on the maximum frame size. This function is based on code from Rabbitpy. https://github.com/gmr/rabbitpy :param str body: :rtype: collections.Iterable """ frames = int(math.ceil(len(body) / float(FRAME_MAX))) for offset in compatibility.RANGE(0, frames): start_frame = FRAME_MAX * offset end_frame = start_frame + FRAME_MAX if end_frame > len(body): end_frame = len(body) yield pamqp_body.ContentBody(body[start_frame:end_frame])
def publish(self, exchange, routing_key='', mandatory=False): """Publish the message to the exchange with the specified routing key. :param exchange: The exchange to publish the message to :type exchange: str or :class:`rabbitpy.Exchange` :param str routing_key: The routing key to use :param bool mandatory: Requires the message is published :return: bool or None :raises: rabbitpy.exceptions.MessageReturnedException """ if isinstance(exchange, base.AMQPClass): exchange = exchange.name method_frame = specification.Basic.Publish(exchange=exchange, routing_key=routing_key or '', mandatory=mandatory) self.channel._write_frame(method_frame) header_frame = header.ContentHeader(body_size=len(self.body), properties=self._properties) self.channel._write_frame(header_frame) if PYTHON3 and isinstance(self.body, str): self.body = bytes(self.body.encode('UTF-8')) pieces = int( math.ceil(len(self.body) / float(self.channel.maximum_frame_size))) # Send the message for offset in range(0, pieces): start = self.channel.maximum_frame_size * offset end = start + self.channel.maximum_frame_size if end > len(self.body): end = len(self.body) self.channel._write_frame(body.ContentBody(self.body[start:end])) # If publisher confirmations are enabled, wait for the response if self.channel.publisher_confirms: response = self.channel._wait_for_confirmation() if isinstance(response, specification.Basic.Ack): return True elif isinstance(response, specification.Basic.Nack): return False else: raise exceptions.UnexpectedResponseError(response)
def _create_content_body(self, body): """Split body based on the maximum frame size. This function is based on code from Rabbitpy. https://github.com/gmr/rabbitpy :param bytes,str,unicode body: Message payload :rtype: collections.Iterable """ frames = int(math.ceil(len(body) / float(self._max_frame_size))) for offset in compatibility.RANGE(0, frames): start_frame = self._max_frame_size * offset end_frame = start_frame + self._max_frame_size body_len = len(body) if end_frame > body_len: end_frame = body_len yield pamqp_body.ContentBody(body[start_frame:end_frame])
def setUp(self) -> None: self.exchange = str(uuid.uuid4()) self.routing_key = str(uuid.uuid4()) self.app_id = str(uuid.uuid4()) self.content_encoding = str(uuid.uuid4()) self.content_type = str(uuid.uuid4()) self.correlation_id = str(uuid.uuid4()) self.delivery_mode = random.randint(1, 2) self.expiration = str(int(time.time()) + random.randint(60, 300)) self.headers = {str(uuid.uuid4()): str(uuid.uuid4())} self.message_id = str(uuid.uuid4()) self.message_type = str(uuid.uuid4()) self.priority = random.randint(0, 255) self.reply_to = str(uuid.uuid4()) self.timestamp = datetime.datetime.now() self.user_id = str(uuid.uuid4()) self.body = b'-'.join([ str(uuid.uuid4()).encode('latin-1') for _offset in range(0, random.randint(1, 100)) ]) self.message = message.Message(self.get_method()) self.message.header = header.ContentHeader( 0, len(self.body), commands.Basic.Properties(app_id=self.app_id, content_encoding=self.content_encoding, content_type=self.content_type, correlation_id=self.correlation_id, delivery_mode=self.delivery_mode, expiration=self.expiration, headers=self.headers, message_id=self.message_id, message_type=self.message_type, priority=self.priority, reply_to=self.reply_to, timestamp=self.timestamp, user_id=self.user_id)) value = bytes(self.body) while value: self.message.body_frames.append( body.ContentBody(value[:constants.FRAME_MAX_SIZE])) value = value[constants.FRAME_MAX_SIZE:]
def test_content_body(self): value = str(uuid.uuid4()).encode('utf-8') expectation = b'\x03\x00\x01\x00\x00\x00$' + value + b'\xce' self.assertEqual(frame.marshal(body.ContentBody(value), 1), expectation)
def _unmarshal_body_frame(frame_data: bytes) -> body.ContentBody: """Attempt to unmarshal a body frame""" content_body = body.ContentBody(b'') content_body.unmarshal(frame_data) return content_body