Repository: boto/boto3
File: boto3/crt.py (Python)

Code before:
    # CRT client can also be configured via `AUTO_RESOLVE_TRANSFER_CLIENT`
    # but it predates this validation. We only validate against CRT client
    # configured via `CRT_TRANSFER_CLIENT` to preserve compatibility.
    if config.preferred_transfer_client != CRT_TRANSFER_CLIENT:
        return
    invalid_crt_args = []
    for param in config.DEFAULTS.keys():
        val = config.get_deep_attr(param)
        if (
            param not in _ALLOWED_CRT_TRANSFER_CONFIG_OPTIONS
            and val is not config.UNSET_DEFAULT
        ):
            invalid_crt_args.append(param)
    if len(invalid_crt_args) > 0:
        raise InvalidCrtTransferConfigError(
            "The following transfer config options are invalid "
            "when `preferred_transfer_client` is set to `crt`: `"
            f"{'`, `'.join(invalid_crt_args)}`"
        )


def create_crt_transfer_manager(client, config):
    """Create a CRTTransferManager for optimized data transfer."""
    crt_s3_client = get_crt_s3_client(client, config)
    if is_crt_compatible_request(client, crt_s3_client):
        _validate_crt_transfer_config(config)
        return CRTTransferManager(
            crt_s3_client.crt_client,
            BOTOCORE_CRT_SERIALIZER,
            config=config,
        )
    return None


Review comment (refactor):
Ideally, validation would occur when the CRT request args are being built in s3transfer since technically the config values could be changed after creating the CRT transfer manager. The reason I'm not doing that right now is because s3transfer doesn't have knowledge of boto3's transfer config aliases, `max_concurrency` and `max_io_queue`.

I'm wondering if, for aliases, we use the alias values as the ground truth when performing validation (ie `max_request_concurrency` and `max_io_queue_size`.
- s3transfer has knowledge of these config properties.
- boto3's `TransferConfig` will always set values for alias keys and values when setting an alias key. But will only set the alias value when setting the alias value. So for example:
  - `config.max_concurrency = 10` sets both `max_concurrency` and `max_request_concurrency`
  - But `config.max_request_concurrency = 10` only sets `max_request_concurrency`.

If we always take the alias value as the param to validate on, then we can move this logic to s3transfer.

Code after:

def _validate_crt_transfer_config(config):
    if config is None:
        return
    # CRT client can also be configured via `AUTO_RESOLVE_TRANSFER_CLIENT`
    # but it predates this validation. We only validate against CRT client
    # configured via `CRT_TRANSFER_CLIENT` to preserve compatibility.
    if config.preferred_transfer_client != CRT_TRANSFER_CLIENT:
        return
    invalid_crt_args = []
    for param in config.DEFAULTS.keys():
        val = config.get_deep_attr(param)
        if (
            param not in _ALLOWED_CRT_TRANSFER_CONFIG_OPTIONS
            and val is not config.UNSET_DEFAULT
        ):
            invalid_crt_args.append(param)
    if len(invalid_crt_args) > 0:
        raise InvalidCrtTransferConfigError(
            "The following transfer config options are invalid "
            "when preferred_transfer_client is set to crt: "
            f"{', '.join(invalid_crt_args)}`"
        )


def create_crt_transfer_manager(client, config):
    """Create a CRTTransferManager for optimized data transfer."""
    crt_s3_client = get_crt_s3_client(client, config)
    if is_crt_compatible_request(client, crt_s3_client):
        crt_transfer_manager_kwargs = {
            'crt_s3_client': crt_s3_client.crt_client,
            'crt_request_serializer': BOTOCORE_CRT_SERIALIZER,
        }
        if TRANSFER_CONFIG_SUPPORTS_CRT:
            _validate_crt_transfer_config(config)
            crt_transfer_manager_kwargs['config'] = config
        if not TRANSFER_CONFIG_SUPPORTS_CRT and config:
            logger.warning(
                'Using TransferConfig with CRT client requires '
                's3transfer >= 0.16.0, configured values will be ignored.'
            )
        return CRTTransferManager(**crt_transfer_manager_kwargs)
    return None