Пример #1
0
 def _populate_message_attributes(self, c_message):
     if self.properties:
         c_message.properties = self.properties.get_properties_obj()
     if self.application_properties:
         if not isinstance(self.application_properties, dict):
             raise TypeError("Application properties must be a dictionary.")
         amqp_props = utils.data_factory(self.application_properties, encoding=self._encoding)
         c_message.application_properties = amqp_props
     if self.annotations:
         if not isinstance(self.annotations, dict):
             raise TypeError("Message annotations must be a dictionary.")
         ann_props = c_uamqp.create_message_annotations(
             utils.data_factory(self.annotations, encoding=self._encoding))
         c_message.message_annotations = ann_props
     if self.delivery_annotations:
         if not isinstance(self.delivery_annotations, dict):
             raise TypeError("Delivery annotations must be a dictionary.")
         delivery_ann_props = c_uamqp.create_delivery_annotations(
             utils.data_factory(self.delivery_annotations, encoding=self._encoding))
         c_message.delivery_annotations = delivery_ann_props
     if self.header:
         c_message.header = self.header.get_header_obj()
     if self.footer:
         if not isinstance(self.footer, dict):
             raise TypeError("Footer must be a dictionary.")
         footer = c_uamqp.create_footer(
             utils.data_factory(self.footer, encoding=self._encoding))
         c_message.footer = footer
    def _create_handler(self):
        source = Source(self._source)
        if self._offset is not None:
            source.set_filter(self._offset._selector())  # pylint:disable=protected-access

        if StrictVersion(uamqp.__version__) < StrictVersion("1.2.3"):  # backward compatible until uamqp 1.2.3 released
            desired_capabilities = {}
        elif self._track_last_enqueued_event_properties:
            symbol_array = [types.AMQPSymbol(self._receiver_runtime_metric_symbol)]
            desired_capabilities = {"desired_capabilities": utils.data_factory(types.AMQPArray(symbol_array))}
        else:
            desired_capabilities = {"desired_capabilities": None}

        self._handler = ReceiveClientAsync(
            source,
            auth=self._client._create_auth(),  # pylint:disable=protected-access
            debug=self._client._config.network_tracing,  # pylint:disable=protected-access
            prefetch=self._prefetch,
            link_properties=self._link_properties,
            timeout=self._timeout,
            error_policy=self._retry_policy,
            keep_alive_interval=self._keep_alive,
            client_name=self._name,
            receive_settle_mode=uamqp.constants.ReceiverSettleMode.ReceiveAndDelete,
            auto_complete=False,
            properties=self._client._create_properties(  # pylint:disable=protected-access
                self._client._config.user_agent),  # pylint:disable=protected-access
            **desired_capabilities,  # pylint:disable=protected-access
            loop=self._loop)
        self._messages_iter = None
Пример #3
0
 def __init__(self, failed, undeliverable, annotations=None, encoding='UTF-8'):
     self.failed = failed
     self.undeliverable = undeliverable
     if annotations and not isinstance(annotations, dict):
         raise TypeError("Disposition annotations must be a dictionary.")
     self.annotations = utils.data_factory(annotations, encoding=encoding) if annotations else None
     super(MessageModified, self).__init__()
Пример #4
0
 def footer(self, value):
     if value and not isinstance(value, dict):
         raise TypeError("Footer must be a dictionary")
     footer_props = c_uamqp.create_footer(
         utils.data_factory(value, encoding=self._encoding))
     self._message.footer = footer_props
     self._footer = value
Пример #5
0
    def set_filter(self,
                   value,
                   name=constants.STRING_FILTER,
                   descriptor=constants.STRING_FILTER):
        """Set a filter on the endpoint. Only one filter
        can be applied to an endpoint.

        :param value: The filter to apply to the endpoint. Set to None for a NULL filter.
        :type value: bytes or str or None
        :param name: The name of the filter. This will be encoded as
         an AMQP Symbol. By default this is set to b'apache.org:selector-filter:string'.
        :type name: bytes
        :param descriptor: The descriptor used if the filter is to be encoded as a described value.
         This will be encoded as an AMQP Symbol. By default this is set to b'apache.org:selector-filter:string'.
         Set to None if the filter should not be encoded as a described value.
        :type descriptor: bytes or None
        """
        value = value.encode(self._encoding) if isinstance(
            value, six.text_type) else value
        filter_set = c_uamqp.dict_value()
        filter_key = c_uamqp.symbol_value(name)
        filter_value = utils.data_factory(value, encoding=self._encoding)
        if value is not None and descriptor is not None:
            descriptor = c_uamqp.symbol_value(descriptor)
            filter_value = c_uamqp.described_value(descriptor, filter_value)

        filter_set[filter_key] = filter_value
        self._address.filter_set = filter_set
