From 23aa10e934eb40c2e2827139fe5c29d5954039ce Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Thu, 23 Jun 2022 15:39:49 -0700 Subject: [PATCH 01/21] Don't import from aiohttp in blob.aio --- .../azure/storage/blob/aio/_download_async.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py index c95c3c6dfc22..b1cfe5362ec9 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py @@ -12,8 +12,7 @@ import warnings from typing import AsyncIterator -from aiohttp import ClientPayloadError -from azure.core.exceptions import HttpResponseError, ServiceResponseError +from azure.core.exceptions import HttpResponseError, ServiceResponseError, IncompleteReadError from .._shared.encryption import ( adjust_blob_size_for_encryption, decrypt_blob, @@ -114,7 +113,7 @@ async def _download_chunk(self, chunk_start, chunk_end): except HttpResponseError as error: process_storage_error(error) - except ClientPayloadError as error: + except IncompleteReadError as error: retry_total -= 1 if retry_total <= 0: raise ServiceResponseError(error, error=error) From 802de5c01aa035accfdd696e1747f1fc26f16441 Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Thu, 23 Jun 2022 16:44:53 -0700 Subject: [PATCH 02/21] update changelog --- sdk/storage/azure-storage-blob/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/storage/azure-storage-blob/CHANGELOG.md b/sdk/storage/azure-storage-blob/CHANGELOG.md index 92db7dfd442b..3d41ffc47459 100644 --- a/sdk/storage/azure-storage-blob/CHANGELOG.md +++ b/sdk/storage/azure-storage-blob/CHANGELOG.md @@ -6,6 +6,7 @@ ### Bugs Fixed +- Removed `aiohttp` import from `azure.storage.blob._download_async`. ## 12.13.0b1 (2022-06-15) ### Features Added From aa7071947c7786b2df139b542b672df89ff62348 Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Thu, 23 Jun 2022 17:04:23 -0700 Subject: [PATCH 03/21] remove dead code --- .../azure/storage/blob/aio/_download_async.py | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py index b1cfe5362ec9..991bcd50bd45 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py @@ -12,7 +12,7 @@ import warnings from typing import AsyncIterator -from azure.core.exceptions import HttpResponseError, ServiceResponseError, IncompleteReadError +from azure.core.exceptions import HttpResponseError from .._shared.encryption import ( adjust_blob_size_for_encryption, decrypt_blob, @@ -98,7 +98,6 @@ async def _download_chunk(self, chunk_start, chunk_end): check_content_md5=self.validate_content ) retry_active = True - retry_total = 3 while retry_active: try: _, response = await self.client.download( @@ -110,14 +109,8 @@ async def _download_chunk(self, chunk_start, chunk_end): **self.request_options ) retry_active = False - except HttpResponseError as error: process_storage_error(error) - except IncompleteReadError as error: - retry_total -= 1 - if retry_total <= 0: - raise ServiceResponseError(error, error=error) - await asyncio.sleep(1) chunk_data = await process_content(response, offset[0], offset[1], self.encryption_options) @@ -323,7 +316,6 @@ async def _initial_request(self): check_content_md5=self._validate_content) retry_active = True - retry_total = 3 while retry_active: try: location_mode, response = await self._clients.blob.download( @@ -374,12 +366,6 @@ async def _initial_request(self): else: process_storage_error(error) - except ClientPayloadError as error: - retry_total -= 1 - if retry_total <= 0: - raise ServiceResponseError(error, error=error) - await asyncio.sleep(1) - # get page ranges to optimize downloading sparse page blob if response.properties.blob_type == 'PageBlob': try: From a9d97d6fbce4eb90fcba3b151ee2bf05e95143aa Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Fri, 24 Jun 2022 08:27:53 -0700 Subject: [PATCH 04/21] changelog formatting --- sdk/storage/azure-storage-blob/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/azure-storage-blob/CHANGELOG.md b/sdk/storage/azure-storage-blob/CHANGELOG.md index 3d41ffc47459..14aabc1d1b09 100644 --- a/sdk/storage/azure-storage-blob/CHANGELOG.md +++ b/sdk/storage/azure-storage-blob/CHANGELOG.md @@ -5,8 +5,8 @@ ### Features Added ### Bugs Fixed - - Removed `aiohttp` import from `azure.storage.blob._download_async`. + ## 12.13.0b1 (2022-06-15) ### Features Added From 46efbf98203ff41c685b408f0d25634d2b60a5d0 Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Mon, 27 Jun 2022 09:54:41 -0700 Subject: [PATCH 05/21] add retries back in --- .../azure/storage/blob/aio/_download_async.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py index 991bcd50bd45..e89f756eabce 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py @@ -12,7 +12,7 @@ import warnings from typing import AsyncIterator -from azure.core.exceptions import HttpResponseError +from azure.core.exceptions import HttpResponseError, ServiceResponseError from .._shared.encryption import ( adjust_blob_size_for_encryption, decrypt_blob, @@ -98,6 +98,7 @@ async def _download_chunk(self, chunk_start, chunk_end): check_content_md5=self.validate_content ) retry_active = True + retry_total = 3 while retry_active: try: _, response = await self.client.download( @@ -109,6 +110,13 @@ async def _download_chunk(self, chunk_start, chunk_end): **self.request_options ) retry_active = False + + except ServiceResponseError as error: + retry_total -= 1 + if retry_total <= 0: + raise ServiceResponseError(error, error=error) + await asyncio.sleep(1) + except HttpResponseError as error: process_storage_error(error) @@ -316,6 +324,7 @@ async def _initial_request(self): check_content_md5=self._validate_content) retry_active = True + retry_total = 3 while retry_active: try: location_mode, response = await self._clients.blob.download( @@ -345,6 +354,12 @@ async def _initial_request(self): self.size = self._file_size retry_active = False + except ServiceResponseError as error: + retry_total -= 1 + if retry_total <= 0: + raise error + await asyncio.sleep(1) + except HttpResponseError as error: if self._start_range is None and error.response.status_code == 416: # Get range will fail on an empty file. If the user did not From 5ba8e9809a360858a5c0602da4b1743ea8e92756 Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Mon, 27 Jun 2022 10:06:00 -0700 Subject: [PATCH 06/21] Catch correct exception --- .../azure/storage/blob/aio/_download_async.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py index e89f756eabce..a0785fecd16d 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py @@ -111,7 +111,7 @@ async def _download_chunk(self, chunk_start, chunk_end): ) retry_active = False - except ServiceResponseError as error: + except IncompleteReadError as error: retry_total -= 1 if retry_total <= 0: raise ServiceResponseError(error, error=error) @@ -354,10 +354,10 @@ async def _initial_request(self): self.size = self._file_size retry_active = False - except ServiceResponseError as error: + except IncompleteReadError as error: retry_total -= 1 if retry_total <= 0: - raise error + raise ServiceResponseError(error, error=error) await asyncio.sleep(1) except HttpResponseError as error: From ab942ac32e95546c8e23dceeb9ef02ed96a607a5 Mon Sep 17 00:00:00 2001 From: Laurent Mazuel Date: Mon, 27 Jun 2022 11:46:25 -0700 Subject: [PATCH 07/21] Update sdk/storage/azure-storage-blob/CHANGELOG.md --- sdk/storage/azure-storage-blob/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/azure-storage-blob/CHANGELOG.md b/sdk/storage/azure-storage-blob/CHANGELOG.md index 14aabc1d1b09..e5e47d097871 100644 --- a/sdk/storage/azure-storage-blob/CHANGELOG.md +++ b/sdk/storage/azure-storage-blob/CHANGELOG.md @@ -5,7 +5,7 @@ ### Features Added ### Bugs Fixed -- Removed `aiohttp` import from `azure.storage.blob._download_async`. +- Removed `aiohttp` import from `azure.storage.blob._download_async`. #24965 ## 12.13.0b1 (2022-06-15) From 307bd4823777a0829751e8e03da1db8bed2e35b5 Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Tue, 28 Jun 2022 09:29:23 -0700 Subject: [PATCH 08/21] missing import --- .../azure/storage/blob/aio/_download_async.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py index b7a9fa49876e..ddcadc22e7bc 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py @@ -13,7 +13,7 @@ import asyncio -from azure.core.exceptions import HttpResponseError, ServiceResponseError +from azure.core.exceptions import HttpResponseError, ServiceResponseError, IncompleteReadError from .._shared.request_handlers import validate_and_format_range_headers from .._shared.response_handlers import process_storage_error, parse_length_from_content_range From 40f49f5911cf5e348648be478fae78b4d4c9149f Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Tue, 28 Jun 2022 12:33:23 -0700 Subject: [PATCH 09/21] catch azure.core exceptions --- .../azure-storage-blob/azure/storage/blob/_download.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_download.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_download.py index 854340b0b8de..5624d9695449 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_download.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_download.py @@ -11,8 +11,7 @@ from io import BytesIO from typing import Iterator, Union -import requests -from azure.core.exceptions import HttpResponseError, ServiceResponseError +from azure.core.exceptions import HttpResponseError, IncompleteReadError, ServiceResponseError from azure.core.tracing.common import with_current_context from ._shared.request_handlers import validate_and_format_range_headers @@ -211,7 +210,7 @@ def _download_chunk(self, chunk_start, chunk_end): try: chunk_data = process_content(response, offset[0], offset[1], self.encryption_options) retry_active = False - except (requests.exceptions.ChunkedEncodingError, requests.exceptions.ConnectionError) as error: + except IncompleteReadError as error: retry_total -= 1 if retry_total <= 0: raise ServiceResponseError(error, error=error) @@ -467,7 +466,7 @@ def _initial_request(self): self._encryption_options ) retry_active = False - except (requests.exceptions.ChunkedEncodingError, requests.exceptions.ConnectionError) as error: + except IncompleteReadError as error: retry_total -= 1 if retry_total <= 0: raise ServiceResponseError(error, error=error) From f82a0e9ac4ad23e7ab5f208e2a7a73b25530bd4e Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Tue, 28 Jun 2022 15:52:37 -0700 Subject: [PATCH 10/21] Revert --- .../azure-storage-blob/azure/storage/blob/_download.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/_download.py b/sdk/storage/azure-storage-blob/azure/storage/blob/_download.py index 5624d9695449..854340b0b8de 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/_download.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/_download.py @@ -11,7 +11,8 @@ from io import BytesIO from typing import Iterator, Union -from azure.core.exceptions import HttpResponseError, IncompleteReadError, ServiceResponseError +import requests +from azure.core.exceptions import HttpResponseError, ServiceResponseError from azure.core.tracing.common import with_current_context from ._shared.request_handlers import validate_and_format_range_headers @@ -210,7 +211,7 @@ def _download_chunk(self, chunk_start, chunk_end): try: chunk_data = process_content(response, offset[0], offset[1], self.encryption_options) retry_active = False - except IncompleteReadError as error: + except (requests.exceptions.ChunkedEncodingError, requests.exceptions.ConnectionError) as error: retry_total -= 1 if retry_total <= 0: raise ServiceResponseError(error, error=error) @@ -466,7 +467,7 @@ def _initial_request(self): self._encryption_options ) retry_active = False - except IncompleteReadError as error: + except (requests.exceptions.ChunkedEncodingError, requests.exceptions.ConnectionError) as error: retry_total -= 1 if retry_total <= 0: raise ServiceResponseError(error, error=error) From 5f340c00323a956d562d12d05f3ccb3200290971 Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Tue, 28 Jun 2022 17:27:19 -0700 Subject: [PATCH 11/21] changelog typo --- sdk/storage/azure-storage-blob/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/azure-storage-blob/CHANGELOG.md b/sdk/storage/azure-storage-blob/CHANGELOG.md index e5e47d097871..27a2835f6dcf 100644 --- a/sdk/storage/azure-storage-blob/CHANGELOG.md +++ b/sdk/storage/azure-storage-blob/CHANGELOG.md @@ -5,7 +5,7 @@ ### Features Added ### Bugs Fixed -- Removed `aiohttp` import from `azure.storage.blob._download_async`. #24965 +- Removed `aiohttp` import from `azure.storage.blob.aio._download_async`. #24965 ## 12.13.0b1 (2022-06-15) From 685e130144a3d6380b7b9016941ddf5967993f58 Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Thu, 30 Jun 2022 13:16:38 -0700 Subject: [PATCH 12/21] changelog formatting --- sdk/storage/azure-storage-blob/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/azure-storage-blob/CHANGELOG.md b/sdk/storage/azure-storage-blob/CHANGELOG.md index 27a2835f6dcf..e6d64c3f25b2 100644 --- a/sdk/storage/azure-storage-blob/CHANGELOG.md +++ b/sdk/storage/azure-storage-blob/CHANGELOG.md @@ -5,7 +5,7 @@ ### Features Added ### Bugs Fixed -- Removed `aiohttp` import from `azure.storage.blob.aio._download_async`. #24965 +- Removed `aiohttp` import from `azure.storage.blob.aio._download_async`. (#24965) ## 12.13.0b1 (2022-06-15) From a3144d0b1b3341b1a1fa77c98fecf6b86402dd7a Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Thu, 30 Jun 2022 20:31:02 -0700 Subject: [PATCH 13/21] more changelog --- sdk/storage/azure-storage-blob/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/azure-storage-blob/CHANGELOG.md b/sdk/storage/azure-storage-blob/CHANGELOG.md index e6d64c3f25b2..21ed6ec382ae 100644 --- a/sdk/storage/azure-storage-blob/CHANGELOG.md +++ b/sdk/storage/azure-storage-blob/CHANGELOG.md @@ -5,7 +5,7 @@ ### Features Added ### Bugs Fixed -- Removed `aiohttp` import from `azure.storage.blob.aio._download_async`. (#24965) +- Removed forced `aiohttp` import from storage async download. (#24965) ## 12.13.0b1 (2022-06-15) From d1d7fefa2297ce68834996e2ba7591efa107393d Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Thu, 30 Jun 2022 20:38:12 -0700 Subject: [PATCH 14/21] merge main --- sdk/storage/azure-storage-blob/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdk/storage/azure-storage-blob/CHANGELOG.md b/sdk/storage/azure-storage-blob/CHANGELOG.md index 21ed6ec382ae..18d56c848932 100644 --- a/sdk/storage/azure-storage-blob/CHANGELOG.md +++ b/sdk/storage/azure-storage-blob/CHANGELOG.md @@ -5,6 +5,8 @@ ### Features Added ### Bugs Fixed +- Stable release of features from 12.13.0b1. +- Added support for deleting versions in `delete_blobs` by supplying `version_id`. - Removed forced `aiohttp` import from storage async download. (#24965) ## 12.13.0b1 (2022-06-15) From 5fbf04383c509799746e4c4bcfcece8451225d98 Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Mon, 25 Jul 2022 16:47:45 -0700 Subject: [PATCH 15/21] start retry tests --- .../azure-storage-blob/tests/test_retry.py | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/sdk/storage/azure-storage-blob/tests/test_retry.py b/sdk/storage/azure-storage-blob/tests/test_retry.py index 6a15b04dd038..3f082d43b836 100644 --- a/sdk/storage/azure-storage-blob/tests/test_retry.py +++ b/sdk/storage/azure-storage-blob/tests/test_retry.py @@ -3,15 +3,19 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- -import unittest +import asyncio +from unittest import mock import pytest +from aiohttp import ClientResponse +from aiohttp.client_exceptions import ClientPayloadError from azure.core.exceptions import ( HttpResponseError, ResourceExistsError, AzureError, ClientAuthenticationError ) +from azure.storage.blob import aio from azure.core.pipeline.transport import( RequestsTransport ) @@ -433,7 +437,33 @@ def test_invalid_account_key(self, storage_account_name, storage_account_key): # Assert # No retry should be performed since the signing error is fatal self.assertEqual(retry_counter.count, 0) + @pytest.mark.live_test_only + @pytest.mark.live_test_only + @BlobPreparer() + async def test_async_streaming_retry(self, storage_account_name, storage_account_key): + """Test that retry mechanisms are working when streaming data.""" + container_name = self.get_resource_name('utcontainer') + service = self._create_storage_service( + BlobServiceClient, storage_account_name, storage_account_key) + container = service.get_container_client(container_name) + container.create_container() + assert container.exists() + blob_name = "myblob" + container.upload_blob(blob_name, b"abcde") + + read_mock = mock.Mock() + future = asyncio.Future() + future.set_exception( + read_mock.side_effect = ClientPayloadError() + with mock.patch.object(ClientResponse, "read", read_mock): + blob = aio.BlobClient( + account_url=service.url, + container_name=container_name, + blob_name=blob_name, + credential=storage_account_key + ) + blob = container.get_blob_client(blob=blob_name) + blob.download_blob() # ------------------------------------------------------------------------------ - From 6aa0a3a9d6b4722071c30a0e0747b3a0ca6d1bfa Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Thu, 28 Jul 2022 10:33:16 -0700 Subject: [PATCH 16/21] remove unused retry --- .../azure/storage/blob/aio/_download_async.py | 131 ++++++++---------- ...etry_async.test_streaming_retry_async.yaml | 101 ++++++++++++++ .../azure-storage-blob/tests/test_retry.py | 30 ---- .../tests/test_retry_async.py | 50 ++++++- 4 files changed, 199 insertions(+), 113 deletions(-) create mode 100644 sdk/storage/azure-storage-blob/tests/recordings/test_retry_async.test_streaming_retry_async.yaml diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py index 72a752ed6b75..ce271c6065c2 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py @@ -102,28 +102,18 @@ async def _download_chunk(self, chunk_start, chunk_end): download_range[1], check_content_md5=self.validate_content ) - retry_active = True - retry_total = 3 - while retry_active: - try: - _, response = await self.client.download( - range=range_header, - range_get_content_md5=range_validation, - validate_content=self.validate_content, - data_stream_total=self.total_size, - download_stream_current=self.progress_total, - **self.request_options - ) - retry_active = False - - except IncompleteReadError as error: - retry_total -= 1 - if retry_total <= 0: - raise ServiceResponseError(error, error=error) - await asyncio.sleep(1) + try: + _, response = await self.client.download( + range=range_header, + range_get_content_md5=range_validation, + validate_content=self.validate_content, + data_stream_total=self.total_size, + download_stream_current=self.progress_total, + **self.request_options + ) - except HttpResponseError as error: - process_storage_error(error) + except HttpResponseError as error: + process_storage_error(error) chunk_data = await process_content(response, offset[0], offset[1], self.encryption_options) @@ -333,64 +323,53 @@ async def _initial_request(self): end_range_required=False, check_content_md5=self._validate_content) - retry_active = True - retry_total = 3 - while retry_active: - try: - location_mode, response = await self._clients.blob.download( - range=range_header, - range_get_content_md5=range_validation, - validate_content=self._validate_content, - data_stream_total=None, - download_stream_current=0, - **self._request_options) - - # Check the location we read from to ensure we use the same one - # for subsequent requests. - self._location_mode = location_mode - - # Parse the total file size and adjust the download size if ranges - # were specified - self._file_size = parse_length_from_content_range(response.properties.content_range) - # Remove any extra encryption data size from blob size - self._file_size = adjust_blob_size_for_encryption(self._file_size, self._encryption_data) - - if self._end_range is not None: - # Use the length unless it is over the end of the file - self.size = min(self._file_size, self._end_range - self._start_range + 1) - elif self._start_range is not None: - self.size = self._file_size - self._start_range - else: - self.size = self._file_size - retry_active = False - - except IncompleteReadError as error: - retry_total -= 1 - if retry_total <= 0: - raise ServiceResponseError(error, error=error) - await asyncio.sleep(1) + try: + location_mode, response = await self._clients.blob.download( + range=range_header, + range_get_content_md5=range_validation, + validate_content=self._validate_content, + data_stream_total=None, + download_stream_current=0, + **self._request_options) - except HttpResponseError as error: - if self._start_range is None and error.response.status_code == 416: - # Get range will fail on an empty file. If the user did not - # request a range, do a regular get request in order to get - # any properties. - try: - _, response = await self._clients.blob.download( - validate_content=self._validate_content, - data_stream_total=0, - download_stream_current=0, - **self._request_options) - retry_active = False - except HttpResponseError as error: - process_storage_error(error) - - # Set the download size to empty - self.size = 0 - self._file_size = 0 - else: + # Check the location we read from to ensure we use the same one + # for subsequent requests. + self._location_mode = location_mode + + # Parse the total file size and adjust the download size if ranges + # were specified + self._file_size = parse_length_from_content_range(response.properties.content_range) + # Remove any extra encryption data size from blob size + self._file_size = adjust_blob_size_for_encryption(self._file_size, self._encryption_data) + + if self._end_range is not None: + # Use the length unless it is over the end of the file + self.size = min(self._file_size, self._end_range - self._start_range + 1) + elif self._start_range is not None: + self.size = self._file_size - self._start_range + else: + self.size = self._file_size + + except HttpResponseError as error: + if self._start_range is None and error.response.status_code == 416: + # Get range will fail on an empty file. If the user did not + # request a range, do a regular get request in order to get + # any properties. + try: + _, response = await self._clients.blob.download( + validate_content=self._validate_content, + data_stream_total=0, + download_stream_current=0, + **self._request_options) + except HttpResponseError as error: process_storage_error(error) + # Set the download size to empty + self.size = 0 + self._file_size = 0 + else: + process_storage_error(error) + # get page ranges to optimize downloading sparse page blob if response.properties.blob_type == 'PageBlob': try: diff --git a/sdk/storage/azure-storage-blob/tests/recordings/test_retry_async.test_streaming_retry_async.yaml b/sdk/storage/azure-storage-blob/tests/recordings/test_retry_async.test_streaming_retry_async.yaml new file mode 100644 index 000000000000..21db0163a563 --- /dev/null +++ b/sdk/storage/azure-storage-blob/tests/recordings/test_retry_async.test_streaming_retry_async.yaml @@ -0,0 +1,101 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/xml + User-Agent: + - azsdk-python-storage-blob/12.14.0b1 Python/3.7.13 (Linux-5.10.102.1-microsoft-standard-WSL2-x86_64-with-debian-bullseye-sid) + x-ms-date: + - Thu, 28 Jul 2022 17:20:03 GMT + x-ms-version: + - '2021-08-06' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainer8bf411fcda52506ff2624030ad184b855dd02cd0?restype=container + response: + body: + string: '' + headers: + content-length: '0' + date: Thu, 28 Jul 2022 17:20:03 GMT + etag: '"0x8DA70BD68F3D0F0"' + last-modified: Thu, 28 Jul 2022 17:20:03 GMT + server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-version: '2021-08-06' + status: + code: 201 + message: Created + url: https://tsjinxuansdktestaccount.blob.core.windows.net/utcontainer8bf411fcda52506ff2624030ad184b855dd02cd0?restype=container +- request: + body: null + headers: + Accept: + - application/xml + User-Agent: + - azsdk-python-storage-blob/12.14.0b1 Python/3.7.13 (Linux-5.10.102.1-microsoft-standard-WSL2-x86_64-with-debian-bullseye-sid) + x-ms-date: + - Thu, 28 Jul 2022 17:20:03 GMT + x-ms-version: + - '2021-08-06' + method: GET + uri: https://storagename.blob.core.windows.net/utcontainer8bf411fcda52506ff2624030ad184b855dd02cd0?restype=container + response: + body: + string: '' + headers: + content-length: '0' + date: Thu, 28 Jul 2022 17:20:03 GMT + etag: '"0x8DA70BD68F3D0F0"' + last-modified: Thu, 28 Jul 2022 17:20:03 GMT + server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-default-encryption-scope: $account-encryption-key + x-ms-deny-encryption-scope-override: 'false' + x-ms-has-immutability-policy: 'false' + x-ms-has-legal-hold: 'false' + x-ms-immutable-storage-with-versioning-enabled: 'false' + x-ms-lease-state: available + x-ms-lease-status: unlocked + x-ms-version: '2021-08-06' + status: + code: 200 + message: OK + url: https://tsjinxuansdktestaccount.blob.core.windows.net/utcontainer8bf411fcda52506ff2624030ad184b855dd02cd0?restype=container +- request: + body: abcde + headers: + Accept: + - application/xml + Content-Length: + - '5' + Content-Type: + - application/octet-stream + If-None-Match: + - '*' + User-Agent: + - azsdk-python-storage-blob/12.14.0b1 Python/3.7.13 (Linux-5.10.102.1-microsoft-standard-WSL2-x86_64-with-debian-bullseye-sid) + x-ms-blob-type: + - BlockBlob + x-ms-date: + - Thu, 28 Jul 2022 17:20:03 GMT + x-ms-version: + - '2021-08-06' + method: PUT + uri: https://storagename.blob.core.windows.net/utcontainer8bf411fcda52506ff2624030ad184b855dd02cd0/myblob + response: + body: + string: '' + headers: + content-length: '0' + content-md5: q1a02StAcTrMWviZhdS3hg== + date: Thu, 28 Jul 2022 17:20:03 GMT + etag: '"0x8DA70BD68F9F016"' + last-modified: Thu, 28 Jul 2022 17:20:03 GMT + server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 + x-ms-content-crc64: ExJGZ9Dkswo= + x-ms-request-server-encrypted: 'true' + x-ms-version: '2021-08-06' + status: + code: 201 + message: Created + url: https://tsjinxuansdktestaccount.blob.core.windows.net/utcontainer8bf411fcda52506ff2624030ad184b855dd02cd0/myblob +version: 1 diff --git a/sdk/storage/azure-storage-blob/tests/test_retry.py b/sdk/storage/azure-storage-blob/tests/test_retry.py index 3f082d43b836..ca4429718aca 100644 --- a/sdk/storage/azure-storage-blob/tests/test_retry.py +++ b/sdk/storage/azure-storage-blob/tests/test_retry.py @@ -437,33 +437,3 @@ def test_invalid_account_key(self, storage_account_name, storage_account_key): # Assert # No retry should be performed since the signing error is fatal self.assertEqual(retry_counter.count, 0) - @pytest.mark.live_test_only - - @pytest.mark.live_test_only - @BlobPreparer() - async def test_async_streaming_retry(self, storage_account_name, storage_account_key): - """Test that retry mechanisms are working when streaming data.""" - container_name = self.get_resource_name('utcontainer') - service = self._create_storage_service( - BlobServiceClient, storage_account_name, storage_account_key) - container = service.get_container_client(container_name) - container.create_container() - assert container.exists() - blob_name = "myblob" - container.upload_blob(blob_name, b"abcde") - - read_mock = mock.Mock() - future = asyncio.Future() - future.set_exception( - read_mock.side_effect = ClientPayloadError() - with mock.patch.object(ClientResponse, "read", read_mock): - blob = aio.BlobClient( - account_url=service.url, - container_name=container_name, - blob_name=blob_name, - credential=storage_account_key - ) - blob = container.get_blob_client(blob=blob_name) - blob.download_blob() - -# ------------------------------------------------------------------------------ diff --git a/sdk/storage/azure-storage-blob/tests/test_retry_async.py b/sdk/storage/azure-storage-blob/tests/test_retry_async.py index d46ecd8eb851..5787f8ef7cee 100644 --- a/sdk/storage/azure-storage-blob/tests/test_retry_async.py +++ b/sdk/storage/azure-storage-blob/tests/test_retry_async.py @@ -3,21 +3,20 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- -import unittest -import pytest import asyncio +import functools +from unittest import mock +import pytest from azure.core.exceptions import ( HttpResponseError, ResourceExistsError, AzureError, - ClientAuthenticationError -) -from azure.core.pipeline.transport import ( - AioHttpTransport + ClientAuthenticationError, + ServiceRequestError ) -from azure.core.pipeline.transport import AioHttpTransport +from azure.core.pipeline.transport import AsyncHttpResponse, AioHttpTransportResponse, AioHttpTransport from multidict import CIMultiDict, CIMultiDictProxy from azure.storage.blob import LocationMode @@ -32,6 +31,8 @@ from devtools_testutils import ResourceGroupPreparer, StorageAccountPreparer, RetryCounter, ResponseCallback from devtools_testutils.storage.aio import AsyncStorageTestCase +from aiohttp.client_exceptions import ClientPayloadError +from aiohttp.streams import StreamReader class AiohttpTestTransport(AioHttpTransport): """Workaround to vcrpy bug: https://github.com/kevin1024/vcrpy/pull/461 @@ -471,4 +472,39 @@ async def test_invalid_account_key_async(self, storage_account_name, storage_acc # No retry should be performed since the signing error is fatal self.assertEqual(retry_counter.count, 0) + @staticmethod + def _count_wrapper(counter, func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + counter[0] += 1 + return func(*args, **kwargs) + return wrapper + + @BlobPreparer() + @AsyncStorageTestCase.await_prepared_test + async def test_streaming_retry_async(self, storage_account_name, storage_account_key): + """Test that retry mechanisms are working when streaming data.""" + # Should check that multiple requests went through the pipeline + from uuid import uuid4 + container_name = self.get_resource_name('utcontainer') + uuid4().hex + retry = LinearRetry(backoff = 0.1, random_jitter_range=0) + + service = self._create_storage_service( + BlobServiceClient, storage_account_name, storage_account_key, retry_policy=retry) + container = service.get_container_client(container_name) + await container.create_container() + assert await container.exists() + blob_name = "myblob" + await container.upload_blob(blob_name, b"abcde") + + stream_reader_read_mock = mock.MagicMock() + future = asyncio.Future() + future.set_exception(ClientPayloadError()) + stream_reader_read_mock.return_value = future + with mock.patch.object(StreamReader, "read", stream_reader_read_mock), pytest.raises(ServiceRequestError): + blob = container.get_blob_client(blob=blob_name) + count = [0] + blob._pipeline._transport.send = self._count_wrapper(count, blob._pipeline._transport.send) + await blob.download_blob() + assert stream_reader_read_mock.call_count == count[0] == 4 # ------------------------------------------------------------------------------ From 9e55db66c69341944e13f7b6e58ad6f3fd6302b6 Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Fri, 29 Jul 2022 16:33:32 -0700 Subject: [PATCH 17/21] initial tests --- ...etry_async.test_streaming_retry_async.yaml | 36 +++++++++---------- .../tests/test_retry_async.py | 9 ++--- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/sdk/storage/azure-storage-blob/tests/recordings/test_retry_async.test_streaming_retry_async.yaml b/sdk/storage/azure-storage-blob/tests/recordings/test_retry_async.test_streaming_retry_async.yaml index 21db0163a563..e9045063c5fc 100644 --- a/sdk/storage/azure-storage-blob/tests/recordings/test_retry_async.test_streaming_retry_async.yaml +++ b/sdk/storage/azure-storage-blob/tests/recordings/test_retry_async.test_streaming_retry_async.yaml @@ -7,25 +7,25 @@ interactions: User-Agent: - azsdk-python-storage-blob/12.14.0b1 Python/3.7.13 (Linux-5.10.102.1-microsoft-standard-WSL2-x86_64-with-debian-bullseye-sid) x-ms-date: - - Thu, 28 Jul 2022 17:20:03 GMT + - Fri, 29 Jul 2022 22:47:17 GMT x-ms-version: - '2021-08-06' method: PUT - uri: https://storagename.blob.core.windows.net/utcontainer8bf411fcda52506ff2624030ad184b855dd02cd0?restype=container + uri: https://storagename.blob.core.windows.net/utcontainer8bf411fc?restype=container response: body: string: '' headers: content-length: '0' - date: Thu, 28 Jul 2022 17:20:03 GMT - etag: '"0x8DA70BD68F3D0F0"' - last-modified: Thu, 28 Jul 2022 17:20:03 GMT + date: Fri, 29 Jul 2022 22:47:18 GMT + etag: '"0x8DA71B44AA1F822"' + last-modified: Fri, 29 Jul 2022 22:47:18 GMT server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 x-ms-version: '2021-08-06' status: code: 201 message: Created - url: https://tsjinxuansdktestaccount.blob.core.windows.net/utcontainer8bf411fcda52506ff2624030ad184b855dd02cd0?restype=container + url: https://tsjinxuansdktestaccount.blob.core.windows.net/utcontainer8bf411fc?restype=container - request: body: null headers: @@ -34,19 +34,19 @@ interactions: User-Agent: - azsdk-python-storage-blob/12.14.0b1 Python/3.7.13 (Linux-5.10.102.1-microsoft-standard-WSL2-x86_64-with-debian-bullseye-sid) x-ms-date: - - Thu, 28 Jul 2022 17:20:03 GMT + - Fri, 29 Jul 2022 22:47:18 GMT x-ms-version: - '2021-08-06' method: GET - uri: https://storagename.blob.core.windows.net/utcontainer8bf411fcda52506ff2624030ad184b855dd02cd0?restype=container + uri: https://storagename.blob.core.windows.net/utcontainer8bf411fc?restype=container response: body: string: '' headers: content-length: '0' - date: Thu, 28 Jul 2022 17:20:03 GMT - etag: '"0x8DA70BD68F3D0F0"' - last-modified: Thu, 28 Jul 2022 17:20:03 GMT + date: Fri, 29 Jul 2022 22:47:18 GMT + etag: '"0x8DA71B44AA1F822"' + last-modified: Fri, 29 Jul 2022 22:47:18 GMT server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 x-ms-default-encryption-scope: $account-encryption-key x-ms-deny-encryption-scope-override: 'false' @@ -59,7 +59,7 @@ interactions: status: code: 200 message: OK - url: https://tsjinxuansdktestaccount.blob.core.windows.net/utcontainer8bf411fcda52506ff2624030ad184b855dd02cd0?restype=container + url: https://tsjinxuansdktestaccount.blob.core.windows.net/utcontainer8bf411fc?restype=container - request: body: abcde headers: @@ -76,20 +76,20 @@ interactions: x-ms-blob-type: - BlockBlob x-ms-date: - - Thu, 28 Jul 2022 17:20:03 GMT + - Fri, 29 Jul 2022 22:47:18 GMT x-ms-version: - '2021-08-06' method: PUT - uri: https://storagename.blob.core.windows.net/utcontainer8bf411fcda52506ff2624030ad184b855dd02cd0/myblob + uri: https://storagename.blob.core.windows.net/utcontainer8bf411fc/myblob response: body: string: '' headers: content-length: '0' content-md5: q1a02StAcTrMWviZhdS3hg== - date: Thu, 28 Jul 2022 17:20:03 GMT - etag: '"0x8DA70BD68F9F016"' - last-modified: Thu, 28 Jul 2022 17:20:03 GMT + date: Fri, 29 Jul 2022 22:47:18 GMT + etag: '"0x8DA71B44AA8379F"' + last-modified: Fri, 29 Jul 2022 22:47:18 GMT server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 x-ms-content-crc64: ExJGZ9Dkswo= x-ms-request-server-encrypted: 'true' @@ -97,5 +97,5 @@ interactions: status: code: 201 message: Created - url: https://tsjinxuansdktestaccount.blob.core.windows.net/utcontainer8bf411fcda52506ff2624030ad184b855dd02cd0/myblob + url: https://tsjinxuansdktestaccount.blob.core.windows.net/utcontainer8bf411fc/myblob version: 1 diff --git a/sdk/storage/azure-storage-blob/tests/test_retry_async.py b/sdk/storage/azure-storage-blob/tests/test_retry_async.py index 5787f8ef7cee..72bfa1351418 100644 --- a/sdk/storage/azure-storage-blob/tests/test_retry_async.py +++ b/sdk/storage/azure-storage-blob/tests/test_retry_async.py @@ -10,6 +10,7 @@ from azure.core.exceptions import ( HttpResponseError, + IncompleteReadError, ResourceExistsError, AzureError, ClientAuthenticationError, @@ -33,6 +34,7 @@ from aiohttp.client_exceptions import ClientPayloadError from aiohttp.streams import StreamReader +from aiohttp.client import ClientResponse class AiohttpTestTransport(AioHttpTransport): """Workaround to vcrpy bug: https://github.com/kevin1024/vcrpy/pull/461 @@ -484,9 +486,7 @@ def wrapper(*args, **kwargs): @AsyncStorageTestCase.await_prepared_test async def test_streaming_retry_async(self, storage_account_name, storage_account_key): """Test that retry mechanisms are working when streaming data.""" - # Should check that multiple requests went through the pipeline - from uuid import uuid4 - container_name = self.get_resource_name('utcontainer') + uuid4().hex + container_name = self.get_resource_name('utcontainer') retry = LinearRetry(backoff = 0.1, random_jitter_range=0) service = self._create_storage_service( @@ -506,5 +506,6 @@ async def test_streaming_retry_async(self, storage_account_name, storage_account count = [0] blob._pipeline._transport.send = self._count_wrapper(count, blob._pipeline._transport.send) await blob.download_blob() - assert stream_reader_read_mock.call_count == count[0] == 4 + assert stream_reader_read_mock.call_count == count[0] == 4 + # ------------------------------------------------------------------------------ From ec0aef37892b6390302bfd9c017c050d2179d9ee Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Fri, 29 Jul 2022 16:35:31 -0700 Subject: [PATCH 18/21] remove retry --- .../azure-storage-blob/tests/test_retry.py | 69 +++++++++++++++++-- 1 file changed, 64 insertions(+), 5 deletions(-) diff --git a/sdk/storage/azure-storage-blob/tests/test_retry.py b/sdk/storage/azure-storage-blob/tests/test_retry.py index ca4429718aca..267dc0cb31ae 100644 --- a/sdk/storage/azure-storage-blob/tests/test_retry.py +++ b/sdk/storage/azure-storage-blob/tests/test_retry.py @@ -3,19 +3,17 @@ # Licensed under the MIT License. See License.txt in the project root for # license information. # -------------------------------------------------------------------------- -import asyncio from unittest import mock +from functools import wraps import pytest -from aiohttp import ClientResponse -from aiohttp.client_exceptions import ClientPayloadError from azure.core.exceptions import ( HttpResponseError, ResourceExistsError, AzureError, - ClientAuthenticationError + ClientAuthenticationError, + ServiceResponseError ) -from azure.storage.blob import aio from azure.core.pipeline.transport import( RequestsTransport ) @@ -28,6 +26,9 @@ LinearRetry, ExponentialRetry, ) +from requests import Response +from requests.exceptions import ContentDecodingError, ChunkedEncodingError +from azure.core.exceptions import DecodeError from settings.testcase import BlobPreparer from devtools_testutils.storage import StorageTestCase @@ -437,3 +438,61 @@ def test_invalid_account_key(self, storage_account_name, storage_account_key): # Assert # No retry should be performed since the signing error is fatal self.assertEqual(retry_counter.count, 0) + + @staticmethod + def count_wrapper(counter, func): + """Wrapper to count how many times a function is called. + :param List[int] counter: + A singleton list. Will usually be `[0]`. + :param callable func: + The function to wrap. + :return Callable: + The wrapped function. + + Example: + ```python + class MyClass: + def hello(self): + pass + + obj = MyClass() + counter = [0] + obj.hello() + obj.hello = count_wrapper(counter, obj.hello) + obj.hello() + obj.hello() + print(counter[0]) # 2 + ``` + """ + @wraps(func) + def inner(*args, **kwargs): + counter[0] += 1 + return func(*args, **kwargs) + return inner + + @BlobPreparer() + def test_streaming_retry(self, storage_account_name, storage_account_key): + """Test that retry mechanisms are working when streaming data.""" + # Should check that multiple requests went through the pipeline + container_name = self.get_resource_name('utcontainer') + service = self._create_storage_service( + BlobServiceClient, storage_account_name, storage_account_key) + container = service.get_container_client(container_name) + container.create_container() + assert container.exists() + blob_name = "myblob" + container.upload_blob(blob_name, b"abcde") + + for error in (ContentDecodingError(), ChunkedEncodingError(), ChunkedEncodingError("IncompleteRead")): + iterator_mock = mock.MagicMock() + iterator_mock.__next__.side_effect = error + iter_content_mock = mock.Mock() + iter_content_mock.return_value = iterator_mock + with mock.patch.object(Response, "iter_content", iter_content_mock), pytest.raises(HttpResponseError): + blob = container.get_blob_client(blob=blob_name) + count = [0] + blob._pipeline._transport.send = self.count_wrapper(count, blob._pipeline._transport.send) + blob.download_blob() + assert iterator_mock.__next__.call_count == count[0] == 3 + + # ------------------------------------------------------------------------------ From 80096aaa8e880067d9037d31ca4e28a76758c688 Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Mon, 1 Aug 2022 09:51:57 -0700 Subject: [PATCH 19/21] typo --- sdk/storage/azure-storage-blob/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/azure-storage-blob/CHANGELOG.md b/sdk/storage/azure-storage-blob/CHANGELOG.md index 79eb658d355e..22e6b44af568 100644 --- a/sdk/storage/azure-storage-blob/CHANGELOG.md +++ b/sdk/storage/azure-storage-blob/CHANGELOG.md @@ -8,7 +8,7 @@ This version and all future versions will require Python 3.7+. Python 3.6 is no - Added support for `AzureNamedKeyCredential` as a valid `credential` type. ### Bugs Fixed -- Removed dead retry meachism from async `azure.storage.blob.aio.StorageStreamDownloader` +- Removed dead retry meachism from async `azure.storage.blob.aio.StorageStreamDownloader`. - Updated exception catching of `azure.storage.blob.StorageStreamDownloader`'s retry mechanism. - Adjusted type hints for `upload_blob` and `StorageStreamDownloader.readall`. From efd1473dfe9c1377cd7ecc96265a5f645dbe493d Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Thu, 4 Aug 2022 08:35:47 -0700 Subject: [PATCH 20/21] unused im --- .../azure/storage/blob/aio/_download_async.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py index ce271c6065c2..133c721ec383 100644 --- a/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py +++ b/sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py @@ -13,7 +13,7 @@ import asyncio -from azure.core.exceptions import HttpResponseError, ServiceResponseError, IncompleteReadError +from azure.core.exceptions import HttpResponseError from .._shared.request_handlers import validate_and_format_range_headers from .._shared.response_handlers import process_storage_error, parse_length_from_content_range From f65d1f02d79d549746278894d10284f54d0268e0 Mon Sep 17 00:00:00 2001 From: Steven Jin Date: Thu, 4 Aug 2022 08:38:07 -0700 Subject: [PATCH 21/21] live-only test --- ...etry_async.test_streaming_retry_async.yaml | 101 ------------------ .../tests/test_retry_async.py | 1 + 2 files changed, 1 insertion(+), 101 deletions(-) delete mode 100644 sdk/storage/azure-storage-blob/tests/recordings/test_retry_async.test_streaming_retry_async.yaml diff --git a/sdk/storage/azure-storage-blob/tests/recordings/test_retry_async.test_streaming_retry_async.yaml b/sdk/storage/azure-storage-blob/tests/recordings/test_retry_async.test_streaming_retry_async.yaml deleted file mode 100644 index e9045063c5fc..000000000000 --- a/sdk/storage/azure-storage-blob/tests/recordings/test_retry_async.test_streaming_retry_async.yaml +++ /dev/null @@ -1,101 +0,0 @@ -interactions: -- request: - body: null - headers: - Accept: - - application/xml - User-Agent: - - azsdk-python-storage-blob/12.14.0b1 Python/3.7.13 (Linux-5.10.102.1-microsoft-standard-WSL2-x86_64-with-debian-bullseye-sid) - x-ms-date: - - Fri, 29 Jul 2022 22:47:17 GMT - x-ms-version: - - '2021-08-06' - method: PUT - uri: https://storagename.blob.core.windows.net/utcontainer8bf411fc?restype=container - response: - body: - string: '' - headers: - content-length: '0' - date: Fri, 29 Jul 2022 22:47:18 GMT - etag: '"0x8DA71B44AA1F822"' - last-modified: Fri, 29 Jul 2022 22:47:18 GMT - server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 - x-ms-version: '2021-08-06' - status: - code: 201 - message: Created - url: https://tsjinxuansdktestaccount.blob.core.windows.net/utcontainer8bf411fc?restype=container -- request: - body: null - headers: - Accept: - - application/xml - User-Agent: - - azsdk-python-storage-blob/12.14.0b1 Python/3.7.13 (Linux-5.10.102.1-microsoft-standard-WSL2-x86_64-with-debian-bullseye-sid) - x-ms-date: - - Fri, 29 Jul 2022 22:47:18 GMT - x-ms-version: - - '2021-08-06' - method: GET - uri: https://storagename.blob.core.windows.net/utcontainer8bf411fc?restype=container - response: - body: - string: '' - headers: - content-length: '0' - date: Fri, 29 Jul 2022 22:47:18 GMT - etag: '"0x8DA71B44AA1F822"' - last-modified: Fri, 29 Jul 2022 22:47:18 GMT - server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 - x-ms-default-encryption-scope: $account-encryption-key - x-ms-deny-encryption-scope-override: 'false' - x-ms-has-immutability-policy: 'false' - x-ms-has-legal-hold: 'false' - x-ms-immutable-storage-with-versioning-enabled: 'false' - x-ms-lease-state: available - x-ms-lease-status: unlocked - x-ms-version: '2021-08-06' - status: - code: 200 - message: OK - url: https://tsjinxuansdktestaccount.blob.core.windows.net/utcontainer8bf411fc?restype=container -- request: - body: abcde - headers: - Accept: - - application/xml - Content-Length: - - '5' - Content-Type: - - application/octet-stream - If-None-Match: - - '*' - User-Agent: - - azsdk-python-storage-blob/12.14.0b1 Python/3.7.13 (Linux-5.10.102.1-microsoft-standard-WSL2-x86_64-with-debian-bullseye-sid) - x-ms-blob-type: - - BlockBlob - x-ms-date: - - Fri, 29 Jul 2022 22:47:18 GMT - x-ms-version: - - '2021-08-06' - method: PUT - uri: https://storagename.blob.core.windows.net/utcontainer8bf411fc/myblob - response: - body: - string: '' - headers: - content-length: '0' - content-md5: q1a02StAcTrMWviZhdS3hg== - date: Fri, 29 Jul 2022 22:47:18 GMT - etag: '"0x8DA71B44AA8379F"' - last-modified: Fri, 29 Jul 2022 22:47:18 GMT - server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0 - x-ms-content-crc64: ExJGZ9Dkswo= - x-ms-request-server-encrypted: 'true' - x-ms-version: '2021-08-06' - status: - code: 201 - message: Created - url: https://tsjinxuansdktestaccount.blob.core.windows.net/utcontainer8bf411fc/myblob -version: 1 diff --git a/sdk/storage/azure-storage-blob/tests/test_retry_async.py b/sdk/storage/azure-storage-blob/tests/test_retry_async.py index 72bfa1351418..c307b252f5ec 100644 --- a/sdk/storage/azure-storage-blob/tests/test_retry_async.py +++ b/sdk/storage/azure-storage-blob/tests/test_retry_async.py @@ -482,6 +482,7 @@ def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper + @pytest.mark.live_test_only @BlobPreparer() @AsyncStorageTestCase.await_prepared_test async def test_streaming_retry_async(self, storage_account_name, storage_account_key):