"""S3 test utils.""" import logging import time from tests.integration import config __all__ = ['S3ClientWrapper'] logger = logging.getLogger() class S3ClientWrapper: """S3 client wrapper.""" def __init__(self, client, bucket_name: str = config.S3_BUCKET_NAME): """Initialize the S3 client wrapper.""" self.client = client self.bucket_name = bucket_name def _list_files(self, prefix: str = config.EMAILS_S3_PREFIX) -> list[str]: response = self.client.list_objects_v2(Bucket=self.bucket_name, Prefix=prefix) if 'Contents' not in response or len(response['Contents']) <= 0: return [] keys = [] for obj in response['Contents']: keys.append(obj['Key']) logger.info(f"File(s) found with prefix '{prefix}': {','.join(keys)})") return keys def wait_for_files( self, num_files: int, prefix: str = config.EMAILS_S3_PREFIX, timeout: int = config.FILE_POLLING_TIMEOUT, interval: int = config.FILE_POLLING_INTERVAL ) -> list[str]: """Wait until all files will arrive within timeout.""" start_time = time.time() files = [] num_files = num_files or 1 timeout = timeout * num_files while True: _files = self._list_files(prefix=prefix) if _files: logger.info( f'Found {len(_files)} file(s) in {time.time() - start_time:.2f} seconds.' f' {num_files} files were expected.' ) files = _files if len(files) >= num_files: break if time.time() - start_time > timeout: logger.info('Timeout reached.') break logger.info(f'Waiting for files with prefix "{prefix}" to appear...') time.sleep(interval) return files def get_file(self, key: str) -> str: """Get file content.""" response = self.client.get_object(Bucket=self.bucket_name, Key=key) return response['Body'].read().decode('utf-8') def delete_files(self, prefix: str = config.EMAILS_S3_PREFIX): """Delete files.""" files = self._list_files(prefix=prefix) for file in files: self.client.delete_object(Bucket=self.bucket_name, Key=file) logger.info(f'Deleted file: {file}')