Skip to content

Commit 1abb890

Browse files
authored
Fix typing contract for Blob client max_concurrency (#45598)
1 parent 25886b2 commit 1abb890

11 files changed

Lines changed: 98 additions & 27 deletions

File tree

sdk/storage/azure-storage-blob/assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"AssetsRepo": "Azure/azure-sdk-assets",
33
"AssetsRepoPrefixPath": "python",
44
"TagPrefix": "python/storage/azure-storage-blob",
5-
"Tag": "python/storage/azure-storage-blob_89c4f2856e"
5+
"Tag": "python/storage/azure-storage-blob_bd8f6233a4"
66
}

sdk/storage/azure-storage-blob/azure/storage/blob/_blob_client.pyi

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ class BlobClient(StorageAccountHostsMixin, StorageEncryptionMixin):
185185
legal_hold: Optional[bool] = None,
186186
standard_blob_tier: Optional[StandardBlobTier] = None,
187187
maxsize_condition: Optional[int] = None,
188-
max_concurrency: int = 1,
188+
max_concurrency: Optional[int] = None,
189189
cpk: Optional[CustomerProvidedEncryptionKey] = None,
190190
encryption_scope: Optional[str] = None,
191191
encoding: str = "UTF-8",
@@ -208,7 +208,7 @@ class BlobClient(StorageAccountHostsMixin, StorageEncryptionMixin):
208208
match_condition: Optional[MatchConditions] = None,
209209
if_tags_match_condition: Optional[str] = None,
210210
cpk: Optional[CustomerProvidedEncryptionKey] = None,
211-
max_concurrency: int = 1,
211+
max_concurrency: Optional[int] = None,
212212
encoding: str,
213213
progress_hook: Optional[Callable[[int, int], None]] = None,
214214
decompress: Optional[bool] = None,
@@ -230,7 +230,7 @@ class BlobClient(StorageAccountHostsMixin, StorageEncryptionMixin):
230230
match_condition: Optional[MatchConditions] = None,
231231
if_tags_match_condition: Optional[str] = None,
232232
cpk: Optional[CustomerProvidedEncryptionKey] = None,
233-
max_concurrency: int = 1,
233+
max_concurrency: Optional[int] = None,
234234
encoding: None = None,
235235
progress_hook: Optional[Callable[[int, int], None]] = None,
236236
decompress: Optional[bool] = None,
@@ -252,7 +252,7 @@ class BlobClient(StorageAccountHostsMixin, StorageEncryptionMixin):
252252
match_condition: Optional[MatchConditions] = None,
253253
if_tags_match_condition: Optional[str] = None,
254254
cpk: Optional[CustomerProvidedEncryptionKey] = None,
255-
max_concurrency: int = 1,
255+
max_concurrency: Optional[int] = None,
256256
encoding: Optional[str] = None,
257257
progress_hook: Optional[Callable[[int, int], None]] = None,
258258
decompress: Optional[bool] = None,