Пример #6
0
    def _create_handler(self, auth: "JWTTokenAsync") -> None:
        source = Source(self._source)
        if self._offset is not None:
            source.set_filter(
                event_position_selector(self._offset, self._offset_inclusive))
        desired_capabilities = None
        if self._track_last_enqueued_event_properties:
            symbol_array = [types.AMQPSymbol(RECEIVER_RUNTIME_METRIC_SYMBOL)]
            desired_capabilities = utils.data_factory(
                types.AMQPArray(symbol_array))

        properties = create_properties(self._client._config.user_agent  # pylint:disable=protected-access
                                       )
        self._handler = ReceiveClientAsync(
            source,
            auth=auth,
            debug=self._client._config.network_tracing,  # pylint:disable=protected-access
            prefetch=self._prefetch,
            link_properties=self._link_properties,
            timeout=self._timeout,
            idle_timeout=self._idle_timeout,
            error_policy=self._retry_policy,
            keep_alive_interval=self._keep_alive,
            client_name=self._name,
            receive_settle_mode=uamqp.constants.ReceiverSettleMode.
            ReceiveAndDelete,
            auto_complete=False,
            properties=properties,
            desired_capabilities=desired_capabilities,
            loop=self._loop,
        )

        self._handler._streaming_receive = True  # pylint:disable=protected-access
        self._handler._message_received_callback = (  # pylint:disable=protected-access
            self._message_received)
def test_event_hubs_client_receive_with_runtime_metric_sync(live_eventhub_config):
    uri = "sb://{}/{}".format(live_eventhub_config['hostname'], live_eventhub_config['event_hub'])
    sas_auth = authentication.SASTokenAuth.from_shared_access_key(
        uri, live_eventhub_config['key_name'], live_eventhub_config['access_key'])

    source = "amqps://{}/{}/ConsumerGroups/{}/Partitions/{}".format(
        live_eventhub_config['hostname'],
        live_eventhub_config['event_hub'],
        live_eventhub_config['consumer_group'],
        live_eventhub_config['partition'])

    receiver_runtime_metric_symbol = b'com.microsoft:enable-receiver-runtime-metric'
    symbol_array = [types.AMQPSymbol(receiver_runtime_metric_symbol)]
    desired_capabilities = utils.data_factory(types.AMQPArray(symbol_array))

    with uamqp.ReceiveClient(source, auth=sas_auth, debug=False, timeout=50, prefetch=50,
                             desired_capabilities=desired_capabilities) as receive_client:
        log.info("Created client, receiving...")
        with pytest.raises(ValueError):
            batch = receive_client.receive_message_batch(max_batch_size=100)
        batch = receive_client.receive_message_batch(max_batch_size=10)
        log.info("Got batch: {}".format(len(batch)))
        assert len(batch) <= 10
        for message in batch:
            annotations = message.annotations
            delivery_annotations = message.delivery_annotations
            log.info("Sequence Number: {}".format(annotations.get(b'x-opt-sequence-number')))
            assert b'last_enqueued_sequence_number' in delivery_annotations
            assert b'last_enqueued_offset' in delivery_annotations
            assert b'last_enqueued_time_utc' in delivery_annotations
            assert b'runtime_info_retrieval_time_utc' in delivery_annotations
    log.info("Finished receiving")
Пример #8
0
async def test_event_hubs_receive_with_runtime_metric_async(
        live_eventhub_config):
    uri = "sb://{}/{}".format(live_eventhub_config['hostname'],
                              live_eventhub_config['event_hub'])
    sas_auth = authentication.SASTokenAsync.from_shared_access_key(
        uri, live_eventhub_config['key_name'],
        live_eventhub_config['access_key'])
    source = "amqps://{}/{}/ConsumerGroups/{}/Partitions/{}".format(
        live_eventhub_config['hostname'], live_eventhub_config['event_hub'],
        live_eventhub_config['consumer_group'],
        live_eventhub_config['partition'])

    receiver_runtime_metric_symbol = b'com.microsoft:enable-receiver-runtime-metric'
    symbol_array = [types.AMQPSymbol(receiver_runtime_metric_symbol)]
    desired_capabilities = utils.data_factory(types.AMQPArray(symbol_array))

    async with uamqp.ReceiveClientAsync(
            source,
            debug=False,
            auth=sas_auth,
            timeout=1000,
            prefetch=10,
            desired_capabilities=desired_capabilities) as receive_client:
        message_batch = await receive_client.receive_message_batch_async(10)
        log.info("got batch: {}".format(len(message_batch)))
        for message in message_batch:
            annotations = message.annotations
            delivery_annotations = message.delivery_annotations
            log.info("Sequence Number: {}".format(
                annotations.get(b'x-opt-sequence-number')))
            assert b'last_enqueued_sequence_number' in delivery_annotations
            assert b'last_enqueued_offset' in delivery_annotations
            assert b'last_enqueued_time_utc' in delivery_annotations
            assert b'runtime_info_retrieval_time_utc' in delivery_annotations
