"""Provides S3 utility functions to facilitate tests.""" from typing import Any import boto3 from mypy_boto3_s3.client import S3Client from mypy_boto3_s3.type_defs import PutObjectOutputTypeDef from tests.testutils.api_client.assets_api_client import AssetsAPIClient class S3Helper: """Provides S3 utility functions to facilitate tests.""" @staticmethod def _s3_client(creds: dict[str, Any]) -> S3Client: """Initialize s3 client via boto3.""" return boto3.client( "s3", aws_access_key_id=creds["aws_access_key_id"], aws_secret_access_key=creds["aws_secret_access_key"], aws_session_token=creds["token"], ) @staticmethod def _upload_to_s3( upload_token: dict[str, Any], file_path: str, content_type: str, file_ext: str ) -> PutObjectOutputTypeDef: """Upload to s3.""" client = S3Helper._s3_client(upload_token["credentials"]) return client.put_object( Bucket=upload_token["bucket"], Key="{}.{}".format(upload_token["filename"], file_ext), Body=open(file_path, "rb").read(), Metadata={"original_filename": upload_token["filename"]}, ContentType=content_type, ) @staticmethod def upload_to_s3_check_response( asset_file: str, file_ext: str, content_type: str, upload_token: dict[str, Any] ) -> None: """Upload a file to s3 and check response.""" s3_response = S3Helper._upload_to_s3( upload_token, asset_file, content_type, file_ext ) s3_response_metadata = s3_response["ResponseMetadata"] assert s3_response_metadata["HTTPStatusCode"] == 200, ( "Result of S3 Upload was {}, expected 200.".format( s3_response_metadata["HTTPStatusCode"] ) ) # etag indicates asset was processed successfully assert s3_response_metadata["HTTPHeaders"]["etag"].replace('"', ""), ( "etag was empty" ) @staticmethod def get_upload_token( assets_api_client: AssetsAPIClient, headers: dict[str, Any], asset_type: str ) -> dict[str, Any]: """Get upload token from s3 and check response.""" upload_token_response = assets_api_client.upload_token(headers, asset_type) assert upload_token_response.status_code == 200, ( "Result of GET was {}, expected 200.".format( upload_token_response.status_code ) ) return upload_token_response.json() # type: ignore[no-any-return]