diff --git a/sdk/storage/azure-storage-blob/HISTORY.md b/sdk/storage/azure-storage-blob/HISTORY.md index fc7b15ce0895..17d5d47f3a31 100644 --- a/sdk/storage/azure-storage-blob/HISTORY.md +++ b/sdk/storage/azure-storage-blob/HISTORY.md @@ -1,6 +1,6 @@ # Change Log azure-storage-blob -## Version 12.0.0: +## Version 12.0.0b5: **Breaking changes** diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_container_client.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_container_client.py index afd99e081a93..bf96369ee3fb 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_container_client.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_container_client.py @@ -693,7 +693,7 @@ def upload_blob( :param metadata: Name-value pairs associated with the blob as metadata. :type metadata: dict(str, str) - :param str encoding: + :keyword str encoding: Defaults to UTF-8. :keyword bool overwrite: Whether the blob to be uploaded should overwrite the current data. If True, upload_blob will silently overwrite the existing data. If set to False, the @@ -808,10 +808,6 @@ def delete_blob( :param blob: The blob with which to interact. If specified, this value will override a blob value specified in the blob URL. :type blob: str or ~azure.storage.blob.BlobProperties - :param str delete_snapshots: - Required if the blob has associated snapshots. Values include: - - "only": Deletes only the blobs snapshots. - - "include": Deletes the blob along with all snapshots. :param str delete_snapshots: Required if the blob has associated snapshots. Values include: - "only": Deletes only the blobs snapshots. diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client.py index de86215853d1..5999a495b97f 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client.py @@ -178,6 +178,7 @@ def _create_pipeline(self, credential, **kwargs): policies = [ QueueMessagePolicy(), config.headers_policy, + config.proxy_policy, config.user_agent_policy, StorageContentValidation(), StorageRequestHook(**kwargs), diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client_async.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client_async.py index 8d2265ec1181..a64531d415ac 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client_async.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_shared/base_client_async.py @@ -82,6 +82,7 @@ def _create_pipeline(self, credential, **kwargs): policies = [ QueueMessagePolicy(), config.headers_policy, + config.proxy_policy, config.user_agent_policy, StorageContentValidation(), StorageRequestHook(**kwargs), diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_version.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_version.py index d8737a7b65ef..58517ac93b1a 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_version.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_version.py @@ -4,4 +4,4 @@ # license information. # -------------------------------------------------------------------------- -VERSION = "12.0.0b4" +VERSION = "12.0.0b5" diff --git a/sdk/storage/azure-storage-blob/setup.py b/sdk/storage/azure-storage-blob/setup.py index c09213e84da1..cef2ff6d71f5 100644 --- a/sdk/storage/azure-storage-blob/setup.py +++ b/sdk/storage/azure-storage-blob/setup.py @@ -79,6 +79,7 @@ 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'License :: OSI Approved :: MIT License', ], zip_safe=False, diff --git a/sdk/storage/azure-storage-file/HISTORY.md b/sdk/storage/azure-storage-file/HISTORY.md index d29d2d22e440..d2c7679a8e2c 100644 --- a/sdk/storage/azure-storage-file/HISTORY.md +++ b/sdk/storage/azure-storage-file/HISTORY.md @@ -1,6 +1,6 @@ # Change Log azure-storage-file -## Version 12.0.0: +## Version 12.0.0b5: **Breaking changes** diff --git a/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client.py b/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client.py index e26ba3fda37f..5999a495b97f 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client.py @@ -28,7 +28,7 @@ from azure.core.configuration import Configuration from azure.core.exceptions import HttpResponseError from azure.core.pipeline import Pipeline -from azure.core.pipeline.transport import RequestsTransport, HttpTransport # pylint: disable=unused-import +from azure.core.pipeline.transport import RequestsTransport, HttpTransport from azure.core.pipeline.policies import ( RedirectPolicy, ContentDecodePolicy, @@ -54,7 +54,7 @@ ExponentialRetry, ) from .._generated.models import StorageErrorException -from .response_handlers import process_storage_error +from .response_handlers import process_storage_error, PartialBatchErrorException _LOGGER = logging.getLogger(__name__) @@ -178,6 +178,7 @@ def _create_pipeline(self, credential, **kwargs): policies = [ QueueMessagePolicy(), config.headers_policy, + config.proxy_policy, config.user_agent_policy, StorageContentValidation(), StorageRequestHook(**kwargs), @@ -199,6 +200,8 @@ def _batch_send( ): """Given a series of request, do a Storage batch call. """ + # Pop it here, so requests doesn't feel bad about additional kwarg + raise_on_any_failure = kwargs.pop("raise_on_any_failure", True) request = self._client._client.post( # pylint: disable=protected-access url='https://{}/?comp=batch'.format(self.primary_hostname), headers={ @@ -222,7 +225,17 @@ def _batch_send( try: if response.status_code not in [202]: raise HttpResponseError(response=response) - return response.parts() + parts = response.parts() + if raise_on_any_failure: + parts = list(response.parts()) + if any(p for p in parts if not 200 <= p.status_code < 300): + error = PartialBatchErrorException( + message="There is a partial failure in the batch operation.", + response=response, parts=parts + ) + raise error + return iter(parts) + return parts except StorageErrorException as error: process_storage_error(error) diff --git a/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client_async.py b/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client_async.py index 4d3fb4c19286..a64531d415ac 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client_async.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/_shared/base_client_async.py @@ -9,8 +9,8 @@ TYPE_CHECKING ) import logging - from azure.core.pipeline import AsyncPipeline +from azure.core.async_paging import AsyncList from azure.core.exceptions import HttpResponseError from azure.core.pipeline.policies import ( ContentDecodePolicy, @@ -34,13 +34,12 @@ from .policies_async import AsyncStorageResponseHook from .._generated.models import StorageErrorException -from .response_handlers import process_storage_error +from .response_handlers import process_storage_error, PartialBatchErrorException if TYPE_CHECKING: from azure.core.pipeline import Pipeline from azure.core.pipeline.transport import HttpRequest from azure.core.configuration import Configuration - _LOGGER = logging.getLogger(__name__) @@ -83,6 +82,7 @@ def _create_pipeline(self, credential, **kwargs): policies = [ QueueMessagePolicy(), config.headers_policy, + config.proxy_policy, config.user_agent_policy, StorageContentValidation(), StorageRequestHook(**kwargs), @@ -104,6 +104,8 @@ async def _batch_send( ): """Given a series of request, do a Storage batch call. """ + # Pop it here, so requests doesn't feel bad about additional kwarg + raise_on_any_failure = kwargs.pop("raise_on_any_failure", True) request = self._client._client.post( # pylint: disable=protected-access url='https://{}/?comp=batch'.format(self.primary_hostname), headers={ @@ -127,7 +129,19 @@ async def _batch_send( try: if response.status_code not in [202]: raise HttpResponseError(response=response) - return response.parts() # Return an AsyncIterator + parts = response.parts() # Return an AsyncIterator + if raise_on_any_failure: + parts_list = [] + async for part in parts: + parts_list.append(part) + if any(p for p in parts_list if not 200 <= p.status_code < 300): + error = PartialBatchErrorException( + message="There is a partial failure in the batch operation.", + response=response, parts=parts_list + ) + raise error + return AsyncList(parts_list) + return parts except StorageErrorException as error: process_storage_error(error) diff --git a/sdk/storage/azure-storage-file/azure/storage/file/_shared/response_handlers.py b/sdk/storage/azure-storage-file/azure/storage/file/_shared/response_handlers.py index fbf9889d762c..ce625d589504 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/_shared/response_handlers.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/_shared/response_handlers.py @@ -31,6 +31,19 @@ _LOGGER = logging.getLogger(__name__) +class PartialBatchErrorException(HttpResponseError): + """There is a partial failure in batch operations. + + :param message: The message of the exception. + :param response: Server response to be deserialized. + :param parts: A list of the parts in multipart response. + """ + + def __init__(self, message, response, parts): + self.parts = parts + super(PartialBatchErrorException, self).__init__(message=message, response=response) + + def parse_length_from_content_range(content_range): ''' Parses the blob length from the content range header: bytes 1-3/65537 diff --git a/sdk/storage/azure-storage-file/azure/storage/file/_version.py b/sdk/storage/azure-storage-file/azure/storage/file/_version.py index 5cd1ed1b1cef..ce4ecebdf250 100644 --- a/sdk/storage/azure-storage-file/azure/storage/file/_version.py +++ b/sdk/storage/azure-storage-file/azure/storage/file/_version.py @@ -4,4 +4,4 @@ # license information. # -------------------------------------------------------------------------- -VERSION = '12.0.0b4' +VERSION = '12.0.0b5' diff --git a/sdk/storage/azure-storage-file/setup.py b/sdk/storage/azure-storage-file/setup.py index 3bcb6cd55049..f41c7c336ab4 100644 --- a/sdk/storage/azure-storage-file/setup.py +++ b/sdk/storage/azure-storage-file/setup.py @@ -67,6 +67,7 @@ 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'License :: OSI Approved :: MIT License', ], zip_safe=False, diff --git a/sdk/storage/azure-storage-queue/HISTORY.md b/sdk/storage/azure-storage-queue/HISTORY.md index 0b0d14f44760..3abb93abdf4b 100644 --- a/sdk/storage/azure-storage-queue/HISTORY.md +++ b/sdk/storage/azure-storage-queue/HISTORY.md @@ -1,6 +1,6 @@ # Change Log azure-storage-queue -## Version 12.0.0: +## Version 12.0.0b5: **Breaking changes** diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client.py index e26ba3fda37f..5999a495b97f 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client.py @@ -28,7 +28,7 @@ from azure.core.configuration import Configuration from azure.core.exceptions import HttpResponseError from azure.core.pipeline import Pipeline -from azure.core.pipeline.transport import RequestsTransport, HttpTransport # pylint: disable=unused-import +from azure.core.pipeline.transport import RequestsTransport, HttpTransport from azure.core.pipeline.policies import ( RedirectPolicy, ContentDecodePolicy, @@ -54,7 +54,7 @@ ExponentialRetry, ) from .._generated.models import StorageErrorException -from .response_handlers import process_storage_error +from .response_handlers import process_storage_error, PartialBatchErrorException _LOGGER = logging.getLogger(__name__) @@ -178,6 +178,7 @@ def _create_pipeline(self, credential, **kwargs): policies = [ QueueMessagePolicy(), config.headers_policy, + config.proxy_policy, config.user_agent_policy, StorageContentValidation(), StorageRequestHook(**kwargs), @@ -199,6 +200,8 @@ def _batch_send( ): """Given a series of request, do a Storage batch call. """ + # Pop it here, so requests doesn't feel bad about additional kwarg + raise_on_any_failure = kwargs.pop("raise_on_any_failure", True) request = self._client._client.post( # pylint: disable=protected-access url='https://{}/?comp=batch'.format(self.primary_hostname), headers={ @@ -222,7 +225,17 @@ def _batch_send( try: if response.status_code not in [202]: raise HttpResponseError(response=response) - return response.parts() + parts = response.parts() + if raise_on_any_failure: + parts = list(response.parts()) + if any(p for p in parts if not 200 <= p.status_code < 300): + error = PartialBatchErrorException( + message="There is a partial failure in the batch operation.", + response=response, parts=parts + ) + raise error + return iter(parts) + return parts except StorageErrorException as error: process_storage_error(error) diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client_async.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client_async.py index 4d3fb4c19286..a64531d415ac 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client_async.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/base_client_async.py @@ -9,8 +9,8 @@ TYPE_CHECKING ) import logging - from azure.core.pipeline import AsyncPipeline +from azure.core.async_paging import AsyncList from azure.core.exceptions import HttpResponseError from azure.core.pipeline.policies import ( ContentDecodePolicy, @@ -34,13 +34,12 @@ from .policies_async import AsyncStorageResponseHook from .._generated.models import StorageErrorException -from .response_handlers import process_storage_error +from .response_handlers import process_storage_error, PartialBatchErrorException if TYPE_CHECKING: from azure.core.pipeline import Pipeline from azure.core.pipeline.transport import HttpRequest from azure.core.configuration import Configuration - _LOGGER = logging.getLogger(__name__) @@ -83,6 +82,7 @@ def _create_pipeline(self, credential, **kwargs): policies = [ QueueMessagePolicy(), config.headers_policy, + config.proxy_policy, config.user_agent_policy, StorageContentValidation(), StorageRequestHook(**kwargs), @@ -104,6 +104,8 @@ async def _batch_send( ): """Given a series of request, do a Storage batch call. """ + # Pop it here, so requests doesn't feel bad about additional kwarg + raise_on_any_failure = kwargs.pop("raise_on_any_failure", True) request = self._client._client.post( # pylint: disable=protected-access url='https://{}/?comp=batch'.format(self.primary_hostname), headers={ @@ -127,7 +129,19 @@ async def _batch_send( try: if response.status_code not in [202]: raise HttpResponseError(response=response) - return response.parts() # Return an AsyncIterator + parts = response.parts() # Return an AsyncIterator + if raise_on_any_failure: + parts_list = [] + async for part in parts: + parts_list.append(part) + if any(p for p in parts_list if not 200 <= p.status_code < 300): + error = PartialBatchErrorException( + message="There is a partial failure in the batch operation.", + response=response, parts=parts_list + ) + raise error + return AsyncList(parts_list) + return parts except StorageErrorException as error: process_storage_error(error) diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/response_handlers.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/response_handlers.py index fbf9889d762c..ce625d589504 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/response_handlers.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_shared/response_handlers.py @@ -31,6 +31,19 @@ _LOGGER = logging.getLogger(__name__) +class PartialBatchErrorException(HttpResponseError): + """There is a partial failure in batch operations. + + :param message: The message of the exception. + :param response: Server response to be deserialized. + :param parts: A list of the parts in multipart response. + """ + + def __init__(self, message, response, parts): + self.parts = parts + super(PartialBatchErrorException, self).__init__(message=message, response=response) + + def parse_length_from_content_range(content_range): ''' Parses the blob length from the content range header: bytes 1-3/65537 diff --git a/sdk/storage/azure-storage-queue/azure/storage/queue/_version.py b/sdk/storage/azure-storage-queue/azure/storage/queue/_version.py index cc32a533d2ce..6ba1d06c4c45 100644 --- a/sdk/storage/azure-storage-queue/azure/storage/queue/_version.py +++ b/sdk/storage/azure-storage-queue/azure/storage/queue/_version.py @@ -9,4 +9,4 @@ # regenerated. # -------------------------------------------------------------------------- -VERSION = "12.0.0b4" +VERSION = "12.0.0b5" diff --git a/sdk/storage/azure-storage-queue/setup.py b/sdk/storage/azure-storage-queue/setup.py index 7b86ed0ba6a5..8615cdfab4b2 100644 --- a/sdk/storage/azure-storage-queue/setup.py +++ b/sdk/storage/azure-storage-queue/setup.py @@ -67,6 +67,7 @@ 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'License :: OSI Approved :: MIT License', ], zip_safe=False,