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_header_frame(frame_data: bytes) -> header.ContentHeader: """Attempt to unmarshal a header frame :raises: pamqp.exceptions.UnmarshalingException """ content_header = header.ContentHeader() try: content_header.unmarshal(frame_data) except struct.error as error: raise exceptions.UnmarshalingException('ContentHeader', error) return content_header
def _unmarshal_header_frame(frame_data): """Attempt to unmarshal a header frame :param bytes frame_data: Raw frame data to assign to our header frame :return tuple: Amount of data consumed and the frame object """ content_header = header.ContentHeader() try: content_header.unmarshal(frame_data) except struct.error as error: raise exceptions.UnmarshalingException('ContentHeader', error) return content_header
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 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 publish(self, body, routing_key, exchange='', properties=None, mandatory=False, immediate=False): """Publish a Message. :param bytes,str,unicode body: Message payload :param str routing_key: Message routing key :param str exchange: The exchange to publish the message to :param dict properties: Message properties :param bool mandatory: Requires the message is published :param bool immediate: Request immediate delivery :raises AMQPInvalidArgument: Invalid Parameters :raises AMQPChannelError: Raises if the channel encountered an error. :raises AMQPConnectionError: Raises if the connection encountered an error. :rtype: bool,None """ self._validate_publish_parameters(body, exchange, immediate, mandatory, properties, routing_key) properties = properties or {} body = self._handle_utf8_payload(body, properties) properties = specification.Basic.Properties(**properties) method_frame = specification.Basic.Publish(exchange=exchange, routing_key=routing_key, mandatory=mandatory, immediate=immediate) header_frame = pamqp_header.ContentHeader(body_size=len(body), properties=properties) frames_out = [method_frame, header_frame] for body_frame in self._create_content_body(body): frames_out.append(body_frame) if self._channel.confirming_deliveries: with self._channel.rpc.lock: return self._publish_confirm(frames_out, mandatory) self._channel.write_frames(frames_out)
def test_content_header_with_basic_properties(self): props = commands.Basic.Properties( app_id='unittest', content_type='application/json', content_encoding='bzip2', correlation_id='d146482a-42dd-4b8b-a620-63d62ef686f3', delivery_mode=2, expiration='100', headers={'foo': 'Test ✈'}, message_id='4b5baed7-66e3-49da-bfe4-20a9651e0db4', message_type='foo', priority=10, reply_to='q1', timestamp=datetime.datetime(2019, 12, 19, 23, 29, 00)) expectation = (b'\x02\x00\x01\x00\x00\x00\xa2\x00<\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\n\xff\xe8\x10application/json\x05' b'bzip2\x00\x00\x00\x11\x03fooS\x00\x00\x00\x08Test ' b'\xe2\x9c\x88\x02\n$d146482a-42dd-4b8b-a620-63d62ef68' b'6f3\x02q1\x03100$4b5baed7-66e3-49da-bfe4-20a9651e0db4' b'\x00\x00\x00\x00]\xfc\x07\xbc\x03foo\x08unittest\xce') self.assertEqual(frame.marshal(header.ContentHeader(0, 10, props), 1), expectation)
def test_content_header(self): expectation = (b'\x02\x00\x01\x00\x00\x00\x0e\x00<\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\n\x00\x00\xce') self.assertEqual(frame.marshal(header.ContentHeader(body_size=10), 1), expectation)