Skip to content

Commit fb365d4

Browse files
committed
Expose CRT config options
1 parent 893c6a8 commit fb365d4

File tree

2 files changed

+73
-11
lines changed

2 files changed

+73
-11
lines changed

boto3/crt.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
create_s3_crt_client,
3232
)
3333

34+
from boto3.s3.constants import CRT_TRANSFER_CLIENT
35+
3436
# Singletons for CRT-backed transfers
3537
CRT_S3_CLIENT = None
3638
BOTOCORE_CRT_SERIALIZER = None
@@ -39,6 +41,15 @@
3941
PROCESS_LOCK_NAME = 'boto3'
4042

4143

44+
ALLOWED_CRT_TRANSFER_CONFIG_OPTIONS = {
45+
'multipart_threshold',
46+
'max_concurrency',
47+
'max_request_concurrency',
48+
'multipart_chunksize',
49+
'preferred_transfer_client',
50+
}
51+
52+
4253
def _create_crt_client(session, config, region_name, cred_provider):
4354
"""Create a CRT S3 Client for file transfer.
4455
@@ -157,11 +168,36 @@ def compare_identity(boto3_creds, crt_s3_creds):
157168
return is_matching_identity
158169

159170

171+
def _validate_crt_transfer_config(config):
172+
# CRT client can also be configured via `AUTO_RESOLVE_TRANSFER_CLIENT`
173+
# but it predates this validation. We only validate against CRT client
174+
# configured via `CRT_TRANSFER_CLIENT` to preserve compatibility.
175+
if config.preferred_transfer_client != CRT_TRANSFER_CLIENT:
176+
return
177+
invalid_crt_args = []
178+
for param in config.DEFAULTS.keys():
179+
val = config.get_deep_attr(param)
180+
if (
181+
param not in ALLOWED_CRT_TRANSFER_CONFIG_OPTIONS
182+
and val is not config.UNSET_DEFAULT
183+
):
184+
invalid_crt_args.append(param)
185+
if len(invalid_crt_args) > 0:
186+
raise ValueError(
187+
"The following transfer config options are invalid "
188+
"when `preferred_transfer_client` is set to `crt`: `"
189+
f"{'`, `'.join(invalid_crt_args)}`"
190+
)
191+
192+
160193
def create_crt_transfer_manager(client, config):
161194
"""Create a CRTTransferManager for optimized data transfer."""
162195
crt_s3_client = get_crt_s3_client(client, config)
163196
if is_crt_compatible_request(client, crt_s3_client):
197+
_validate_crt_transfer_config(config)
164198
return CRTTransferManager(
165-
crt_s3_client.crt_client, BOTOCORE_CRT_SERIALIZER
199+
crt_s3_client.crt_client,
200+
BOTOCORE_CRT_SERIALIZER,
201+
config=config,
166202
)
167203
return None

boto3/s3/transfer.py

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -249,18 +249,31 @@ class TransferConfig(S3TransferConfig):
249249
'max_concurrency': 'max_request_concurrency',
250250
'max_io_queue': 'max_io_queue_size',
251251
}
252+
DEFAULTS = {
253+
'multipart_threshold': 8 * MB,
254+
'max_concurrency': 10,
255+
'max_request_concurrency': 10,
256+
'multipart_chunksize': 8 * MB,
257+
'num_download_attempts': 5,
258+
'max_io_queue': 100,
259+
'max_io_queue_size': 100,
260+
'io_chunksize': 256 * KB,
261+
'use_threads': True,
262+
'max_bandwidth': None,
263+
'preferred_transfer_client': constants.AUTO_RESOLVE_TRANSFER_CLIENT,
264+
}
252265

253266
def __init__(
254267
self,
255-
multipart_threshold=8 * MB,
256-
max_concurrency=10,
257-
multipart_chunksize=8 * MB,
258-
num_download_attempts=5,
259-
max_io_queue=100,
260-
io_chunksize=256 * KB,
261-
use_threads=True,
262-
max_bandwidth=None,
263-
preferred_transfer_client=constants.AUTO_RESOLVE_TRANSFER_CLIENT,
268+
multipart_threshold=S3TransferConfig.UNSET_DEFAULT,
269+
max_concurrency=S3TransferConfig.UNSET_DEFAULT,
270+
multipart_chunksize=S3TransferConfig.UNSET_DEFAULT,
271+
num_download_attempts=S3TransferConfig.UNSET_DEFAULT,
272+
max_io_queue=S3TransferConfig.UNSET_DEFAULT,
273+
io_chunksize=S3TransferConfig.UNSET_DEFAULT,
274+
use_threads=S3TransferConfig.UNSET_DEFAULT,
275+
max_bandwidth=S3TransferConfig.UNSET_DEFAULT,
276+
preferred_transfer_client=S3TransferConfig.UNSET_DEFAULT,
264277
):
265278
"""Configuration object for managed S3 transfers
266279
@@ -325,7 +338,11 @@ def __init__(
325338
# S3TransferConfig so we add aliases so you can still access the
326339
# old version of the names.
327340
for alias in self.ALIAS:
328-
setattr(self, alias, getattr(self, self.ALIAS[alias]))
341+
setattr(
342+
self,
343+
alias,
344+
object.__getattribute__(self, self.ALIAS[alias]),
345+
)
329346
self.use_threads = use_threads
330347
self.preferred_transfer_client = preferred_transfer_client
331348

@@ -337,6 +354,15 @@ def __setattr__(self, name, value):
337354
# Always set the value of the actual name provided.
338355
super().__setattr__(name, value)
339356

357+
def __getattribute__(self, item):
358+
value = object.__getattribute__(self, item)
359+
defaults = object.__getattribute__(self, 'DEFAULTS')
360+
if item not in defaults:
361+
return value
362+
if value is self.UNSET_DEFAULT:
363+
return self.DEFAULTS[item]
364+
return value
365+
340366

341367
class S3Transfer:
342368
ALLOWED_DOWNLOAD_ARGS = TransferManager.ALLOWED_DOWNLOAD_ARGS

0 commit comments

Comments
 (0)