diff --git a/HISTORY.rst b/HISTORY.rst index d60b724..6e90e55 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -3,6 +3,18 @@ Release History =============== +1.0.0 (2018-08-22) +++++++++++++++++++ + +- API stable. +- Renamed internal `_async` module to `async_ops` for docs generation. +- Added optional `auth_timeout` parameter to `EventHubClient` and `EventHubClientAsync` to configure how long to allow for token + negotiation to complete. Default is 60 seconds. +- Added optional `send_timeout` parameter to `EventHubClient.add_sender` and `EventHubClientAsync.add_async_sender` to determine the + timeout for Events to be successfully sent. Default value is 60 seconds. +- Reformatted logging for performance. + + 0.2.0 (2018-08-06) ++++++++++++++++++ diff --git a/README.rst b/README.rst index 616771e..2d75dc3 100644 --- a/README.rst +++ b/README.rst @@ -26,6 +26,11 @@ Python 2.7 support The uAMQP library currently only supports Python 3.4 and above. Python 2.7 support is planned for a future release. +Documentation ++++++++++++++ +Reference documentation is available at `docs.microsoft.com/python/api/azure-eventhub `__. + + Examples +++++++++ diff --git a/azure/eventhub/__init__.py b/azure/eventhub/__init__.py index ae780c2..3cde06c 100644 --- a/azure/eventhub/__init__.py +++ b/azure/eventhub/__init__.py @@ -3,7 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- -__version__ = "0.2.0" +__version__ = "1.0.0" from azure.eventhub.common import EventData, EventHubError, Offset from azure.eventhub.client import EventHubClient @@ -11,7 +11,7 @@ from azure.eventhub.receiver import Receiver try: - from azure.eventhub._async import ( + from azure.eventhub.async_ops import ( EventHubClientAsync, AsyncSender, AsyncReceiver) diff --git a/azure/eventhub/_async/__init__.py b/azure/eventhub/async_ops/__init__.py similarity index 98% rename from azure/eventhub/_async/__init__.py rename to azure/eventhub/async_ops/__init__.py index 5b102b5..7774724 100644 --- a/azure/eventhub/_async/__init__.py +++ b/azure/eventhub/async_ops/__init__.py @@ -183,7 +183,7 @@ def add_async_receiver( :operation: An optional operation to be appended to the hostname in the source URL. The value must start with `/` character. :type operation: str - :rtype: ~azure.eventhub._async.receiver_async.ReceiverAsync + :rtype: ~azure.eventhub.async_ops.receiver_async.ReceiverAsync """ path = self.address.path + operation if operation else self.address.path source_url = "amqps://{}{}/ConsumerGroups/{}/Partitions/{}".format( @@ -214,7 +214,7 @@ def add_async_epoch_receiver( :operation: An optional operation to be appended to the hostname in the source URL. The value must start with `/` character. :type operation: str - :rtype: ~azure.eventhub._async.receiver_async.ReceiverAsync + :rtype: ~azure.eventhub.async_ops.receiver_async.ReceiverAsync """ path = self.address.path + operation if operation else self.address.path source_url = "amqps://{}{}/ConsumerGroups/{}/Partitions/{}".format( @@ -249,7 +249,7 @@ def add_async_sender( :param auto_reconnect: Whether to automatically reconnect the sender if a retryable error occurs. Default value is `True`. :type auto_reconnect: bool - :rtype: ~azure.eventhub._async.sender_async.SenderAsync + :rtype: ~azure.eventhub.async_ops.sender_async.SenderAsync """ target = "amqps://{}{}".format(self.address.hostname, self.address.path) if operation: diff --git a/azure/eventhub/_async/receiver_async.py b/azure/eventhub/async_ops/receiver_async.py similarity index 98% rename from azure/eventhub/_async/receiver_async.py rename to azure/eventhub/async_ops/receiver_async.py index 0d49231..ad04520 100644 --- a/azure/eventhub/_async/receiver_async.py +++ b/azure/eventhub/async_ops/receiver_async.py @@ -29,7 +29,7 @@ def __init__( # pylint: disable=super-init-not-called Instantiate an async receiver. :param client: The parent EventHubClientAsync. - :type client: ~azure.eventhub._async.EventHubClientAsync + :type client: ~azure.eventhub.async_ops.EventHubClientAsync :param source: The source EventHub from which to receive events. :type source: ~uamqp.address.Source :param prefetch: The number of events to prefetch from the service @@ -78,7 +78,7 @@ async def open_async(self): context will be used to create a new handler before opening it. :param connection: The underlying client shared connection. - :type: connection: ~uamqp._async.connection_async.ConnectionAsync + :type: connection: ~uamqp.async_ops.connection_async.ConnectionAsync """ # pylint: disable=protected-access if self.redirected: diff --git a/azure/eventhub/_async/sender_async.py b/azure/eventhub/async_ops/sender_async.py similarity index 98% rename from azure/eventhub/_async/sender_async.py rename to azure/eventhub/async_ops/sender_async.py index bd72dd5..098c026 100644 --- a/azure/eventhub/_async/sender_async.py +++ b/azure/eventhub/async_ops/sender_async.py @@ -29,7 +29,7 @@ def __init__( # pylint: disable=super-init-not-called Instantiate an EventHub event SenderAsync handler. :param client: The parent EventHubClientAsync. - :type client: ~azure.eventhub._async.EventHubClientAsync + :type client: ~azure.eventhub.async_ops.EventHubClientAsync :param target: The URI of the EventHub to send to. :type target: str :param partition: The specific partition ID to send to. Default is `None`, in which case the service @@ -80,7 +80,7 @@ async def open_async(self): context will be used to create a new handler before opening it. :param connection: The underlying client shared connection. - :type: connection:~uamqp._async.connection_async.ConnectionAsync + :type: connection: ~uamqp.async_ops.connection_async.ConnectionAsync """ if self.redirected: self.target = self.redirected.address diff --git a/azure/eventhub/client.py b/azure/eventhub/client.py index 3a61c60..43c3b65 100644 --- a/azure/eventhub/client.py +++ b/azure/eventhub/client.py @@ -109,7 +109,7 @@ def __init__(self, address, username=None, password=None, debug=False, http_prox Additionally the following keys may also be present: 'username', 'password'. :type http_proxy: dict[str, Any] :param auth_timeout: The time in seconds to wait for a token to be authorized by the service. - The default value is 60 seconds. + The default value is 60 seconds. If set to 0, no timeout will be enforced from the client. :type auth_timeout: int """ self.container_id = "eventhub.pysdk-" + str(uuid.uuid4())[:8] @@ -142,6 +142,7 @@ def from_connection_string(cls, conn_str, eventhub=None, **kwargs): :type conn_str: str :param eventhub: The name of the EventHub, if the EntityName is not included in the connection string. + :type eventhub: str :param debug: Whether to output network trace logs to the logger. Default is `False`. :type debug: bool @@ -150,7 +151,7 @@ def from_connection_string(cls, conn_str, eventhub=None, **kwargs): Additionally the following keys may also be present: 'username', 'password'. :type http_proxy: dict[str, Any] :param auth_timeout: The time in seconds to wait for a token to be authorized by the service. - The default value is 60 seconds. + The default value is 60 seconds. If set to 0, no timeout will be enforced from the client. :type auth_timeout: int """ address, policy, key, entity = _parse_conn_str(conn_str) @@ -173,7 +174,7 @@ def from_iothub_connection_string(cls, conn_str, **kwargs): Additionally the following keys may also be present: 'username', 'password'. :type http_proxy: dict[str, Any] :param auth_timeout: The time in seconds to wait for a token to be authorized by the service. - The default value is 60 seconds. + The default value is 60 seconds. If set to 0, no timeout will be enforced from the client. :type auth_timeout: int """ address, policy, key, _ = _parse_conn_str(conn_str) @@ -297,11 +298,11 @@ def get_eventhub_info(self): """ Get details on the specified EventHub. Keys in the details dictionary include: - -'name' - -'type' - -'created_at' - -'partition_count' - -'partition_ids' + -'name' + -'type' + -'created_at' + -'partition_count' + -'partition_ids' :rtype: dict """ @@ -394,8 +395,7 @@ def add_epoch_receiver( def add_sender(self, partition=None, operation=None, send_timeout=60, keep_alive=30, auto_reconnect=True): """ - Add a sender to the client to send ~azure.eventhub.common.EventData object - to an EventHub. + Add a sender to the client to EventData object to an EventHub. :param partition: Optionally specify a particular partition to send to. If omitted, the events will be distributed to available partitions via diff --git a/azure/eventhub/common.py b/azure/eventhub/common.py index 035a812..af4db4e 100644 --- a/azure/eventhub/common.py +++ b/azure/eventhub/common.py @@ -45,7 +45,7 @@ def _error_handler(error): class EventData(object): """ The EventData class is a holder of event content. - Acts as a wrapper to an ~uamqp.message.Message object. + Acts as a wrapper to an uamqp.message.Message object. """ PROP_SEQ_NUMBER = b"x-opt-sequence-number" @@ -186,7 +186,7 @@ def body(self): """ The body of the event data object. - :rtype: bytes or generator[bytes] + :rtype: bytes or Generator[bytes] """ return self.message.get_data() @@ -194,6 +194,7 @@ def body(self): class Offset(object): """ The offset (position or timestamp) where a receiver starts. Examples: + Beginning of the event stream: >>> offset = Offset("-1") End of the event stream: @@ -238,6 +239,14 @@ def selector(self): class EventHubError(Exception): """ Represents an error happened in the client. + + :ivar message: The error message. + :vartype message: str + :ivar error: The error condition, if available. + :vartype error: str + :ivar details: The error details, if included in the + service response. + :vartype details: dict[str, str] """ def __init__(self, message, details=None): diff --git a/azure/eventhub/sender.py b/azure/eventhub/sender.py index e0ed738..b7fef5e 100644 --- a/azure/eventhub/sender.py +++ b/azure/eventhub/sender.py @@ -235,7 +235,7 @@ def transfer(self, event_data, callback=None): :type event_data: ~azure.eventhub.common.EventData :param callback: Callback to be run once the message has been send. This must be a function that accepts two arguments. - :type callback: func[~uamqp.constants.MessageSendResult, ~azure.eventhub.common.EventHubError] + :type callback: callable[~uamqp.constants.MessageSendResult, ~azure.eventhub.common.EventHubError] """ if self.error: raise self.error diff --git a/azure/eventprocessorhost/eh_partition_pump.py b/azure/eventprocessorhost/eh_partition_pump.py index 995440a..4ebd6a9 100644 --- a/azure/eventprocessorhost/eh_partition_pump.py +++ b/azure/eventprocessorhost/eh_partition_pump.py @@ -36,7 +36,7 @@ async def on_open_async(self): _opened_ok = True except Exception as err: # pylint: disable=broad-except _logger.warning( - "%r,%r PartitionPumpWarning: Failure creating client or receiver, " + "%r,%r PartitionPumpWarning: Failure creating client or receiver, " + "retrying: %r", self.host.guid, self.partition_context.partition_id, err) last_exception = err _retry_count += 1 @@ -91,7 +91,7 @@ async def clean_up_clients_async(self): async def on_closing_async(self, reason): """ - Overides partition pump on cleasing. + Overides partition pump on closing. :param reason: The reason for the shutdown. :type reason: str diff --git a/setup.py b/setup.py index 8efb8aa..891a80e 100644 --- a/setup.py +++ b/setup.py @@ -55,7 +55,7 @@ zip_safe=False, packages=find_packages(exclude=["examples", "tests"]), install_requires=[ - 'uamqp>=0.2.1,<0.3.0', + 'uamqp>=1.0.0,<2.0.0', 'msrestazure~=0.4.11', 'azure-common~=1.1', 'azure-storage~=0.36.0'