Skip to content

Commit 8ac37df

Browse files
Catch exceptions thrown by async download (Azure#14946)
* fixed excpetion handling * added test
1 parent 3b97366 commit 8ac37df

File tree

4 files changed

+275
-5
lines changed

4 files changed

+275
-5
lines changed

sdk/storage/azure-storage-blob/azure/storage/blob/aio/_download_async.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
from .._deserialize import get_page_ranges_result
1919
from .._download import process_range_and_offset, _ChunkDownloader
2020

21-
2221
async def process_content(data, start_offset, end_offset, encryption):
2322
if data is None:
2423
raise ValueError("Response cannot be None.")
@@ -390,7 +389,7 @@ async def content_as_text(self, max_concurrency=1, encoding="UTF-8"):
390389
391390
This operation is blocking until all data is downloaded.
392391
393-
:keyword int max_concurrency:
392+
:param int max_concurrency:
394393
The number of parallel connections with which to download.
395394
:param str encoding:
396395
Test encoding to decode the downloaded bytes. Default is UTF-8.
@@ -458,8 +457,13 @@ async def readinto(self, stream):
458457
]
459458
while running_futures:
460459
# Wait for some download to finish before adding a new one
461-
_done, running_futures = await asyncio.wait(
460+
done, running_futures = await asyncio.wait(
462461
running_futures, return_when=asyncio.FIRST_COMPLETED)
462+
try:
463+
for task in done:
464+
task.result()
465+
except HttpResponseError as error:
466+
process_storage_error(error)
463467
try:
464468
next_chunk = next(dl_tasks)
465469
except StopIteration:
@@ -469,7 +473,12 @@ async def readinto(self, stream):
469473

470474
if running_futures:
471475
# Wait for the remaining downloads to finish
472-
await asyncio.wait(running_futures)
476+
done, _running_futures = await asyncio.wait(running_futures)
477+
try:
478+
for task in done:
479+
task.result()
480+
except HttpResponseError as error:
481+
process_storage_error(error)
473482
return self.size
474483

475484
async def download_to_stream(self, stream, max_concurrency=1):
@@ -479,6 +488,8 @@ async def download_to_stream(self, stream, max_concurrency=1):
479488
The stream to download to. This can be an open file-handle,
480489
or any writable stream. The stream must be seekable if the download
481490
uses more than one parallel connection.
491+
:param int max_concurrency:
492+
The number of parallel connections with which to download.
482493
:returns: The properties of the downloaded blob.
483494
:rtype: Any
484495
"""

sdk/storage/azure-storage-blob/tests/get_blob_to_stream_async.temp.4ebacace-c663-4994-b478-01affe7284f1.dat

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

sdk/storage/azure-storage-blob/tests/recordings/test_get_blob_async.test_readinto_raises_exceptions.yaml

Lines changed: 236 additions & 0 deletions
Large diffs are not rendered by default.

sdk/storage/azure-storage-blob/tests/test_get_blob_async.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
TEST_BLOB_PREFIX = 'blob'
3535

3636

37-
3837
# ------------------------------------------------------------------------------
3938

4039
class AiohttpTestTransport(AioHttpTransport):
@@ -346,6 +345,29 @@ async def test_get_blob_to_stream_async(self, resource_group, location, storage_
346345
self.assertEqual(self.byte_data, actual)
347346
self._teardown(FILE_PATH)
348347

348+
@pytest.mark.live_test_only
349+
@GlobalStorageAccountPreparer()
350+
@AsyncStorageTestCase.await_prepared_test
351+
async def test_readinto_raises_exceptions(self, resource_group, location, storage_account, storage_account_key):
352+
# parallel tests introduce random order of requests, can only run live
353+
callback_counter = {'value': 0}
354+
355+
def callback(response):
356+
callback_counter['value'] += 1
357+
if callback_counter['value'] > 3:
358+
raise ValueError()
359+
360+
# Arrange
361+
await self._setup(storage_account, storage_account_key)
362+
blob = self.bsc.get_blob_client(self.container_name, self.byte_blob)
363+
364+
# Act
365+
FILE_PATH = 'get_blob_to_stream_async.temp.{}.dat'.format(str(uuid.uuid4()))
366+
with open(FILE_PATH, 'wb') as stream:
367+
downloader = await blob.download_blob(max_concurrency=2, raw_response_hook=callback)
368+
with self.assertRaises(ValueError):
369+
await downloader.readinto(stream)
370+
349371
@pytest.mark.live_test_only
350372
@GlobalStorageAccountPreparer()
351373
@AsyncStorageTestCase.await_prepared_test

0 commit comments

Comments
 (0)