Пример #9
0
    def _c_wrapper(self, value_array):
        value_type = type(value_array[0])
        if not all(isinstance(x, value_type) for x in value_array):
            raise ValueError("All Array values must be the same type.")

        c_array = c_uamqp.array_value()
        for value in value_array:
            c_array.append(utils.data_factory(value))
        return c_array
Пример #10
0
 def user_id(self, value):
     if isinstance(value, six.text_type):
         value = value.encode(self._encoding)
     elif value is not None and not isinstance(value, six.binary_type):
         raise TypeError("user_id must be bytes or str.")
     # user_id is type of binary according to the spec.
     # convert byte string into bytearray then wrap the data into c_uamqp.BinaryValue.
     if value is not None:
         self._user_id = utils.data_factory(bytearray(value), encoding=self._encoding)
     else:
         self._user_id = None
Пример #11
0
    def set(self, value):
        """Set a value as the message body. This can be any
        Python data type and it will be automatically encoded
        into an AMQP type. If a specific AMQP type is required, a
        `types.AMQPType` can be used.

        :param data: The data to send in the body.
        :type data: ~uamqp.types.AMQPType
        """
        value = utils.data_factory(value)
        self._message.set_body_value(value)
Пример #12
0
    def __init__(self,
                 session,
                 source,
                 target,
                 on_message_received,
                 name=None,
                 receive_settle_mode=constants.ReceiverSettleMode.PeekLock,
                 send_settle_mode=constants.SenderSettleMode.Unsettled,
                 max_message_size=constants.MAX_MESSAGE_LENGTH_BYTES,
                 prefetch=300,
                 properties=None,
                 error_policy=None,
                 debug=False,
                 encoding='UTF-8',
                 desired_capabilities=None):
        # pylint: disable=protected-access
        if name:
            self.name = name.encode(encoding) if isinstance(
                name, six.text_type) else name
        else:
            self.name = str(uuid.uuid4()).encode(encoding)
        target = target.encode(encoding) if isinstance(
            target, six.text_type) else target
        role = constants.Role.Receiver

        self.source = source._address.value
        self.target = c_uamqp.Messaging.create_target(target)
        self.on_message_received = on_message_received
        self.encoding = encoding
        self.error_policy = error_policy or errors.ErrorPolicy()
        self._settle_mode = receive_settle_mode
        self._conn = session._conn
        self._session = session
        self._link = c_uamqp.create_link(session._session, self.name,
                                         role.value, self.source, self.target)
        self._link.subscribe_to_detach_event(self)
        if prefetch:
            self._link.set_prefetch_count(prefetch)
        if properties:
            self._link.set_attach_properties(
                utils.data_factory(properties, encoding=encoding))
        if receive_settle_mode:
            self.receive_settle_mode = receive_settle_mode
        if send_settle_mode:
            self.send_settle_mode = send_settle_mode
        if max_message_size:
            self.max_message_size = max_message_size
        if desired_capabilities:
            self._link.set_desired_capabilities(desired_capabilities)

        self._receiver = c_uamqp.create_message_receiver(self._link, self)
        self._receiver.set_trace(debug)
        self._state = constants.MessageReceiverState.Idle
        self._error = None
Пример #13
0
    def append(self, value):
        """Append an item to the body. This can be any
        Python data type and it will be automatically encoded
        into an AMQP type. If a specific AMQP type is required, a
        `types.AMQPType` can be used.

        :param data: The data to append.
        :type data: ~uamqp.types.AMQPType
        """
        value = utils.data_factory(value, encoding=self._encoding)
        self._message.add_body_sequence(value)
