2222from botocore .config import Config
2323from botocore .exceptions import (
2424 ClientError ,
25+ ConnectionError ,
2526 InvalidS3UsEast1RegionalEndpointConfigError ,
2627 ParamValidationError ,
2728 UnsupportedS3AccesspointConfigurationError ,
@@ -2357,6 +2358,32 @@ def test_checksum_content_encoding(content_encoding, expected_header):
23572358 assert request_headers ["Content-Encoding" ] == expected_header
23582359
23592360
2361+ @mock .patch ('botocore.endpoint.URLLib3Session.send' )
2362+ @mock .patch ('botocore.client.apply_request_checksum' )
2363+ def test_retries_reuse_request_checksum (
2364+ mock_apply_request_checksum , mock_urllib3_session_send
2365+ ):
2366+ # Force retry behavior.
2367+ mock_urllib3_session_send .side_effect = ConnectionError (error = 'Fake error' )
2368+ op_kwargs = {
2369+ "Bucket" : "mybucket" ,
2370+ "Key" : "mykey" ,
2371+ "Body" : b"foo" ,
2372+ "ChecksumAlgorithm" : "CRC32" ,
2373+ }
2374+ s3 = _create_s3_client (
2375+ retries = {
2376+ 'max_attempts' : 1 ,
2377+ }
2378+ )
2379+ with pytest .raises (ConnectionError ):
2380+ s3 .put_object (** op_kwargs )
2381+ # Ensure sending request was retried.
2382+ assert mock_urllib3_session_send .call_count == 2
2383+ # But request checksum was only calculated once.
2384+ assert mock_apply_request_checksum .call_count == 1
2385+
2386+
23602387def _s3_addressing_test_cases ():
23612388 # The default behavior for sigv2. DNS compatible buckets
23622389 yield dict (
@@ -3458,6 +3485,7 @@ def _create_s3_client(
34583485 s3_config = None ,
34593486 signature_version = "s3v4" ,
34603487 use_fips_endpoint = None ,
3488+ retries = None ,
34613489):
34623490 environ = {}
34633491 with mock .patch ("os.environ" , environ ):
@@ -3471,6 +3499,7 @@ def _create_s3_client(
34713499 signature_version = signature_version ,
34723500 s3 = s3_config ,
34733501 use_fips_endpoint = use_fips_endpoint ,
3502+ retries = retries ,
34743503 )
34753504 s3 = session .create_client (
34763505 "s3" ,
0 commit comments