azure-storage-blob 12.25.0b1__py3-none-any.whl → 12.26.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 (64) hide show
  1. azure/storage/blob/__init__.py +3 -2
  2. azure/storage/blob/_blob_client.py +94 -41
  3. azure/storage/blob/_blob_client_helpers.py +19 -4
  4. azure/storage/blob/_blob_service_client.py +16 -13
  5. azure/storage/blob/_container_client.py +25 -22
  6. azure/storage/blob/_deserialize.py +1 -1
  7. azure/storage/blob/_download.py +7 -7
  8. azure/storage/blob/_encryption.py +177 -184
  9. azure/storage/blob/_generated/_azure_blob_storage.py +1 -1
  10. azure/storage/blob/_generated/_configuration.py +2 -2
  11. azure/storage/blob/_generated/_serialization.py +3 -3
  12. azure/storage/blob/_generated/aio/_azure_blob_storage.py +1 -1
  13. azure/storage/blob/_generated/aio/_configuration.py +2 -2
  14. azure/storage/blob/_generated/aio/operations/_append_blob_operations.py +5 -4
  15. azure/storage/blob/_generated/aio/operations/_blob_operations.py +5 -25
  16. azure/storage/blob/_generated/aio/operations/_block_blob_operations.py +9 -7
  17. azure/storage/blob/_generated/aio/operations/_container_operations.py +1 -19
  18. azure/storage/blob/_generated/aio/operations/_page_blob_operations.py +5 -10
  19. azure/storage/blob/_generated/aio/operations/_service_operations.py +1 -8
  20. azure/storage/blob/_generated/models/__init__.py +2 -0
  21. azure/storage/blob/_generated/models/_azure_blob_storage_enums.py +6 -0
  22. azure/storage/blob/_generated/operations/_append_blob_operations.py +12 -9
  23. azure/storage/blob/_generated/operations/_blob_operations.py +32 -49
  24. azure/storage/blob/_generated/operations/_block_blob_operations.py +21 -13
  25. azure/storage/blob/_generated/operations/_container_operations.py +19 -37
  26. azure/storage/blob/_generated/operations/_page_blob_operations.py +17 -19
  27. azure/storage/blob/_generated/operations/_service_operations.py +9 -17
  28. azure/storage/blob/_lease.py +1 -0
  29. azure/storage/blob/_quick_query_helper.py +20 -24
  30. azure/storage/blob/_serialize.py +1 -0
  31. azure/storage/blob/_shared/__init__.py +7 -7
  32. azure/storage/blob/_shared/authentication.py +49 -32
  33. azure/storage/blob/_shared/avro/avro_io.py +45 -43
  34. azure/storage/blob/_shared/avro/avro_io_async.py +42 -41
  35. azure/storage/blob/_shared/avro/datafile.py +24 -21
  36. azure/storage/blob/_shared/avro/datafile_async.py +15 -15
  37. azure/storage/blob/_shared/avro/schema.py +196 -217
  38. azure/storage/blob/_shared/base_client.py +87 -61
  39. azure/storage/blob/_shared/base_client_async.py +58 -51
  40. azure/storage/blob/_shared/constants.py +1 -1
  41. azure/storage/blob/_shared/models.py +93 -92
  42. azure/storage/blob/_shared/parser.py +3 -3
  43. azure/storage/blob/_shared/policies.py +176 -145
  44. azure/storage/blob/_shared/policies_async.py +59 -70
  45. azure/storage/blob/_shared/request_handlers.py +51 -47
  46. azure/storage/blob/_shared/response_handlers.py +49 -45
  47. azure/storage/blob/_shared/shared_access_signature.py +67 -71
  48. azure/storage/blob/_shared/uploads.py +56 -49
  49. azure/storage/blob/_shared/uploads_async.py +72 -61
  50. azure/storage/blob/_shared_access_signature.py +3 -1
  51. azure/storage/blob/_version.py +1 -1
  52. azure/storage/blob/aio/__init__.py +3 -2
  53. azure/storage/blob/aio/_blob_client_async.py +241 -44
  54. azure/storage/blob/aio/_blob_service_client_async.py +13 -11
  55. azure/storage/blob/aio/_container_client_async.py +28 -25
  56. azure/storage/blob/aio/_download_async.py +16 -12
  57. azure/storage/blob/aio/_lease_async.py +1 -0
  58. azure/storage/blob/aio/_quick_query_helper_async.py +194 -0
  59. {azure_storage_blob-12.25.0b1.dist-info → azure_storage_blob-12.26.0.dist-info}/METADATA +7 -7
  60. azure_storage_blob-12.26.0.dist-info/RECORD +85 -0
  61. {azure_storage_blob-12.25.0b1.dist-info → azure_storage_blob-12.26.0.dist-info}/WHEEL +1 -1
  62. azure_storage_blob-12.25.0b1.dist-info/RECORD +0 -84
  63. {azure_storage_blob-12.25.0b1.dist-info → azure_storage_blob-12.26.0.dist-info}/LICENSE +0 -0
  64. {azure_storage_blob-12.25.0b1.dist-info → azure_storage_blob-12.26.0.dist-info}/top_level.txt +0 -0
@@ -20,7 +20,10 @@ from urllib.parse import parse_qs, quote
20
20
  from azure.core.credentials import AzureSasCredential, AzureNamedKeyCredential, TokenCredential
21
21
  from azure.core.exceptions import HttpResponseError
22
22
  from azure.core.pipeline import Pipeline
23
- from azure.core.pipeline.transport import HttpTransport, RequestsTransport # pylint: disable=non-abstract-transport-import, no-name-in-module
23
+ from azure.core.pipeline.transport import ( # pylint: disable=non-abstract-transport-import, no-name-in-module
24
+ HttpTransport,
25
+ RequestsTransport,
26
+ )
24
27
  from azure.core.pipeline.policies import (
25
28
  AzureSasCredentialPolicy,
26
29
  ContentDecodePolicy,
@@ -65,27 +68,42 @@ _SERVICE_PARAMS = {
65
68
 
66
69
 
67
70
  class StorageAccountHostsMixin(object):
71
+
68
72
  _client: Any
73
+ _hosts: Dict[str, str]
74
+
69
75
  def __init__(
70
76
  self,
71
77
  parsed_url: Any,
72
78
  service: str,
73
- credential: Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, "AsyncTokenCredential", TokenCredential]] = None, # pylint: disable=line-too-long
74
- **kwargs: Any
79
+ credential: Optional[
80
+ Union[
81
+ str,
82
+ Dict[str, str],
83
+ AzureNamedKeyCredential,
84
+ AzureSasCredential,
85
+ "AsyncTokenCredential",
86
+ TokenCredential,
87
+ ]
88
+ ] = None,
89
+ **kwargs: Any,
75
90
  ) -> None:
76
91
  self._location_mode = kwargs.get("_location_mode", LocationMode.PRIMARY)
77
- self._hosts = kwargs.get("_hosts")
92
+ self._hosts = kwargs.get("_hosts", {})
78
93
  self.scheme = parsed_url.scheme
79
94
  self._is_localhost = False
80
95
 
81
96
  if service not in ["blob", "queue", "file-share", "dfs"]:
82
97
  raise ValueError(f"Invalid service: {service}")
83
- service_name = service.split('-')[0]
98
+ service_name = service.split("-")[0]
84
99
  account = parsed_url.netloc.split(f".{service_name}.core.")
85
100
 
86
101
  self.account_name = account[0] if len(account) > 1 else None
87
- if not self.account_name and parsed_url.netloc.startswith("localhost") \
88
- or parsed_url.netloc.startswith("127.0.0.1"):
102
+ if (
103
+ not self.account_name
104
+ and parsed_url.netloc.startswith("localhost")
105
+ or parsed_url.netloc.startswith("127.0.0.1")
106
+ ):
89
107
  self._is_localhost = True
90
108
  self.account_name = parsed_url.path.strip("/")
91
109
 
@@ -93,7 +111,7 @@ class StorageAccountHostsMixin(object):
93
111
  if self.scheme.lower() != "https" and hasattr(self.credential, "get_token"):
94
112
  raise ValueError("Token credential is only supported with HTTPS.")
95
113
 
96
- secondary_hostname = None
114
+ secondary_hostname = ""
97
115
  if hasattr(self.credential, "account_name"):
98
116
  self.account_name = self.credential.account_name
99
117
  secondary_hostname = f"{self.credential.account_name}-secondary.{service_name}.{SERVICE_HOST_BASE}"
@@ -103,7 +121,7 @@ class StorageAccountHostsMixin(object):
103
121
  secondary_hostname = parsed_url.netloc.replace(account[0], account[0] + "-secondary")
104
122
  if kwargs.get("secondary_hostname"):
105
123
  secondary_hostname = kwargs["secondary_hostname"]
106
- primary_hostname = (parsed_url.netloc + parsed_url.path).rstrip('/')
124
+ primary_hostname = (parsed_url.netloc + parsed_url.path).rstrip("/")
107
125
  self._hosts = {LocationMode.PRIMARY: primary_hostname, LocationMode.SECONDARY: secondary_hostname}
108
126
 
109
127
  self._sdk_moniker = f"storage-{service}/{VERSION}"
@@ -116,70 +134,76 @@ class StorageAccountHostsMixin(object):
116
134
  def __exit__(self, *args):
117
135
  self._client.__exit__(*args)
118
136
 
119
- def close(self):
120
- """ This method is to close the sockets opened by the client.
137
+ def close(self) -> None:
138
+ """This method is to close the sockets opened by the client.
121
139
  It need not be used when using with a context manager.
122
140
  """
123
141
  self._client.close()
124
142
 
125
143
  @property
126
- def url(self):
144
+ def url(self) -> str:
127
145
  """The full endpoint URL to this entity, including SAS token if used.
128
146
 
129
147
  This could be either the primary endpoint,
130
148
  or the secondary endpoint depending on the current :func:`location_mode`.
131
- :returns: The full endpoint URL to this entity, including SAS token if used.
149
+
150
+ :return: The full endpoint URL to this entity, including SAS token if used.
132
151
  :rtype: str
133
152
  """
134
- return self._format_url(self._hosts[self._location_mode])
153
+ return self._format_url(self._hosts[self._location_mode]) # type: ignore
135
154
 
136
155
  @property
137
- def primary_endpoint(self):
156
+ def primary_endpoint(self) -> str:
138
157
  """The full primary endpoint URL.
139
158
 
159
+ :return: The full primary endpoint URL.
140
160
  :rtype: str
141
161
  """
142
- return self._format_url(self._hosts[LocationMode.PRIMARY])
162
+ return self._format_url(self._hosts[LocationMode.PRIMARY]) # type: ignore
143
163
 
144
164
  @property
145
- def primary_hostname(self):
165
+ def primary_hostname(self) -> str:
146
166
  """The hostname of the primary endpoint.
147
167
 
168
+ :return: The hostname of the primary endpoint.
148
169
  :rtype: str
149
170
  """
150
171
  return self._hosts[LocationMode.PRIMARY]
151
172
 
152
173
  @property
153
- def secondary_endpoint(self):
174
+ def secondary_endpoint(self) -> str:
154
175
  """The full secondary endpoint URL if configured.
155
176
 
156
177
  If not available a ValueError will be raised. To explicitly specify a secondary hostname, use the optional
157
178
  `secondary_hostname` keyword argument on instantiation.
158
179
 
180
+ :return: The full secondary endpoint URL.
159
181
  :rtype: str
160
- :raise ValueError:
182
+ :raise ValueError: If no secondary endpoint is configured.
161
183
  """
162
184
  if not self._hosts[LocationMode.SECONDARY]:
163
185
  raise ValueError("No secondary host configured.")
164
- return self._format_url(self._hosts[LocationMode.SECONDARY])
186
+ return self._format_url(self._hosts[LocationMode.SECONDARY]) # type: ignore
165
187
 
166
188
  @property
167
- def secondary_hostname(self):
189
+ def secondary_hostname(self) -> Optional[str]:
168
190
  """The hostname of the secondary endpoint.
169
191
 
170
192
  If not available this will be None. To explicitly specify a secondary hostname, use the optional
171
193
  `secondary_hostname` keyword argument on instantiation.
172
194
 
195
+ :return: The hostname of the secondary endpoint, or None if not configured.
173
196
  :rtype: Optional[str]
174
197
  """
175
198
  return self._hosts[LocationMode.SECONDARY]
176
199
 
177
200
  @property
178
- def location_mode(self):
201
+ def location_mode(self) -> str:
179
202
  """The location mode that the client is currently using.
180
203
 
181
204
  By default this will be "primary". Options include "primary" and "secondary".
182
205
 
206
+ :return: The current location mode.
183
207
  :rtype: str
184
208
  """
185
209
 
@@ -202,11 +226,16 @@ class StorageAccountHostsMixin(object):
202
226
  return self._client._config.version # pylint: disable=protected-access
203
227
 
204
228
  def _format_query_string(
205
- self, sas_token: Optional[str],
206
- credential: Optional[Union[str, Dict[str, str], "AzureNamedKeyCredential", "AzureSasCredential", TokenCredential]], # pylint: disable=line-too-long
229
+ self,
230
+ sas_token: Optional[str],
231
+ credential: Optional[
232
+ Union[str, Dict[str, str], "AzureNamedKeyCredential", "AzureSasCredential", TokenCredential]
233
+ ],
207
234
  snapshot: Optional[str] = None,
208
- share_snapshot: Optional[str] = None
209
- ) -> Tuple[str, Optional[Union[str, Dict[str, str], "AzureNamedKeyCredential", "AzureSasCredential", TokenCredential]]]: # pylint: disable=line-too-long
235
+ share_snapshot: Optional[str] = None,
236
+ ) -> Tuple[
237
+ str, Optional[Union[str, Dict[str, str], "AzureNamedKeyCredential", "AzureSasCredential", TokenCredential]]
238
+ ]:
210
239
  query_str = "?"
211
240
  if snapshot:
212
241
  query_str += f"snapshot={snapshot}&"
@@ -214,7 +243,8 @@ class StorageAccountHostsMixin(object):
214
243
  query_str += f"sharesnapshot={share_snapshot}&"
215
244
  if sas_token and isinstance(credential, AzureSasCredential):
216
245
  raise ValueError(
217
- "You cannot use AzureSasCredential when the resource URI also contains a Shared Access Signature.")
246
+ "You cannot use AzureSasCredential when the resource URI also contains a Shared Access Signature."
247
+ )
218
248
  if _is_credential_sastoken(credential):
219
249
  credential = cast(str, credential)
220
250
  query_str += credential.lstrip("?")
@@ -224,13 +254,16 @@ class StorageAccountHostsMixin(object):
224
254
  return query_str.rstrip("?&"), credential
225
255
 
226
256
  def _create_pipeline(
227
- self, credential: Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, TokenCredential]] = None, # pylint: disable=line-too-long
228
- **kwargs: Any
257
+ self,
258
+ credential: Optional[
259
+ Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, TokenCredential]
260
+ ] = None,
261
+ **kwargs: Any,
229
262
  ) -> Tuple[StorageConfiguration, Pipeline]:
230
263
  self._credential_policy: Any = None
231
264
  if hasattr(credential, "get_token"):
232
- if kwargs.get('audience'):
233
- audience = str(kwargs.pop('audience')).rstrip('/') + DEFAULT_OAUTH_SCOPE
265
+ if kwargs.get("audience"):
266
+ audience = str(kwargs.pop("audience")).rstrip("/") + DEFAULT_OAUTH_SCOPE
234
267
  else:
235
268
  audience = STORAGE_OAUTH_SCOPE
236
269
  self._credential_policy = StorageBearerTokenCredentialPolicy(cast(TokenCredential, credential), audience)
@@ -264,22 +297,18 @@ class StorageAccountHostsMixin(object):
264
297
  config.logging_policy,
265
298
  StorageResponseHook(**kwargs),
266
299
  DistributedTracingPolicy(**kwargs),
267
- HttpLoggingPolicy(**kwargs)
300
+ HttpLoggingPolicy(**kwargs),
268
301
  ]
269
302
  if kwargs.get("_additional_pipeline_policies"):
270
303
  policies = policies + kwargs.get("_additional_pipeline_policies") # type: ignore
271
304
  config.transport = transport # type: ignore
272
305
  return config, Pipeline(transport, policies=policies)
273
306
 
274
- def _batch_send(
275
- self,
276
- *reqs: "HttpRequest",
277
- **kwargs: Any
278
- ) -> Iterator["HttpResponse"]:
307
+ def _batch_send(self, *reqs: "HttpRequest", **kwargs: Any) -> Iterator["HttpResponse"]:
279
308
  """Given a series of request, do a Storage batch call.
280
309
 
281
310
  :param HttpRequest reqs: A collection of HttpRequest objects.
282
- :returns: An iterator of HttpResponse objects.
311
+ :return: An iterator of HttpResponse objects.
283
312
  :rtype: Iterator[HttpResponse]
284
313
  """
285
314
  # Pop it here, so requests doesn't feel bad about additional kwarg
@@ -288,25 +317,21 @@ class StorageAccountHostsMixin(object):
288
317
 
289
318
  request = self._client._client.post( # pylint: disable=protected-access
290
319
  url=(
291
- f'{self.scheme}://{self.primary_hostname}/'
320
+ f"{self.scheme}://{self.primary_hostname}/"
292
321
  f"{kwargs.pop('path', '')}?{kwargs.pop('restype', '')}"
293
322
  f"comp=batch{kwargs.pop('sas', '')}{kwargs.pop('timeout', '')}"
294
323
  ),
295
324
  headers={
296
- 'x-ms-version': self.api_version,
297
- "Content-Type": "multipart/mixed; boundary=" + _get_batch_request_delimiter(batch_id, False, False)
298
- }
325
+ "x-ms-version": self.api_version,
326
+ "Content-Type": "multipart/mixed; boundary=" + _get_batch_request_delimiter(batch_id, False, False),
327
+ },
299
328
  )
300
329
 
301
330
  policies = [StorageHeadersPolicy()]
302
331
  if self._credential_policy:
303
332
  policies.append(self._credential_policy)
304
333
 
305
- request.set_multipart_mixed(
306
- *reqs,
307
- policies=policies,
308
- enforce_https=False
309
- )
334
+ request.set_multipart_mixed(*reqs, policies=policies, enforce_https=False)
310
335
 
311
336
  Pipeline._prepare_multipart_mixed_request(request) # pylint: disable=protected-access
312
337
  body = serialize_batch_body(request.multipart_mixed_info[0], batch_id)
@@ -314,9 +339,7 @@ class StorageAccountHostsMixin(object):
314
339
 
315
340
  temp = request.multipart_mixed_info
316
341
  request.multipart_mixed_info = None
317
- pipeline_response = self._pipeline.run(
318
- request, **kwargs
319
- )
342
+ pipeline_response = self._pipeline.run(request, **kwargs)
320
343
  response = pipeline_response.http_response
321
344
  request.multipart_mixed_info = temp
322
345
 
@@ -328,8 +351,7 @@ class StorageAccountHostsMixin(object):
328
351
  parts = list(response.parts())
329
352
  if any(p for p in parts if not 200 <= p.status_code < 300):
330
353
  error = PartialBatchErrorException(
331
- message="There is a partial failure in the batch operation.",
332
- response=response, parts=parts
354
+ message="There is a partial failure in the batch operation.", response=response, parts=parts
333
355
  )
334
356
  raise error
335
357
  return iter(parts)
@@ -343,6 +365,7 @@ class TransportWrapper(HttpTransport):
343
365
  by a `get_client` method does not close the outer transport for the parent
344
366
  when used in a context manager.
345
367
  """
368
+
346
369
  def __init__(self, transport):
347
370
  self._transport = transport
348
371
 
@@ -364,7 +387,9 @@ class TransportWrapper(HttpTransport):
364
387
 
365
388
  def _format_shared_key_credential(
366
389
  account_name: Optional[str],
367
- credential: Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, "AsyncTokenCredential", TokenCredential]] = None # pylint: disable=line-too-long
390
+ credential: Optional[
391
+ Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, "AsyncTokenCredential", TokenCredential]
392
+ ] = None,
368
393
  ) -> Any:
369
394
  if isinstance(credential, str):
370
395
  if not account_name:
@@ -384,8 +409,12 @@ def _format_shared_key_credential(
384
409
  def parse_connection_str(
385
410
  conn_str: str,
386
411
  credential: Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, TokenCredential]],
387
- service: str
388
- ) -> Tuple[str, Optional[str], Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, TokenCredential]]]: # pylint: disable=line-too-long
412
+ service: str,
413
+ ) -> Tuple[
414
+ str,
415
+ Optional[str],
416
+ Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, TokenCredential]],
417
+ ]:
389
418
  conn_str = conn_str.rstrip(";")
390
419
  conn_settings_list = [s.split("=", 1) for s in conn_str.split(";")]
391
420
  if any(len(tup) != 2 for tup in conn_settings_list):
@@ -407,14 +436,11 @@ def parse_connection_str(
407
436
  if endpoints["secondary"] in conn_settings:
408
437
  raise ValueError("Connection string specifies only secondary endpoint.")
409
438
  try:
410
- primary =(
439
+ primary = (
411
440
  f"{conn_settings['DEFAULTENDPOINTSPROTOCOL']}://"
412
441
  f"{conn_settings['ACCOUNTNAME']}.{service}.{conn_settings['ENDPOINTSUFFIX']}"
413
442
  )
414
- secondary = (
415
- f"{conn_settings['ACCOUNTNAME']}-secondary."
416
- f"{service}.{conn_settings['ENDPOINTSUFFIX']}"
417
- )
443
+ secondary = f"{conn_settings['ACCOUNTNAME']}-secondary." f"{service}.{conn_settings['ENDPOINTSUFFIX']}"
418
444
  except KeyError:
419
445
  pass
420
446
 
@@ -434,7 +460,7 @@ def parse_connection_str(
434
460
 
435
461
 
436
462
  def create_configuration(**kwargs: Any) -> StorageConfiguration:
437
- # Backwards compatibility if someone is not passing sdk_moniker
463
+ # Backwards compatibility if someone is not passing sdk_moniker
438
464
  if not kwargs.get("sdk_moniker"):
439
465
  kwargs["sdk_moniker"] = f"storage-{kwargs.pop('storage_sdk')}/{VERSION}"
440
466
  config = StorageConfiguration(**kwargs)
@@ -64,18 +64,26 @@ class AsyncStorageAccountHostsMixin(object):
64
64
  async def __aexit__(self, *args):
65
65
  await self._client.__aexit__(*args)
66
66
 
67
- async def close(self):
68
- """ This method is to close the sockets opened by the client.
67
+ async def close(self) -> None:
68
+ """This method is to close the sockets opened by the client.
69
69
  It need not be used when using with a context manager.
70
+
71
+ :return: None
72
+ :rtype: None
70
73
  """
71
74
  await self._client.close()
72
75
 
73
76
  def _format_query_string(
74
- self, sas_token: Optional[str],
75
- credential: Optional[Union[str, Dict[str, str], "AzureNamedKeyCredential", "AzureSasCredential", AsyncTokenCredential]], # pylint: disable=line-too-long
77
+ self,
78
+ sas_token: Optional[str],
79
+ credential: Optional[
80
+ Union[str, Dict[str, str], "AzureNamedKeyCredential", "AzureSasCredential", AsyncTokenCredential]
81
+ ],
76
82
  snapshot: Optional[str] = None,
77
- share_snapshot: Optional[str] = None
78
- ) -> Tuple[str, Optional[Union[str, Dict[str, str], "AzureNamedKeyCredential", "AzureSasCredential", AsyncTokenCredential]]]: # pylint: disable=line-too-long
83
+ share_snapshot: Optional[str] = None,
84
+ ) -> Tuple[
85
+ str, Optional[Union[str, Dict[str, str], "AzureNamedKeyCredential", "AzureSasCredential", AsyncTokenCredential]]
86
+ ]:
79
87
  query_str = "?"
80
88
  if snapshot:
81
89
  query_str += f"snapshot={snapshot}&"
@@ -83,7 +91,8 @@ class AsyncStorageAccountHostsMixin(object):
83
91
  query_str += f"sharesnapshot={share_snapshot}&"
84
92
  if sas_token and isinstance(credential, AzureSasCredential):
85
93
  raise ValueError(
86
- "You cannot use AzureSasCredential when the resource URI also contains a Shared Access Signature.")
94
+ "You cannot use AzureSasCredential when the resource URI also contains a Shared Access Signature."
95
+ )
87
96
  if _is_credential_sastoken(credential):
88
97
  query_str += credential.lstrip("?") # type: ignore [union-attr]
89
98
  credential = None
@@ -92,35 +101,40 @@ class AsyncStorageAccountHostsMixin(object):
92
101
  return query_str.rstrip("?&"), credential
93
102
 
94
103
  def _create_pipeline(
95
- self, credential: Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, AsyncTokenCredential]] = None, # pylint: disable=line-too-long
96
- **kwargs: Any
104
+ self,
105
+ credential: Optional[
106
+ Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, AsyncTokenCredential]
107
+ ] = None,
108
+ **kwargs: Any,
97
109
  ) -> Tuple[StorageConfiguration, AsyncPipeline]:
98
110
  self._credential_policy: Optional[
99
- Union[AsyncStorageBearerTokenCredentialPolicy,
100
- SharedKeyCredentialPolicy,
101
- AzureSasCredentialPolicy]] = None
102
- if hasattr(credential, 'get_token'):
103
- if kwargs.get('audience'):
104
- audience = str(kwargs.pop('audience')).rstrip('/') + DEFAULT_OAUTH_SCOPE
111
+ Union[AsyncStorageBearerTokenCredentialPolicy, SharedKeyCredentialPolicy, AzureSasCredentialPolicy]
112
+ ] = None
113
+ if hasattr(credential, "get_token"):
114
+ if kwargs.get("audience"):
115
+ audience = str(kwargs.pop("audience")).rstrip("/") + DEFAULT_OAUTH_SCOPE
105
116
  else:
106
117
  audience = STORAGE_OAUTH_SCOPE
107
118
  self._credential_policy = AsyncStorageBearerTokenCredentialPolicy(
108
- cast(AsyncTokenCredential, credential), audience)
119
+ cast(AsyncTokenCredential, credential), audience
120
+ )
109
121
  elif isinstance(credential, SharedKeyCredentialPolicy):
110
122
  self._credential_policy = credential
111
123
  elif isinstance(credential, AzureSasCredential):
112
124
  self._credential_policy = AzureSasCredentialPolicy(credential)
113
125
  elif credential is not None:
114
126
  raise TypeError(f"Unsupported credential: {type(credential)}")
115
- config = kwargs.get('_configuration') or create_configuration(**kwargs)
116
- if kwargs.get('_pipeline'):
117
- return config, kwargs['_pipeline']
118
- transport = kwargs.get('transport')
127
+ config = kwargs.get("_configuration") or create_configuration(**kwargs)
128
+ if kwargs.get("_pipeline"):
129
+ return config, kwargs["_pipeline"]
130
+ transport = kwargs.get("transport")
119
131
  kwargs.setdefault("connection_timeout", CONNECTION_TIMEOUT)
120
132
  kwargs.setdefault("read_timeout", READ_TIMEOUT)
121
133
  if not transport:
122
134
  try:
123
- from azure.core.pipeline.transport import AioHttpTransport # pylint: disable=non-abstract-transport-import
135
+ from azure.core.pipeline.transport import ( # pylint: disable=non-abstract-transport-import
136
+ AioHttpTransport,
137
+ )
124
138
  except ImportError as exc:
125
139
  raise ImportError("Unable to create async transport. Please check aiohttp is installed.") from exc
126
140
  transport = AioHttpTransport(**kwargs)
@@ -143,53 +157,41 @@ class AsyncStorageAccountHostsMixin(object):
143
157
  HttpLoggingPolicy(**kwargs),
144
158
  ]
145
159
  if kwargs.get("_additional_pipeline_policies"):
146
- policies = policies + kwargs.get("_additional_pipeline_policies") #type: ignore
147
- config.transport = transport #type: ignore
148
- return config, AsyncPipeline(transport, policies=policies) #type: ignore
160
+ policies = policies + kwargs.get("_additional_pipeline_policies") # type: ignore
161
+ config.transport = transport # type: ignore
162
+ return config, AsyncPipeline(transport, policies=policies) # type: ignore
149
163
 
150
- async def _batch_send(
151
- self,
152
- *reqs: "HttpRequest",
153
- **kwargs: Any
154
- ) -> AsyncList["HttpResponse"]:
164
+ async def _batch_send(self, *reqs: "HttpRequest", **kwargs: Any) -> AsyncList["HttpResponse"]:
155
165
  """Given a series of request, do a Storage batch call.
156
166
 
157
167
  :param HttpRequest reqs: A collection of HttpRequest objects.
158
- :returns: An AsyncList of HttpResponse objects.
168
+ :return: An AsyncList of HttpResponse objects.
159
169
  :rtype: AsyncList[HttpResponse]
160
170
  """
161
171
  # Pop it here, so requests doesn't feel bad about additional kwarg
162
172
  raise_on_any_failure = kwargs.pop("raise_on_any_failure", True)
163
173
  request = self._client._client.post( # pylint: disable=protected-access
164
174
  url=(
165
- f'{self.scheme}://{self.primary_hostname}/'
175
+ f"{self.scheme}://{self.primary_hostname}/"
166
176
  f"{kwargs.pop('path', '')}?{kwargs.pop('restype', '')}"
167
177
  f"comp=batch{kwargs.pop('sas', '')}{kwargs.pop('timeout', '')}"
168
178
  ),
169
- headers={
170
- 'x-ms-version': self.api_version
171
- }
179
+ headers={"x-ms-version": self.api_version},
172
180
  )
173
181
 
174
182
  policies = [StorageHeadersPolicy()]
175
183
  if self._credential_policy:
176
184
  policies.append(self._credential_policy) # type: ignore
177
185
 
178
- request.set_multipart_mixed(
179
- *reqs,
180
- policies=policies,
181
- enforce_https=False
182
- )
186
+ request.set_multipart_mixed(*reqs, policies=policies, enforce_https=False)
183
187
 
184
- pipeline_response = await self._pipeline.run(
185
- request, **kwargs
186
- )
188
+ pipeline_response = await self._pipeline.run(request, **kwargs)
187
189
  response = pipeline_response.http_response
188
190
 
189
191
  try:
190
192
  if response.status_code not in [202]:
191
193
  raise HttpResponseError(response=response)
192
- parts = response.parts() # Return an AsyncIterator
194
+ parts = response.parts() # Return an AsyncIterator
193
195
  if raise_on_any_failure:
194
196
  parts_list = []
195
197
  async for part in parts:
@@ -197,7 +199,8 @@ class AsyncStorageAccountHostsMixin(object):
197
199
  if any(p for p in parts_list if not 200 <= p.status_code < 300):
198
200
  error = PartialBatchErrorException(
199
201
  message="There is a partial failure in the batch operation.",
200
- response=response, parts=parts_list
202
+ response=response,
203
+ parts=parts_list,
201
204
  )
202
205
  raise error
203
206
  return AsyncList(parts_list)
@@ -205,11 +208,16 @@ class AsyncStorageAccountHostsMixin(object):
205
208
  except HttpResponseError as error:
206
209
  process_storage_error(error)
207
210
 
211
+
208
212
  def parse_connection_str(
209
213
  conn_str: str,
210
214
  credential: Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, AsyncTokenCredential]],
211
- service: str
212
- ) -> Tuple[str, Optional[str], Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, AsyncTokenCredential]]]: # pylint: disable=line-too-long
215
+ service: str,
216
+ ) -> Tuple[
217
+ str,
218
+ Optional[str],
219
+ Optional[Union[str, Dict[str, str], AzureNamedKeyCredential, AzureSasCredential, AsyncTokenCredential]],
220
+ ]:
213
221
  conn_str = conn_str.rstrip(";")
214
222
  conn_settings_list = [s.split("=", 1) for s in conn_str.split(";")]
215
223
  if any(len(tup) != 2 for tup in conn_settings_list):
@@ -231,14 +239,11 @@ def parse_connection_str(
231
239
  if endpoints["secondary"] in conn_settings:
232
240
  raise ValueError("Connection string specifies only secondary endpoint.")
233
241
  try:
234
- primary =(
242
+ primary = (
235
243
  f"{conn_settings['DEFAULTENDPOINTSPROTOCOL']}://"
236
244
  f"{conn_settings['ACCOUNTNAME']}.{service}.{conn_settings['ENDPOINTSUFFIX']}"
237
245
  )
238
- secondary = (
239
- f"{conn_settings['ACCOUNTNAME']}-secondary."
240
- f"{service}.{conn_settings['ENDPOINTSUFFIX']}"
241
- )
246
+ secondary = f"{conn_settings['ACCOUNTNAME']}-secondary." f"{service}.{conn_settings['ENDPOINTSUFFIX']}"
242
247
  except KeyError:
243
248
  pass
244
249
 
@@ -256,11 +261,13 @@ def parse_connection_str(
256
261
  secondary = secondary.replace(".blob.", ".dfs.")
257
262
  return primary, secondary, credential
258
263
 
264
+
259
265
  class AsyncTransportWrapper(AsyncHttpTransport):
260
266
  """Wrapper class that ensures that an inner client created
261
267
  by a `get_client` method does not close the outer transport for the parent
262
268
  when used in a context manager.
263
269
  """
270
+
264
271
  def __init__(self, async_transport):
265
272
  self._transport = async_transport
266
273
 
@@ -16,4 +16,4 @@ READ_TIMEOUT = 60
16
16
  DEFAULT_OAUTH_SCOPE = "/.default"
17
17
  STORAGE_OAUTH_SCOPE = "https://storage.azure.com/.default"
18
18
 
19
- SERVICE_HOST_BASE = 'core.windows.net'
19
+ SERVICE_HOST_BASE = "core.windows.net"