azure-storage-blob 12.21.0b1__py3-none-any.whl → 12.22.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. azure/storage/blob/__init__.py +19 -18
  2. azure/storage/blob/_blob_client.py +470 -1555
  3. azure/storage/blob/_blob_client_helpers.py +1242 -0
  4. azure/storage/blob/_blob_service_client.py +93 -112
  5. azure/storage/blob/_blob_service_client_helpers.py +27 -0
  6. azure/storage/blob/_container_client.py +169 -376
  7. azure/storage/blob/_container_client_helpers.py +261 -0
  8. azure/storage/blob/_deserialize.py +68 -44
  9. azure/storage/blob/_download.py +375 -241
  10. azure/storage/blob/_encryption.py +14 -7
  11. azure/storage/blob/_generated/py.typed +1 -0
  12. azure/storage/blob/_lease.py +52 -63
  13. azure/storage/blob/_list_blobs_helper.py +129 -135
  14. azure/storage/blob/_models.py +480 -277
  15. azure/storage/blob/_quick_query_helper.py +30 -31
  16. azure/storage/blob/_serialize.py +38 -56
  17. azure/storage/blob/_shared/avro/datafile.py +1 -1
  18. azure/storage/blob/_shared/avro/datafile_async.py +1 -1
  19. azure/storage/blob/_shared/base_client.py +1 -1
  20. azure/storage/blob/_shared/base_client_async.py +1 -1
  21. azure/storage/blob/_shared/policies.py +8 -6
  22. azure/storage/blob/_shared/policies_async.py +3 -1
  23. azure/storage/blob/_shared/response_handlers.py +6 -2
  24. azure/storage/blob/_shared/shared_access_signature.py +2 -2
  25. azure/storage/blob/_shared/uploads.py +1 -1
  26. azure/storage/blob/_shared/uploads_async.py +1 -1
  27. azure/storage/blob/_shared_access_signature.py +70 -53
  28. azure/storage/blob/_upload_helpers.py +75 -68
  29. azure/storage/blob/_version.py +1 -1
  30. azure/storage/blob/aio/__init__.py +19 -11
  31. azure/storage/blob/aio/_blob_client_async.py +554 -301
  32. azure/storage/blob/aio/_blob_service_client_async.py +148 -97
  33. azure/storage/blob/aio/_container_client_async.py +282 -139
  34. azure/storage/blob/aio/_download_async.py +408 -283
  35. azure/storage/blob/aio/_lease_async.py +61 -60
  36. azure/storage/blob/aio/_list_blobs_helper.py +94 -96
  37. azure/storage/blob/aio/_models.py +60 -38
  38. azure/storage/blob/aio/_upload_helpers.py +75 -66
  39. {azure_storage_blob-12.21.0b1.dist-info → azure_storage_blob-12.22.0.dist-info}/METADATA +7 -7
  40. {azure_storage_blob-12.21.0b1.dist-info → azure_storage_blob-12.22.0.dist-info}/RECORD +43 -39
  41. {azure_storage_blob-12.21.0b1.dist-info → azure_storage_blob-12.22.0.dist-info}/WHEEL +1 -1
  42. {azure_storage_blob-12.21.0b1.dist-info → azure_storage_blob-12.22.0.dist-info}/LICENSE +0 -0
  43. {azure_storage_blob-12.21.0b1.dist-info → azure_storage_blob-12.22.0.dist-info}/top_level.txt +0 -0
@@ -5,35 +5,37 @@
5
5
  # --------------------------------------------------------------------------
6
6
 
7
7
  from io import SEEK_SET, UnsupportedOperation
8
- from typing import TypeVar, TYPE_CHECKING
8
+ from typing import Any, cast, Dict, IO, Optional, TypeVar, TYPE_CHECKING
9
9
 
10
10
  from azure.core.exceptions import ResourceExistsError, ResourceModifiedError, HttpResponseError
11
11
 
