diff --git a/sdk/storage/azure-storage-queue/HISTORY.md b/sdk/storage/azure-storage-queue/HISTORY.md index e69de29bb2d1..057e7f4febe7 100644 --- a/sdk/storage/azure-storage-queue/HISTORY.md +++ b/sdk/storage/azure-storage-queue/HISTORY.md @@ -0,0 +1,35 @@ +# Change Log azure-storage-queue + +## Version 12.0.0b1: + +For release notes and more information please visit +https://aka.ms/azure-sdk-preview1-python + +## Version 2.0.1: +- Updated dependency on azure-storage-common. + +## Version 2.0.0: +- Support for 2018-11-09 REST version. + +## Version 1.4.0: + +- azure-storage-nspkg is not installed anymore on Python 3 (PEP420-based namespace package) + +## Version 1.3.0: + +- Support for 2018-03-28 REST version. Please see our REST API documentation and blog for information about the related added features. + +## Version 1.2.0rc1: + +- Support for 2017-11-09 REST version. Please see our REST API documentation and blog for information about the related added features. +- Added support for OAuth authentication for HTTPS requests(Please note that this feature is available in preview). + +## Version 1.1.0: + +- Support for 2017-07-29 REST version. Please see our REST API documentation and blogs for information about the related added features. +- Queue messages can now have an arbitrarily large or infinite time to live. +- Error message now contains the ErrorCode from the x-ms-error-code header value. + +## Version 1.0.0: + +- The package has switched from Apache 2.0 to the MIT license. \ No newline at end of file diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_queue_utils.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_queue_utils.py index f3ddee6b4821..49086b696a39 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_queue_utils.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_queue_utils.py @@ -103,6 +103,11 @@ def decode(self, content, response): class TextBase64EncodePolicy(MessageEncodePolicy): + """Base 64 message encoding policy for text messages. + + Encodes text (unicode) messages to base 64. If the input content + is not text, a TypeError will be raised. Input text must support UTF-8. + """ def encode(self, content): if not isinstance(content, six.text_type): @@ -111,6 +116,12 @@ def encode(self, content): class TextBase64DecodePolicy(MessageDecodePolicy): + """Message decoding policy for base 64-encoded messages into text. + + Decodes base64-encoded messages to text (unicode). If the input content + is not valid base 64, a DecodeError will be raised. Message data must + support UTF-8. + """ def decode(self, content, response): try: @@ -124,6 +135,11 @@ def decode(self, content, response): class BinaryBase64EncodePolicy(MessageEncodePolicy): + """Base 64 message encoding policy for binary messages. + + Encodes binary messages to base 64. If the input content + is not bytes, a TypeError will be raised. + """ def encode(self, content): if not isinstance(content, six.binary_type): @@ -132,6 +148,11 @@ def encode(self, content): class BinaryBase64DecodePolicy(MessageDecodePolicy): + """Message decoding policy for base 64-encoded messages into bytes. + + Decodes base64-encoded messages to bytes. If the input content + is not valid base 64, a DecodeError will be raised. + """ def decode(self, content, response): try: @@ -145,6 +166,11 @@ def decode(self, content, response): class TextXMLEncodePolicy(MessageEncodePolicy): + """XML message encoding policy for text messages. + + Encodes text (unicode) messages to XML. If the input content + is not text, a TypeError will be raised. + """ def encode(self, content): if not isinstance(content, six.text_type): @@ -153,18 +179,24 @@ def encode(self, content): class TextXMLDecodePolicy(MessageDecodePolicy): + """Message decoding policy for XML-encoded messages into text. + + Decodes XML-encoded messages to text (unicode). + """ def decode(self, content, response): return xml_unescape(content) class NoEncodePolicy(MessageEncodePolicy): + """Bypass any message content encoding.""" def encode(self, content): return content class NoDecodePolicy(MessageDecodePolicy): + """Bypass any message content decoding.""" def decode(self, content, response): return content diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/models.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/models.py index 9f39bcd30d0e..dbad2a1c58c8 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/models.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/models.py @@ -383,32 +383,31 @@ def __str__(self): class Services(object): - """ - Specifies the services accessible with the account SAS. + """Specifies the services accessible with the account SAS. :cvar Services Services.BLOB: The blob service. :cvar Services Services.FILE: The file service :cvar Services Services.QUEUE: The queue service. - :cvar Services Services.TABLE: The table service. :param bool blob: - Access to any blob service, for example, the `.BlockBlobService` + Access for the `~azure.storage.blob.blob_service_client.BlobServiceClient` :param bool queue: - Access to the `.QueueService` + Access for the `~azure.storage.queue.queue_service_client.QueueServiceClient` :param bool file: - Access to the `.FileService` - :param bool table: - Access to the TableService + Access for the `~azure.storage.file.file_service_client.FileServiceClient` :param str _str: A string representing the services. """ - def __init__(self, blob=False, queue=False, file=False, table=False, _str=None): + BLOB = None # type: Services + QUEUE = None # type: Services + FILE = None # type: Services + + def __init__(self, blob=False, queue=False, file=False, _str=None): if not _str: _str = '' self.blob = blob or ('b' in _str) self.queue = queue or ('q' in _str) self.file = file or ('f' in _str) - self.table = table or ('t' in _str) def __or__(self, other): return Services(_str=str(self) + str(other)) @@ -419,11 +418,9 @@ def __add__(self, other): def __str__(self): return (('b' if self.blob else '') + ('q' if self.queue else '') + - ('t' if self.table else '') + ('f' if self.file else '')) -Services.BLOB = Services(blob=True) # type: ignore -Services.QUEUE = Services(queue=True) # type: ignore -Services.TABLE = Services(table=True) # type: ignore -Services.FILE = Services(file=True) # type: ignore +Services.BLOB = Services(blob=True) +Services.QUEUE = Services(queue=True) +Services.FILE = Services(file=True) diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/utils.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/utils.py index 08f54e572f29..6d980d967891 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/utils.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/utils.py @@ -18,8 +18,8 @@ try: from urllib.parse import quote, unquote, parse_qs except ImportError: - from urlparse import parse_qs # type: ignore - from urllib2 import quote, unquote # type: ignore + from urlparse import parse_qs # type: ignore + from urllib2 import quote, unquote # type: ignore import six import isodate @@ -540,7 +540,6 @@ def is_credential_sastoken(credential): def add_metadata_headers(metadata): - # type: (Dict[str, str]) -> Dict[str, str] headers = {} if metadata: for key, value in metadata.items(): diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/models.py b/sdk/storage/azure-storage-queue/azure/storage/queue/models.py index f808917a106d..224508d959fc 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/models.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/models.py @@ -221,7 +221,11 @@ def _from_generated(cls, generated): class MessagesPaged(Paged): - """Queue messages paged. + """An iterable of Queue Messages. + + :ivar int results_per_page: The maximum number of results retrieved per API call. + :ivar current_page: The current page of listed results. + :vartype current_page: list(~azure.storage.queue.models.QueueMessage) :param callable command: Function to retrieve the next page of items. :param int results_per_page: The maximum number of messages to retrieve per @@ -277,10 +281,20 @@ def _from_generated(cls, generated): class QueuePropertiesPaged(Paged): - """Queue properties paged. + """An iterable of Queue properties. + + :ivar str service_endpoint: The service URL. + :ivar str prefix: A queue name prefix being used to filter the list. + :ivar str current_marker: The continuation token of the current page of results. + :ivar int results_per_page: The maximum number of results retrieved per API call. + :ivar str next_marker: The continuation token to retrieve the next page of results. + :ivar str location_mode: The location mode being used to list results. The available + options include "primary" and "secondary". + :ivar current_page: The current page of listed results. + :vartype current_page: list(~azure.storage.queue.models.QueueProperties) :param callable command: Function to retrieve the next page of items. - :param str prefix: Filters the results to return only containers whose names + :param str prefix: Filters the results to return only queues whose names begin with the specified prefix. :param int results_per_page: The maximum number of queue names to retrieve per call. @@ -352,6 +366,11 @@ class QueuePermissions(object): A string representing the permissions. """ + READ = None # type: QueuePermissions + ADD = None # type: QueuePermissions + UPDATE = None # type: QueuePermissions + PROCESS = None # type: QueuePermissions + def __init__(self, read=False, add=False, update=False, process=False, _str=None): if not _str: _str = '' @@ -373,7 +392,7 @@ def __str__(self): ('p' if self.process else '')) -QueuePermissions.READ = QueuePermissions(read=True) # type: ignore -QueuePermissions.ADD = QueuePermissions(add=True) # type: ignore -QueuePermissions.UPDATE = QueuePermissions(update=True) # type: ignore -QueuePermissions.PROCESS = QueuePermissions(process=True) # type: ignore +QueuePermissions.READ = QueuePermissions(read=True) +QueuePermissions.ADD = QueuePermissions(add=True) +QueuePermissions.UPDATE = QueuePermissions(update=True) +QueuePermissions.PROCESS = QueuePermissions(process=True) diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/queue_client.py b/sdk/storage/azure-storage-queue/azure/storage/queue/queue_client.py index 24c6e9c05145..72372a209f48 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/queue_client.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/queue_client.py @@ -45,13 +45,30 @@ class QueueClient(StorageAccountHostsMixin): - """Creates a new QueueClient. This client represents interaction with a specific - queue, although that queue may not yet exist. - + """A client to interact with a specific Queue. + + :ivar str url: + The full endpoint URL to the Queue, including SAS token if used. This could be + either the primary endpoint, or the secondard endpint depending on the current `location_mode`. + :ivar str primary_endpoint: + The full primary endpoint URL. + :ivar str primary_hostname: + The hostname of the primary endpoint. + :ivar str secondary_endpoint: + The full secondard endpoint URL if configured. If not available + a ValueError will be raised. To explicitly specify a secondary hostname, use the optional + `secondary_hostname` keyword argument on instantiation. + :ivar str secondary_hostname: + The hostname of the secondary endpoint. If not available this + will be None. To explicitly specify a secondary hostname, use the optional + `secondary_hostname` keyword argument on instantiation. + :ivar str location_mode: + The location mode that the client is currently using. By default + this will be "primary". Options include "primary" and "secondary". :param str queue_url: The full URI to the queue. This can also be a URL to the storage account, in which case the queue must also be specified. :param queue: The queue. If specified, this value will override - a queue value specified in the blob URL. + a queue value specified in the queue URL. :type queue: str or ~azure.storage.queue.models.QueueProperties :param credential: The credentials with which to authenticate. This is optional if the @@ -222,6 +239,7 @@ def generate_shared_access_signature( def create_queue(self, metadata=None, timeout=None, **kwargs): # type: (Optional[Dict[str, Any]], Optional[int], Optional[Any]) -> None """Creates a new queue in the storage account. + If a queue with the same name already exists, the operation fails. :param metadata: @@ -522,9 +540,7 @@ def receive_messages(self, messages_per_page=None, visibility_timeout=None, time The server timeout, expressed in seconds. :return: Returns a message iterator of dict-like Message objects. - Objects are also populated with the content although it is not - returned from the service. - :rtype: ~azure.storage.queue.models.QueueMessage + :rtype: ~azure.storage.queue.models.MessagesPaged Example: .. literalinclude:: ../tests/samples/test_samples_message_queue.py diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/queue_service_client.py b/sdk/storage/azure-storage-queue/azure/storage/queue/queue_service_client.py index d8fdc900d126..0dd7c3a9789b 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/queue_service_client.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/queue_service_client.py @@ -40,15 +40,33 @@ class QueueServiceClient(StorageAccountHostsMixin): - """A client interact with the Queue Service at the account level. + """A client to interact with the Queue Service at the account level. This client provides operations to retrieve and configure the account properties as well as list, create and delete queues within the account. For operations relating to a specific queue, a client for this entity can be retrieved using the :func:`~get_queue_client` function. + :ivar str url: + The full queue service endpoint URL, including SAS token if used. This could be + either the primary endpoint, or the secondard endpint depending on the current `location_mode`. + :ivar str primary_endpoint: + The full primary endpoint URL. + :ivar str primary_hostname: + The hostname of the primary endpoint. + :ivar str secondary_endpoint: + The full secondard endpoint URL if configured. If not available + a ValueError will be raised. To explicitly specify a secondary hostname, use the optional + `secondary_hostname` keyword argument on instantiation. + :ivar str secondary_hostname: + The hostname of the secondary endpoint. If not available this + will be None. To explicitly specify a secondary hostname, use the optional + `secondary_hostname` keyword argument on instantiation. + :ivar str location_mode: + The location mode that the client is currently using. By default + this will be "primary". Options include "primary" and "secondary". :param str account_url: - The URL to the queue storage account. Any other entities included + The URL to the queue service endpoint. Any other entities included in the URL path (e.g. queue) will be discarded. This URL can be optionally authenticated with a SAS token. :param credential: @@ -291,6 +309,7 @@ def list_queues( ): # type: (...) -> QueuePropertiesPaged """Returns a generator to list the queues under the specified account. + The generator will lazily follow the continuation tokens returned by the service and stop when all queues have been returned. @@ -338,9 +357,10 @@ def create_queue( **kwargs ): # type: (...) -> QueueClient - """Creates a new queue under the specified account. If a queue - with the same name already exists, the operation fails. Returns a client with - which to interact with the newly created queue. + """Creates a new queue under the specified account. + + If a queue with the same name already exists, the operation fails. + Returns a client with which to interact with the newly created queue. :param str name: The name of the queue to create. :param metadata: @@ -402,6 +422,7 @@ def delete_queue( def get_queue_client(self, queue, **kwargs): # type: (Union[QueueProperties, str], Optional[Any]) -> QueueClient """Get a client to interact with the specified queue. + The queue need not already exist. :param queue: