示例#1
0
    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)
示例#2
0
    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()
示例#3
0
文件: frame.py 项目: michael-k/pamqp
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
示例#4
0
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
示例#5
0
    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)
示例#6
0
    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:]
示例#7
0
    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)
示例#8
0
 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)
示例#9
0
 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)