12
- from ._shared.response_handlers import process_storage_error, return_response_headers
13
- from ._shared.models import StorageErrorCode
14
- from ._shared.uploads import (
15
- upload_data_chunks,
16
- upload_substream_blocks,
17
- BlockBlobChunkUploader,
18
- PageBlobChunkUploader,
19
- AppendBlobChunkUploader
12
+ from ._encryption import (
13
+ _ENCRYPTION_PROTOCOL_V1,
14
+ _ENCRYPTION_PROTOCOL_V2,
15
+ encrypt_blob,
16
+ GCMBlobEncryptionStream,
17
+ generate_blob_encryption_data,
18
+ get_adjusted_upload_size,
19
+ get_blob_encryptor_and_padder
20
20
  )
21
21
  from ._generated.models import (
22
- BlockLookupList,
23
22
  AppendPositionAccessConditions,
24
- ModifiedAccessConditions,
23
+ BlockLookupList,
24
+ ModifiedAccessConditions
25
25
  )
26
- from ._encryption import (
27
- GCMBlobEncryptionStream,
28
- encrypt_blob,
29
- get_adjusted_upload_size,
30
- get_blob_encryptor_and_padder,
31
- generate_blob_encryption_data,
32
- _ENCRYPTION_PROTOCOL_V1,
33
- _ENCRYPTION_PROTOCOL_V2
26
+ from ._shared.models import StorageErrorCode
27
+ from ._shared.response_handlers import process_storage_error, return_response_headers
28
+ from ._shared.uploads import (
29
+ AppendBlobChunkUploader,
30
+ BlockBlobChunkUploader,
31
+ PageBlobChunkUploader,
32
+ upload_data_chunks,
33
+ upload_substream_blocks
34
34
  )
35
35
 
36
36
  if TYPE_CHECKING:
37
+ from ._generated.operations import AppendBlobOperations, BlockBlobOperations, PageBlobOperations
38
+ from ._shared.models import StorageConfiguration
37
39
  BlobLeaseClient = TypeVar("BlobLeaseClient")
38
40
 
39
41
  _LARGE_BLOB_UPLOAD_MAX_READ_BUFFER_SIZE = 4 * 1024 * 1024
@@ -63,16 +65,17 @@ def _any_conditions(modified_access_conditions=None, **kwargs): # pylint: disab
63
65
 
64
66
 
65
67
  def upload_block_blob( # pylint: disable=too-many-locals, too-many-statements
66
- client=None,
67
- stream=None,
68
- length=None,
69
- overwrite=None,
70
- headers=None,
71
- validate_content=None,
72
- max_concurrency=None,
73
- blob_settings=None,
74
- encryption_options=None,
75
- **kwargs):
68
+ client: "BlockBlobOperations",
69
+ stream: IO,
70
+ overwrite: bool,
71
+ encryption_options: Dict[str, Any],
72
+ blob_settings: "StorageConfiguration",
73
+ headers: Dict[str, Any],
74
+ validate_content: bool,
75
+ max_concurrency: Optional[int],
76
+ length: Optional[int] = None,
77
+ **kwargs: Any
78
+ ) -> Dict[str, Any]:
76
79
  try:
77
80
  if not overwrite and not _any_conditions(**kwargs):
78
81
  kwargs['modified_access_conditions'].if_none_match = '*'
@@ -91,7 +94,7 @@ def upload_block_blob( # pylint: disable=too-many-locals, too-many-statements
91
94
 
92
95
  # Do single put if the size is smaller than or equal config.max_single_put_size
93
96
  if adjusted_count is not None and (adjusted_count <= blob_settings.max_single_put_size):
94
- data = stream.read(length)
97
+ data = stream.read(length or -1)
95
98
  if not isinstance(data, bytes):
96
99
  raise TypeError('Blob data should be of type bytes.')
97
100
 
@@ -100,7 +103,7 @@ def upload_block_blob( # pylint: disable=too-many-locals, too-many-statements
100
103
  headers['x-ms-meta-encryptiondata'] = encryption_data
101
104
 
102
105
  response = client.upload(
103
- body=data,
106
+ body=data, # type: ignore [arg-type]
104
107
  content_length=adjusted_count,
105
108
  blob_http_headers=blob_headers,
106
109
  headers=headers,
@@ -118,7 +121,7 @@ def upload_block_blob( # pylint: disable=too-many-locals, too-many-statements
118
121
  if progress_hook:
119
122
  progress_hook(adjusted_count, adjusted_count)
120
123
 
121
- return response
124
+ return cast(Dict[str, Any], response)
122
125
 
123
126
  use_original_upload_path = blob_settings.use_byte_buffer or \
124
127
  validate_content or encryption_options.get('required') or \
@@ -130,10 +133,10 @@ def upload_block_blob( # pylint: disable=too-many-locals, too-many-statements
130
133
  total_size = length
131
134
  encryptor, padder = None, None
132
135
  if encryption_options and encryption_options.get('key'):
133
- cek, iv, encryption_data = generate_blob_encryption_data(
136
+ cek, iv, encryption_metadata = generate_blob_encryption_data(
134
137
  encryption_options['key'],
135
138
  encryption_options['version'])
136
- headers['x-ms-meta-encryptiondata'] = encryption_data
139
+ headers['x-ms-meta-encryptiondata'] = encryption_metadata
137
140
 
138
141
  if encryption_options['version'] == _ENCRYPTION_PROTOCOL_V1:
139
142
  encryptor, padder = get_blob_encryptor_and_padder(cek, iv, True)
@@ -143,7 +146,9 @@ def upload_block_blob( # pylint: disable=too-many-locals, too-many-statements
143
146
  # Adjust total_size for encryption V2
144
147
  total_size = adjusted_count
145
148
  # V2 wraps the data stream with an encryption stream
146
- stream = GCMBlobEncryptionStream(cek, stream)
149
+ if cek is None:
150
+ raise ValueError("Generate encryption metadata failed. 'cek' is None.")
151
+ stream = GCMBlobEncryptionStream(cek, stream) # type: ignore [assignment]
147
152
 
148
153
  block_ids = upload_data_chunks(
149
154
  service=client,
@@ -175,7 +180,7 @@ def upload_block_blob( # pylint: disable=too-many-locals, too-many-statements
175
180
 
176
181
  block_lookup = BlockLookupList(committed=[], uncommitted=[], latest=[])
177
182
  block_lookup.latest = block_ids
178
- return client.commit_block_list(
183
+ return cast(Dict[str, Any], client.commit_block_list(
179
184
  block_lookup,
180
185
  blob_http_headers=blob_headers,
181
186
  cls=return_response_headers,
@@ -186,7 +191,7 @@ def upload_block_blob( # pylint: disable=too-many-locals, too-many-statements
186
191
  immutability_policy_expiry=immutability_policy_expiry,
187
192
  immutability_policy_mode=immutability_policy_mode,
188
193
  legal_hold=legal_hold,
189
- **kwargs)
194
+ **kwargs))
190
195
  except HttpResponseError as error:
191
196
  try:
192
197
  process_storage_error(error)
@@ -197,16 +202,17 @@ def upload_block_blob( # pylint: disable=too-many-locals, too-many-statements
197
202
 
198
203
 
199
204
  def upload_page_blob(
200
- client=None,
201
- stream=None,
202
- length=None,
203
- overwrite=None,
204
- headers=None,
205
- validate_content=None,
206
- max_concurrency=None,
207
- blob_settings=None,
208
- encryption_options=None,
209
- **kwargs):
205
+ client: "PageBlobOperations",
206
+ overwrite: bool,
207
+ encryption_options: Dict[str, Any],
208
+ blob_settings: "StorageConfiguration",
209
+ headers: Dict[str, Any],
210
+ stream: IO,
211
+ length: Optional[int] = None,
212
+ validate_content: Optional[bool] = None,
213
+ max_concurrency: Optional[int] = None,
214
+ **kwargs: Any
215
+ ) -> Dict[str, Any]:
210
216
  try:
211
217
  if not overwrite and not _any_conditions(**kwargs):
212
218
  kwargs['modified_access_conditions'].if_none_match = '*'
@@ -232,18 +238,18 @@ def upload_page_blob(
232
238
  blob_tags_string = kwargs.pop('blob_tags_string', None)
233
239
  progress_hook = kwargs.pop('progress_hook', None)
234
240
 
235
- response = client.create(
241
+ response = cast(Dict[str, Any], client.create(
236
242
  content_length=0,
237
243
  blob_content_length=length,
238
- blob_sequence_number=None,
244
+ blob_sequence_number=None, # type: ignore [arg-type]
239
245
  blob_http_headers=kwargs.pop('blob_headers', None),
240
246
  blob_tags_string=blob_tags_string,
241
247
  tier=tier,
242
248
  cls=return_response_headers,
243
249
  headers=headers,
244
- **kwargs)
250
+ **kwargs))
245
251
  if length == 0:
246
- return response
252
+ return cast(Dict[str, Any], response)
247
253
 
248
254
  if encryption_options and encryption_options.get('key'):
249
255
  if encryption_options['version'] == _ENCRYPTION_PROTOCOL_V1:
@@ -252,7 +258,7 @@ def upload_page_blob(
252
258
  kwargs['padder'] = padder
253
259
 
254
260
  kwargs['modified_access_conditions'] = ModifiedAccessConditions(if_match=response['etag'])
255
- return upload_data_chunks(
261
+ return cast(Dict[str, Any], upload_data_chunks(
256
262
  service=client,
257
263
  uploader_class=PageBlobChunkUploader,
258
264
  total_size=length,
@@ -262,7 +268,7 @@ def upload_page_blob(
262
268
  validate_content=validate_content,
263
269
  progress_hook=progress_hook,
264
270
  headers=headers,
265
- **kwargs)
271
+ **kwargs))
266
272
 
267
273
  except HttpResponseError as error:
268
274
  try:
@@ -274,16 +280,17 @@ def upload_page_blob(
274
280
 
275
281
 
276
282
  def upload_append_blob( # pylint: disable=unused-argument
277
- client=None,
278
- stream=None,
279
- length=None,
280
- overwrite=None,
281
- headers=None,
282
- validate_content=None,
283
- max_concurrency=None,
284
- blob_settings=None,
285
- encryption_options=None,
286
- **kwargs):
283
+ client: "AppendBlobOperations",
284
+ overwrite: bool,
285
+ encryption_options: Dict[str, Any],
286
+ blob_settings: "StorageConfiguration",
287
+ headers: Dict[str, Any],
288
+ stream: IO,
289
+ length: Optional[int] = None,
290
+ validate_content: Optional[bool] = None,
291
+ max_concurrency: Optional[int] = None,
292
+ **kwargs: Any
293
+ ) -> Dict[str, Any]:
287
294
  try:
288
295
  if length == 0:
289
296
  return {}
@@ -302,7 +309,7 @@ def upload_append_blob( # pylint: disable=unused-argument
302
309
  headers=headers,
303
310
  blob_tags_string=blob_tags_string,
304
311
  **kwargs)
305
- return upload_data_chunks(
312
+ return cast(Dict[str, Any], upload_data_chunks(
306
313
  service=client,
307
314
  uploader_class=AppendBlobChunkUploader,
308
315
  total_size=length,
@@ -313,9 +320,9 @@ def upload_append_blob( # pylint: disable=unused-argument
313
320
  append_position_access_conditions=append_conditions,
314
321
  progress_hook=progress_hook,
315
322
  headers=headers,
316
- **kwargs)
323
+ **kwargs))
317
324
  except HttpResponseError as error:
318
- if error.response.status_code != 404:
325
+ if error.response.status_code != 404: # type: ignore [union-attr]
319
326
  raise
320
327
  # rewind the request body if it is a stream
321
328
  if hasattr(stream, 'read'):
@@ -331,7 +338,7 @@ def upload_append_blob( # pylint: disable=unused-argument
331
338
  headers=headers,
332
339
  blob_tags_string=blob_tags_string,
333
340
  **kwargs)
334
- return upload_data_chunks(
341
+ return cast(Dict[str, Any], upload_data_chunks(
335
342
  service=client,
336
343
  uploader_class=AppendBlobChunkUploader,
337
344
  total_size=length,
@@ -342,6 +349,6 @@ def upload_append_blob( # pylint: disable=unused-argument
342
349
  append_position_access_conditions=append_conditions,
343
350
  progress_hook=progress_hook,
344
351
  headers=headers,
345
- **kwargs)
352
+ **kwargs))
346
353
  except HttpResponseError as error:
347
354
  process_storage_error(error)
@@ -4,4 +4,4 @@
4
4
  # license information.
5
5
  # --------------------------------------------------------------------------
6
6
 
7
- VERSION = "12.21.0b1"
7
+ VERSION = "12.22.0"
@@ -7,6 +7,7 @@
7
7
 
8
8
  import os
9
9
 
10
+ from typing import Any, AnyStr, Dict, cast, IO, Iterable, Optional, Union, TYPE_CHECKING
10
11
  from ._list_blobs_helper import BlobPrefix
11
12
  from .._models import BlobType
12
13
  from .._shared.policies_async import ExponentialRetry, LinearRetry
@@ -16,13 +17,17 @@ from ._blob_service_client_async import BlobServiceClient
16
17
  from ._lease_async import BlobLeaseClient
17
18
  from ._download_async import StorageStreamDownloader
18
19
 
20
+ if TYPE_CHECKING:
21
+ from azure.core.credentials import AzureNamedKeyCredential, AzureSasCredential
22
+ from azure.core.credentials_async import AsyncTokenCredential
23
+
19
24
 
20
25
  async def upload_blob_to_url(
21
- blob_url, # type: str
22
- data, # type: Union[Iterable[AnyStr], IO[AnyStr]]
23
- credential=None, # type: Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, "TokenCredential"]] # pylint: disable=line-too-long
24
- **kwargs):
25
- # type: (...) -> dict[str, Any]
26
+ blob_url: str,
27
+ data: Union[Iterable[AnyStr], IO[AnyStr]],
28
+ credential: Optional[Union[str, Dict[str, str], "AzureNamedKeyCredential", "AzureSasCredential", "AsyncTokenCredential"]] = None, # pylint: disable=line-too-long
29
+ **kwargs: Any
30
+ ) -> Dict[str, Any]:
26
31
  """Upload data to a given URL
27
32
 
28
33
  The data will be uploaded as a block blob.
@@ -72,7 +77,10 @@ async def upload_blob_to_url(
72
77
  :rtype: dict[str, Any]
73
78
  """
74
79
  async with BlobClient.from_blob_url(blob_url, credential=credential) as client:
75
- return await client.upload_blob(data=data, blob_type=BlobType.BlockBlob, **kwargs)
80
+ return await cast(BlobClient, client).upload_blob(
81
+ data=data,
82
+ blob_type=BlobType.BLOCKBLOB,
83
+ **kwargs)
76
84
 
77
85
 
78
86
  # Download data to specified open file-handle.
@@ -82,11 +90,11 @@ async def _download_to_stream(client, handle, **kwargs):
82
90
 
83
91
 
84
92
  async def download_blob_from_url(
85
- blob_url, # type: str
86
- output, # type: str
87
- credential=None, # type: Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, "TokenCredential"]] # pylint: disable=line-too-long
88
- **kwargs):
89
- # type: (...) -> None
93
+ blob_url: str,
94
+ output: str,
95
+ credential: Optional[Union[str, Dict[str, str], "AzureNamedKeyCredential", "AzureSasCredential", "AsyncTokenCredential"]] = None, # pylint: disable=line-too-long
96
+ **kwargs: Any
97
+ ) -> None:
90
98
  """Download the contents of a blob to a local file or stream.
91
99
 
92
100
  :param str blob_url: