Skip to content

Commit 660572e

Browse files
committed
[Storage][102] CRC64 content validation - part 7 - record tests (#46461)
1 parent 0afa08f commit 660572e

37 files changed

Lines changed: 676 additions & 1566 deletions

eng/tools/azure-sdk-tools/devtools_testutils/storage/decorators.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
class GenericTestProxyParametrize1:
88
def __call__(self, fn):
99
def _wrapper(test_class, a, **kwargs):
10-
fn(test_class, a, **kwargs)
10+
return fn(test_class, a, **kwargs)
1111
return _wrapper
1212

1313

1414
class GenericTestProxyParametrize2:
1515
def __call__(self, fn):
1616
def _wrapper(test_class, a, b, **kwargs):
17-
fn(test_class, a, b, **kwargs)
17+
return fn(test_class, a, b, **kwargs)
1818
return _wrapper

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_339150483d"
5+
"Tag": "python/storage/azure-storage-blob_e0a670a6a4"
66
}

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

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -265,33 +265,6 @@ def _download_blob_options(
265265
client: "AzureBlobStorage",
266266
**kwargs
267267
) -> Dict[str, Any]:
268-
"""Creates a dictionary containing the options for a download blob operation.
269-
270-
:param str blob_name:
271-
The name of the blob.
272-
:param str container_name:
273-
The name of the container.
274-
:param Optional[str] version_id:
275-
The version id parameter is a value that, when present, specifies the version of the blob to download.
276-
:param Optional[int] offset:
277-
Start of byte range to use for downloading a section of the blob. Must be set if length is provided.
278-
:param Optional[int] length:
279-
Number of bytes to read from the stream. This is optional, but should be supplied for optimal performance.
280-
:param Optional[str] encoding:
281-
Encoding to decode the downloaded bytes. Default is None, i.e. no decoding.
282-
:param Dict[str, Any] encryption_options:
283-
The options for encryption, if enabled.
284-
:param validate_content:
285-
Enables checksum validation for the transfer. Already parsed via parse_validation_option.
286-
:param StorageConfiguration config:
287-
The Storage configuration options.
288-
:param str sdk_moniker:
289-
The string representing the SDK package version.
290-
:param AzureBlobStorage client:
291-
The generated Blob Storage client.
292-
:return: A dictionary containing the download blob options.
293-
:rtype: Dict[str, Any]
294-
"""
295268
if length is not None:
296269
if offset is None:
297270
raise ValueError("Offset must be provided if length is provided.")

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,11 @@ def __init__(
386386
# The service only provides transactional MD5s for chunks under 4MB.
387387
# If validate_content is using MD5, get only self.MAX_CHUNK_GET_SIZE for the first
388388
# chunk so a transactional MD5 can be retrieved.
389-
first_get_size = self._config.max_single_get_size if not is_md5_validation(self._validate_content) else self._config.max_chunk_get_size
389+
first_get_size = (
390+
self._config.max_single_get_size
391+
if not is_md5_validation(self._validate_content)
392+
else self._config.max_chunk_get_size
393+
)
390394

391395
initial_request_start = self._download_start
392396
if self._end_range is not None and self._end_range - initial_request_start < first_get_size:

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@
4040
StorageHosts,
4141
StorageRequestHook,
4242
)
43-
from .policies_async import AsyncStorageBearerTokenCredentialPolicy, AsyncContentValidationPolicy, AsyncStorageResponseHook
43+
from .policies_async import (
44+
AsyncStorageBearerTokenCredentialPolicy,
45+
AsyncContentValidationPolicy,
46+
AsyncStorageResponseHook,
47+
)
4448
from .response_handlers import PartialBatchErrorException, process_storage_error
4549
from .._shared_access_signature import _is_credential_sastoken
4650

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

Lines changed: 42 additions & 126 deletions
Large diffs are not rendered by default.

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

Lines changed: 25 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,9 @@
4545
async def retry_hook(settings, **kwargs):
4646
if settings["hook"]:
4747
if asyncio.iscoroutine(settings["hook"]):
48-
await settings["hook"](
49-
retry_count=settings["count"] - 1,
50-
location_mode=settings["mode"],
51-
**kwargs
52-
)
48+
await settings["hook"](retry_count=settings["count"] - 1, location_mode=settings["mode"], **kwargs)
5349
else:
54-
settings["hook"](
55-
retry_count=settings["count"] - 1,
56-
location_mode=settings["mode"],
57-
**kwargs
58-
)
50+
settings["hook"](retry_count=settings["count"] - 1, location_mode=settings["mode"], **kwargs)
5951

6052

6153
async def is_checksum_retry(response):
@@ -70,9 +62,9 @@ async def is_checksum_retry(response):
7062
await response.http_response.load_body() # Load the body in memory and close the socket
7163
except (StreamClosedError, StreamConsumedError):
7264
pass
73-
computed_md5 = response.http_request.headers.get(
74-
"content-md5", None
75-
) or encode_base64(calculate_content_md5(response.http_response.body()))
65+
computed_md5 = response.http_request.headers.get("content-md5", None) or encode_base64(
66+
calculate_content_md5(response.http_response.body())
67+
)
7668
if response.http_response.headers["content-md5"] != computed_md5:
7769
return True
7870
return False
@@ -118,50 +110,36 @@ async def send(self, request: "PipelineRequest") -> "PipelineResponse":
118110
data_stream_total = request.context.options.pop("data_stream_total", None)
119111
download_stream_current = request.context.get("download_stream_current")
120112
if download_stream_current is None:
121-
download_stream_current = request.context.options.pop(
122-
"download_stream_current", None
123-
)
113+
download_stream_current = request.context.options.pop("download_stream_current", None)
124114
upload_stream_current = request.context.get("upload_stream_current")
125115
if upload_stream_current is None:
126-
upload_stream_current = request.context.options.pop(
127-
"upload_stream_current", None
128-
)
116+
upload_stream_current = request.context.options.pop("upload_stream_current", None)
129117

130-
response_callback = request.context.get(
131-
"response_callback"
132-
) or request.context.options.pop("raw_response_hook", self._response_callback)
118+
response_callback = request.context.get("response_callback") or request.context.options.pop(
119+
"raw_response_hook", self._response_callback
120+
)
133121

134122
response = await self.next.send(request)
135-
will_retry = is_retry(
136-
response, request.context.options.get("mode")
137-
) or await is_checksum_retry(response)
123+
will_retry = is_retry(response, request.context.options.get("mode")) or await is_checksum_retry(response)
138124

139125
# Auth error could come from Bearer challenge, in which case this request will be made again
140126
is_auth_error = response.http_response.status_code == 401
141127
should_update_counts = not (will_retry or is_auth_error)
142128

143129
if should_update_counts and download_stream_current is not None:
144-
download_stream_current += int(
145-
response.http_response.headers.get("Content-Length", 0)
146-
)
130+
download_stream_current += int(response.http_response.headers.get("Content-Length", 0))
147131
if data_stream_total is None:
148132
content_range = response.http_response.headers.get("Content-Range")
149133
if content_range:
150-
data_stream_total = int(
151-
content_range.split(" ", 1)[1].split("/", 1)[1]
152-
)
134+
data_stream_total = int(content_range.split(" ", 1)[1].split("/", 1)[1])
153135
else:
154136
data_stream_total = download_stream_current
155137
elif should_update_counts and upload_stream_current is not None:
156-
upload_stream_current += int(
157-
response.http_request.headers.get("Content-Length", 0)
158-
)
138+
upload_stream_current += int(response.http_request.headers.get("Content-Length", 0))
159139
for pipeline_obj in [request, response]:
160140
if hasattr(pipeline_obj, "context"):
161141
pipeline_obj.context["data_stream_total"] = data_stream_total
162-
pipeline_obj.context["download_stream_current"] = (
163-
download_stream_current
164-
)
142+
pipeline_obj.context["download_stream_current"] = download_stream_current
165143
pipeline_obj.context["upload_stream_current"] = upload_stream_current
166144
if response_callback:
167145
if asyncio.iscoroutine(response_callback):
@@ -190,9 +168,7 @@ async def send(self, request):
190168
while retries_remaining:
191169
try:
192170
response = await self.next.send(request)
193-
if is_retry(
194-
response, retry_settings["mode"]
195-
) or await is_checksum_retry(response):
171+
if is_retry(response, retry_settings["mode"]) or await is_checksum_retry(response):
196172
retries_remaining = self.increment(
197173
retry_settings,
198174
request=request.http_request,
@@ -211,9 +187,7 @@ async def send(self, request):
211187
except AzureError as err:
212188
if isinstance(err, AzureSigningError):
213189
raise
214-
retries_remaining = self.increment(
215-
retry_settings, request=request.http_request, error=err
216-
)
190+
retries_remaining = self.increment(retry_settings, request=request.http_request, error=err)
217191
if retries_remaining:
218192
await retry_hook(
219193
retry_settings,
@@ -275,9 +249,7 @@ def __init__(
275249
self.initial_backoff = initial_backoff
276250
self.increment_base = increment_base
277251
self.random_jitter_range = random_jitter_range
278-
super(ExponentialRetry, self).__init__(
279-
retry_total=retry_total, retry_to_secondary=retry_to_secondary, **kwargs
280-
)
252+
super(ExponentialRetry, self).__init__(retry_total=retry_total, retry_to_secondary=retry_to_secondary, **kwargs)
281253

282254
def get_backoff_time(self, settings: Dict[str, Any]) -> float:
283255
"""
@@ -290,14 +262,8 @@ def get_backoff_time(self, settings: Dict[str, Any]) -> float:
290262
:rtype: int or None
291263
"""
292264
random_generator = random.Random()
293-
backoff = self.initial_backoff + (
294-
0 if settings["count"] == 0 else pow(self.increment_base, settings["count"])
295-
)
296-
random_range_start = (
297-
backoff - self.random_jitter_range
298-
if backoff > self.random_jitter_range
299-
else 0
300-
)
265+
backoff = self.initial_backoff + (0 if settings["count"] == 0 else pow(self.increment_base, settings["count"]))
266+
random_range_start = backoff - self.random_jitter_range if backoff > self.random_jitter_range else 0
301267
random_range_end = backoff + self.random_jitter_range
302268
return random_generator.uniform(random_range_start, random_range_end)
303269

@@ -335,9 +301,7 @@ def __init__(
335301
"""
336302
self.backoff = backoff
337303
self.random_jitter_range = random_jitter_range
338-
super(LinearRetry, self).__init__(
339-
retry_total=retry_total, retry_to_secondary=retry_to_secondary, **kwargs
340-
)
304+
super(LinearRetry, self).__init__(retry_total=retry_total, retry_to_secondary=retry_to_secondary, **kwargs)
341305

342306
def get_backoff_time(self, settings: Dict[str, Any]) -> float:
343307
"""
@@ -352,28 +316,18 @@ def get_backoff_time(self, settings: Dict[str, Any]) -> float:
352316
random_generator = random.Random()
353317
# the backoff interval normally does not change, however there is the possibility
354318
# that it was modified by accessing the property directly after initializing the object
355-
random_range_start = (
356-
self.backoff - self.random_jitter_range
357-
if self.backoff > self.random_jitter_range
358-
else 0
359-
)
319+
random_range_start = self.backoff - self.random_jitter_range if self.backoff > self.random_jitter_range else 0
360320
random_range_end = self.backoff + self.random_jitter_range
361321
return random_generator.uniform(random_range_start, random_range_end)
362322

363323

364324
class AsyncStorageBearerTokenCredentialPolicy(AsyncBearerTokenCredentialPolicy):
365325
"""Custom Bearer token credential policy for following Storage Bearer challenges"""
366326

367-
def __init__(
368-
self, credential: "AsyncTokenCredential", audience: str, **kwargs: Any
369-
) -> None:
370-
super(AsyncStorageBearerTokenCredentialPolicy, self).__init__(
371-
credential, audience, **kwargs
372-
)
327+
def __init__(self, credential: "AsyncTokenCredential", audience: str, **kwargs: Any) -> None:
328+
super(AsyncStorageBearerTokenCredentialPolicy, self).__init__(credential, audience, **kwargs)
373329

374-
async def on_challenge(
375-
self, request: "PipelineRequest", response: "PipelineResponse"
376-
) -> bool:
330+
async def on_challenge(self, request: "PipelineRequest", response: "PipelineResponse") -> bool:
377331
try:
378332
auth_header = response.http_response.headers.get("WWW-Authenticate")
379333
challenge = StorageHttpChallenge(auth_header)

0 commit comments

Comments
 (0)