Пример #14
0
    def append(self, data):
        """Append a sequence section to the body. The data
        should be a list of objects. The object in the list
        can be any Python data type and it will be automatically
        encoded into an AMQP type. If a specific AMQP type
        is required, a `types.AMQPType` can be used.

        :param data: The list of objects to append.
        :type data: list[~uamqp.types.AMQPType]
        """
        data = utils.data_factory(data)
        self._message.add_body_sequence(data)
Пример #15
0
 def get_message(self):
     """Get the underlying C message from this object.
     :returns: ~uamqp.c_uamqp.cMessage
     """
     if not self._message:
         return None
     if self.properties:
         self._message.properties = self.properties._properties  # pylint: disable=protected-access
     if self.application_properties:
         if not isinstance(self.application_properties, dict):
             raise TypeError("Application properties must be a dictionary.")
         amqp_props = utils.data_factory(self.application_properties, encoding=self._encoding)
         self._message.application_properties = amqp_props
     if self.annotations:
         if not isinstance(self.annotations, dict):
             raise TypeError("Message annotations must be a dictionary.")
         ann_props = c_uamqp.create_message_annotations(
             utils.data_factory(self.annotations, encoding=self._encoding))
         self._message.message_annotations = ann_props
     if self.header:
         self._message.header = self.header._header  # pylint: disable=protected-access
     return self._message
def test_message_properties():

    value = c_uamqp.create_properties()
    assert not value.user_id

    value = c_uamqp.create_properties()
    value.user_id = utils.data_factory(bytearray(b'testuseridlongstring'))
    assert value.user_id == b'testuseridlongstring'

    value = c_uamqp.create_properties()
    value.user_id = utils.data_factory(bytearray(b''))
    assert value.user_id == b''

    value = c_uamqp.create_properties()
    value.user_id = utils.data_factory(bytearray(b'short'))
    assert value.user_id == b'short'

    value = c_uamqp.create_properties()
    value.user_id = utils.data_factory(bytearray(b'!@#$%^&*()+_?'))
    assert value.user_id == b'!@#$%^&*()+_?'

    value = c_uamqp.create_properties()
    value.user_id = utils.data_factory(bytearray(b'\nweird\0user\1id\0\t'))
    assert value.user_id == b'\nweird\0user\1id\0\t'
Пример #17
0
async def test_event_hubs_idempotent_producer(live_eventhub_config):

    uri = "sb://{}/{}".format(live_eventhub_config['hostname'],
                              live_eventhub_config['event_hub'])
    sas_auth = authentication.SASTokenAsync.from_shared_access_key(
        uri, live_eventhub_config['key_name'],
        live_eventhub_config['access_key'])

    target = "amqps://{}/{}/Partitions/0".format(
        live_eventhub_config['hostname'], live_eventhub_config['event_hub'])

    symbol_array = [
        uamqp_types.AMQPSymbol(b"com.microsoft:idempotent-producer")
    ]
    desired_capabilities = utils.data_factory(
        uamqp_types.AMQPArray(symbol_array))

    link_properties = {
        uamqp_types.AMQPSymbol(b"com.microsoft:timeout"):
        uamqp_types.AMQPLong(int(60 * 1000))
    }

    def on_attach(attach_source, attach_target, properties, error):
        if str(attach_target) == target:
            on_attach.owner_level = properties.get(
                b"com.microsoft:producer-epoch")
            on_attach.producer_group_id = properties.get(
                b"com.microsoft:producer-id")
            on_attach.starting_sequence_number = properties.get(
                b"com.microsoft:producer-sequence-number")

    send_client = uamqp.SendClientAsync(
        target,
        auth=sas_auth,
        desired_capabilities=desired_capabilities,
        link_properties=link_properties,
        on_attach=on_attach,
        debug=True)
    await send_client.open_async()
    while not await send_client.client_ready_async():
        await asyncio.sleep(0.05)

    assert on_attach.owner_level is not None
    assert on_attach.producer_group_id is not None
    assert on_attach.starting_sequence_number is not None
    await send_client.close_async()