sdk/storage/azure-storage-blob/azure/storage/blob/_blob_client_helpers.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
)
4949
from ._shared import encode_base64
5050
from ._shared.base_client import parse_query
51+
from ._shared.constants import DEFAULT_MAX_CONCURRENCY
5152
from ._shared.request_handlers import (
5253
add_metadata_headers,
5354
get_length,
@@ -137,7 +138,9 @@ def _upload_blob_options( # pylint:disable=too-many-statements
137138
validate_content = kwargs.pop('validate_content', False)
138139
content_settings = kwargs.pop('content_settings', None)
139140
overwrite = kwargs.pop('overwrite', False)
140-
max_concurrency = kwargs.pop('max_concurrency', 1)
141+
max_concurrency = kwargs.pop('max_concurrency', None)
142+
if max_concurrency is None:
143+
max_concurrency = DEFAULT_MAX_CONCURRENCY
141144
cpk = kwargs.pop('cpk', None)
142145
cpk_info = None
143146
if cpk:
@@ -323,7 +326,7 @@ def _download_blob_options(
323326
'modified_access_conditions': mod_conditions,
324327
'cpk_info': cpk_info,
325328
'download_cls': kwargs.pop('cls', None) or deserialize_blob_stream,
326-
'max_concurrency':kwargs.pop('max_concurrency', 1),
329+
'max_concurrency': kwargs.pop('max_concurrency', None) or DEFAULT_MAX_CONCURRENCY,
327330
'encoding': encoding,
328331
'timeout': kwargs.pop('timeout', None),
329332
'name': blob_name,

sdk/storage/azure-storage-blob/azure/storage/blob/_download.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
from ._shared.request_handlers import validate_and_format_range_headers
2222
from ._shared.response_handlers import parse_length_from_content_range, process_storage_error
23+
from ._shared.constants import DEFAULT_MAX_CONCURRENCY
2324
from ._deserialize import deserialize_blob_properties, get_page_ranges_result
2425
from ._encryption import (
2526
adjust_blob_size_for_encryption,
@@ -330,7 +331,7 @@ def __init__(
330331
end_range: Optional[int] = None,
331332
validate_content: bool = None, # type: ignore [assignment]
332333
encryption_options: Dict[str, Any] = None, # type: ignore [assignment]
333-
max_concurrency: int = 1,
334+
max_concurrency: Optional[int] = None,
334335
name: str = None, # type: ignore [assignment]
335336
container: str = None, # type: ignore [assignment]
336337
encoding: Optional[str] = None,
@@ -345,7 +346,7 @@ def __init__(
345346
self._config = config
346347
self._start_range = start_range
347348
self._end_range = end_range
348-
self._max_concurrency = max_concurrency
349+
self._max_concurrency = max_concurrency if max_concurrency is not None else DEFAULT_MAX_CONCURRENCY
349350
self._encoding = encoding
350351
self._validate_content = validate_content
351352
self._encryption_options = encryption_options or {}
@@ -865,7 +866,7 @@ def _check_and_report_progress(self):
865866
if self._progress_hook and self._current_content_offset == len(self._current_content):
866867
self._progress_hook(self._download_offset, self.size)
867868

868-
def content_as_bytes(self, max_concurrency=1):
869+
def content_as_bytes(self, max_concurrency=None):
869870
"""DEPRECATED: Download the contents of this file.
870871
871872
This operation is blocking until all data is downloaded.
@@ -885,10 +886,10 @@ def content_as_bytes(self, max_concurrency=1):
885886
raise ValueError("Stream has been partially read in text mode. "
886887
"content_as_bytes is not supported in text mode.")
887888

888-
self._max_concurrency = max_concurrency
889+
self._max_concurrency = max_concurrency if max_concurrency is not None else DEFAULT_MAX_CONCURRENCY
889890
return self.readall()
890891

891-
def content_as_text(self, max_concurrency=1, encoding="UTF-8"):
892+
def content_as_text(self, max_concurrency=None, encoding="UTF-8"):
892893
"""DEPRECATED: Download the contents of this blob, and decode as text.
893894
894895
This operation is blocking until all data is downloaded.
@@ -910,11 +911,11 @@ def content_as_text(self, max_concurrency=1, encoding="UTF-8"):
910911
raise ValueError("Stream has been partially read in text mode. "
911912
"content_as_text is not supported in text mode.")
912913

913-
self._max_concurrency = max_concurrency
914+
self._max_concurrency = max_concurrency if max_concurrency is not None else DEFAULT_MAX_CONCURRENCY
914915
self._encoding = encoding
915916
return self.readall()
916917

917-
def download_to_stream(self, stream, max_concurrency=1):
918+
def download_to_stream(self, stream, max_concurrency=None):
918919
"""DEPRECATED: Download the contents of this blob to a stream.
919920
920921
This method is deprecated, use func:`readinto` instead.
@@ -936,6 +937,6 @@ def download_to_stream(self, stream, max_concurrency=1):
936937
raise ValueError("Stream has been partially read in text mode. "
937938
"download_to_stream is not supported in text mode.")
938939

939-
self._max_concurrency = max_concurrency
940+
self._max_concurrency = max_concurrency if max_concurrency is not None else DEFAULT_MAX_CONCURRENCY
940941
self.readinto(stream)
941942
return self.properties

sdk/storage/azure-storage-blob/azure/storage/blob/_shared/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
READ_TIMEOUT = 60
1515
DATA_BLOCK_SIZE = 256 * 1024
1616

17+
DEFAULT_MAX_CONCURRENCY = 1
18+
1719
DEFAULT_OAUTH_SCOPE = "/.default"
1820
STORAGE_OAUTH_SCOPE = "https://storage.azure.com/.default"
1921

sdk/storage/azure-storage-blob/azure/storage/blob/aio/_blob_client_async.pyi

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ class BlobClient( # type: ignore[misc]
187187
legal_hold: Optional[bool] = None,
188188
standard_blob_tier: Optional[StandardBlobTier] = None,
189189
maxsize_condition: Optional[int] = None,
190-
max_concurrency: int = 1,
190+
max_concurrency: Optional[int] = None,
191191
cpk: Optional[CustomerProvidedEncryptionKey] = None,
192192
encryption_scope: Optional[str] = None,
193193
encoding: str = "UTF-8",
@@ -210,7 +210,7 @@ class BlobClient( # type: ignore[misc]
210210
match_condition: Optional[MatchConditions] = None,
211211
if_tags_match_condition: Optional[str] = None,
212212
cpk: Optional[CustomerProvidedEncryptionKey] = None,
213-
max_concurrency: int = 1,
213+
max_concurrency: Optional[int] = None,
214214
encoding: str,
215215
progress_hook: Optional[Callable[[int, int], Awaitable[None]]] = None,
216216
decompress: Optional[bool] = None,
@@ -232,7 +232,7 @@ class BlobClient( # type: ignore[misc]
232232
match_condition: Optional[MatchConditions] = None,
233233
if_tags_match_condition: Optional[str] = None,
234234
cpk: Optional[CustomerProvidedEncryptionKey] = None,
235-
max_concurrency: int = 1,
235+
max_concurrency: Optional[int] = None,
236236
encoding: None = None,
237237
progress_hook: Optional[Callable[[int, int], Awaitable[None]]] = None,
238238
decompress: Optional[bool] = None,
@@ -254,7 +254,7 @@ class BlobClient( # type: ignore[misc]
254254
match_condition: Optional[MatchConditions] = None,
255255
if_tags_match_condition: Optional[str] = None,
256256
cpk: Optional[CustomerProvidedEncryptionKey] = None,
257-
max_concurrency: int = 1,
257+
max_concurrency: Optional[int] = None,
258258
encoding: Optional[str] = None,
259259
progress_hook: Optional[Callable[[int, int], Awaitable[None]]] = None,
260260
decompress: Optional[bool] = None,

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
from .._shared.request_handlers import validate_and_format_range_headers
2525
from .._shared.response_handlers import parse_length_from_content_range, process_storage_error
26+
from .._shared.constants import DEFAULT_MAX_CONCURRENCY
2627
from .._deserialize import deserialize_blob_properties, get_page_ranges_result
2728
from .._download import process_range_and_offset, _ChunkDownloader
2829
from .._encryption import (
@@ -239,7 +240,7 @@ def __init__(
239240
end_range: Optional[int] = None,
240241
validate_content: bool = None, # type: ignore [assignment]
241242
encryption_options: Dict[str, Any] = None, # type: ignore [assignment]
242-
max_concurrency: int = 1,
243+
max_concurrency: Optional[int] = None,
243244
name: str = None, # type: ignore [assignment]
244245
container: str = None, # type: ignore [assignment]
245246
encoding: Optional[str] = None,
@@ -254,7 +255,7 @@ def __init__(
254255
self._config = config
255256
self._start_range = start_range
256257
self._end_range = end_range
257-
self._max_concurrency = max_concurrency
258+
self._max_concurrency = max_concurrency if max_concurrency is not None else DEFAULT_MAX_CONCURRENCY
258259
self._encoding = encoding
259260
self._validate_content = validate_content
260261
self._encryption_options = encryption_options or {}
@@ -808,7 +809,7 @@ async def _check_and_report_progress(self):
808809
if self._progress_hook and self._current_content_offset == len(self._current_content):
809810
await self._progress_hook(self._download_offset, self.size)
810811

811-
async def content_as_bytes(self, max_concurrency=1):
812+
async def content_as_bytes(self, max_concurrency=None):
812813
"""DEPRECATED: Download the contents of this file.
813814
814815
This operation is blocking until all data is downloaded.
@@ -828,10 +829,10 @@ async def content_as_bytes(self, max_concurrency=1):
828829
raise ValueError("Stream has been partially read in text mode. "
829830
"content_as_bytes is not supported in text mode.")
830831

831-
self._max_concurrency = max_concurrency
832+
self._max_concurrency = max_concurrency if max_concurrency is not None else DEFAULT_MAX_CONCURRENCY
832833
return await self.readall()
833834

834-
async def content_as_text(self, max_concurrency=1, encoding="UTF-8"):
835+
async def content_as_text(self, max_concurrency=None, encoding="UTF-8"):
835836
"""DEPRECATED: Download the contents of this blob, and decode as text.
836837
837838
This operation is blocking until all data is downloaded.
@@ -853,11 +854,11 @@ async def content_as_text(self, max_concurrency=1, encoding="UTF-8"):
853854
raise ValueError("Stream has been partially read in text mode. "
854855
"content_as_text is not supported in text mode.")
855856

856-
self._max_concurrency = max_concurrency
857+
self._max_concurrency = max_concurrency if max_concurrency is not None else DEFAULT_MAX_CONCURRENCY
857858
self._encoding = encoding
858859
return await self.readall()
859860

860-
async def download_to_stream(self, stream, max_concurrency=1):
861+
async def download_to_stream(self, stream, max_concurrency=None):
861862
"""DEPRECATED: Download the contents of this blob to a stream.
862863
863864
This method is deprecated, use func:`readinto` instead.
@@ -879,6 +880,6 @@ async def download_to_stream(self, stream, max_concurrency=1):
879880
raise ValueError("Stream has been partially read in text mode. "
880881
"download_to_stream is not supported in text mode.")
881882

882-
self._max_concurrency = max_concurrency
883+
self._max_concurrency = max_concurrency if max_concurrency is not None else DEFAULT_MAX_CONCURRENCY
883884
await self.readinto(stream)
884885
return self.properties

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,4 +1984,21 @@ def test_upload_blob_copy_source_error_and_status_code(self, **kwargs):
19841984
finally:
19851985
self.bsc.delete_container(self.container_name)
19861986

1987+
@BlobPreparer()
1988+
@recorded_by_proxy
1989+
def test_put_block_blob_with_none_concurrency(self, **kwargs):
1990+
storage_account_name = kwargs.pop("storage_account_name")
1991+
storage_account_key = kwargs.pop("storage_account_key")
1992+
1993+
self._setup(storage_account_name, storage_account_key)
1994+
blob_name = self._get_blob_reference()
1995+
blob = self.bsc.get_blob_client(self.container_name, blob_name)
1996+
data = b'a' * 5 * 1024
1997+
1998+
# max_concurrency=None should not raise TypeError
1999+
blob.upload_blob(data, max_concurrency=None, overwrite=True)
2000+
2001+
content = blob.download_blob().readall()
2002+
assert data == content
2003+
19872004
#------------------------------------------------------------------------------

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2102,4 +2102,21 @@ async def test_upload_blob_copy_source_error_and_status_code(self, **kwargs):
21022102
finally:
21032103
await self.bsc.delete_container(self.container_name)
21042104

2105+
@BlobPreparer()
2106+
@recorded_by_proxy_async
2107+
async def test_put_block_blob_with_none_concurrency(self, **kwargs):
2108+
storage_account_name = kwargs.pop("storage_account_name")
2109+
storage_account_key = kwargs.pop("storage_account_key")
2110+
2111+
await self._setup(storage_account_name, storage_account_key)
2112+
blob_name = self._get_blob_reference()
2113+
blob = self.bsc.get_blob_client(self.container_name, blob_name)
2114+
data = b'a' * 5 * 1024
2115+
2116+
# max_concurrency=None should not raise TypeError
2117+
await blob.upload_blob(data, max_concurrency=None, overwrite=True)
2118+
2119+
content = await (await blob.download_blob()).readall()
2120+
assert data == content
2121+
21052122
# ------------------------------------------------------------------------------

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,4 +1663,19 @@ def test_get_blob_read_chars_utf32(self, **kwargs):
16631663
result += stream.readall()
16641664
assert result == data
16651665

1666+
@BlobPreparer()
1667+
@recorded_by_proxy
1668+
def test_get_blob_to_bytes_with_none_concurrency(self, **kwargs):
1669+
storage_account_name = kwargs.pop("storage_account_name")
1670+
storage_account_key = kwargs.pop("storage_account_key")
1671+
1672+
self._setup(storage_account_name, storage_account_key)
1673+
blob = self.bsc.get_blob_client(self.container_name, self.byte_blob)
1674+
1675+
# max_concurrency=None should not raise TypeError
1676+
stream = blob.download_blob(max_concurrency=None)
1677+
content = stream.readall()
1678+
1679+
assert self.byte_data == content
1680+
16661681
# ------------------------------------------------------------------------------

0 commit comments

Comments
 (0)