Пример #18
0
    def __init__(self,
                 session,
                 source,
                 target,
                 on_message_received,
                 name=None,
                 receive_settle_mode=None,
                 max_message_size=None,
                 prefetch=None,
                 properties=None,
                 debug=False,
                 encoding='UTF-8'):
        # pylint: disable=protected-access
        if name:
            self.name = name.encode(encoding) if isinstance(name,
                                                            str) else name
        else:
            self.name = str(uuid.uuid4()).encode(encoding)
        target = target.encode(encoding) if isinstance(target, str) else target
        role = constants.Role.Receiver

        self.source = source._address.value
        self.target = c_uamqp.Messaging.create_target(target)
        self.on_message_received = on_message_received
        self._conn = session._conn
        self._session = session
        self._link = c_uamqp.create_link(session._session, self.name,
                                         role.value, self.source, self.target)

        if prefetch:
            self._link.set_prefetch_count(prefetch)
        if properties:
            self._link.set_attach_properties(
                utils.data_factory(properties, encoding=encoding))
        if receive_settle_mode:
            self.receive_settle_mode = receive_settle_mode
        if max_message_size:
            self.max_message_size = max_message_size

        self._receiver = c_uamqp.create_message_receiver(self._link, self)
        self._receiver.set_trace(debug)
        self._state = constants.MessageReceiverState.Idle
Пример #19
0
    def __init__(self,
                 session,
                 source,
                 target,
                 name=None,
                 send_settle_mode=None,
                 max_message_size=None,
                 link_credit=None,
                 properties=None,
                 debug=False,
                 encoding='UTF-8'):
        # pylint: disable=protected-access
        if name:
            self.name = name.encode(encoding) if isinstance(name,
                                                            str) else name
        else:
            self.name = str(uuid.uuid4()).encode(encoding)
        source = source.encode(encoding) if isinstance(source, str) else source
        role = constants.Role.Sender

        self.source = c_uamqp.Messaging.create_source(source)
        self.target = target._address.value
        self._conn = session._conn
        self._session = session
        self._link = c_uamqp.create_link(session._session, self.name,
                                         role.value, self.source, self.target)
        self._link.max_message_size = max_message_size

        if link_credit:
            self._link.set_prefetch_count(link_credit)
        if properties:
            self._link.set_attach_properties(
                utils.data_factory(properties, encoding=encoding))
        if send_settle_mode:
            self.send_settle_mode = send_settle_mode
        if max_message_size:
            self.max_message_size = max_message_size

        self._sender = c_uamqp.create_message_sender(self._link, self)
        self._sender.set_trace(debug)
        self._state = constants.MessageSenderState.Idle
Пример #20
0
 def __init__(self,
              condition=None,
              description=None,
              encoding='UTF-8',
              info=None):
     if condition:
         self.error_condition = condition.encode(encoding) if isinstance(
             condition, six.text_type) else condition
     else:
         self.error_condition = b"amqp:internal-error"
     self.error_description = None
     if description:
         self.error_description = description.encode(encoding) if isinstance(description, six.text_type) \
             else description
     else:
         self.error_description = b""
     if info and not isinstance(info, dict):
         raise TypeError("Disposition error info must be a dictionary.")
     self.error_info = utils.data_factory(
         info, encoding=encoding) if info else None
     super(MessageRejected, self).__init__()
Пример #21
0
 def _c_wrapper(self, descriptor, described):
     descriptor = utils.data_factory(descriptor)
     described = utils.data_factory(described)
     return c_uamqp.described_value(descriptor, described)
Пример #22
0
 def absolute_expiry_time(self, value):
     value = utils.data_factory(value, encoding=self._encoding)
     self._properties.absolute_expiry_time = value
Пример #23
0
 def content_encoding(self, value):
     value = utils.data_factory(value, encoding=self._encoding)
     self._properties.content_encoding = value
Пример #24
0
 def creation_time(self, value):
     value = utils.data_factory(value, encoding=self._encoding)
     self._properties.creation_time = value
Пример #25
0
 def properties(self, value):
     if not isinstance(value, dict):
         raise TypeError("Connection properties must be a dictionary.")
     self._conn.properties = utils.data_factory(value,
                                                encoding=self._encoding)
Пример #26
0
 def group_sequence(self, value):
     value = utils.data_factory(value, encoding=self._encoding)
     self._properties.group_sequence = value
Пример #27
0
 def reply_to_group_id(self, value):
     value = utils.data_factory(value, encoding=self._encoding)
     self._properties.reply_to_group_id = value
Пример #28
0
 def correlation_id(self, value):
     if value is None:
         self._correlation_id = None
     else:
         self._correlation_id = utils.data_factory(value,
                                                   encoding=self._encoding)
Пример #29
0
 def reply_to(self, value):
     if value is None:
         self._reply_to = None
     else:
         self._reply_to = utils.data_factory(value, encoding=self._encoding)
Пример #30
0
 def message_id(self, value):
     if value is None:
         self._message_id = None
     else:
         self._message_id = utils.data_factory(value,
                                               encoding=self._encoding)