"""Abstract base class for storage adapters""" from abc import ABC, abstractmethod from io import BytesIO class StorageAdapter(ABC): """Abstract base class for storage adapters""" @abstractmethod def upload_file( self, file_data: BytesIO, bucket_name: str, object_name: str, content_type: str, ) -> dict: """ Upload a file to storage Args: file_data: File data as BytesIO bucket_name: Name of the bucket object_name: Name of the object in storage content_type: MIME type of the file Returns: dict: Upload result with metadata """ pass @abstractmethod def download_file(self, bucket_name: str, object_name: str) -> BytesIO: """ Download a file from storage Args: bucket_name: Name of the bucket object_name: Name of the object in storage Returns: BytesIO: File data """ pass @abstractmethod def delete_file(self, bucket_name: str, object_name: str) -> bool: """ Delete a file from storage Args: bucket_name: Name of the bucket object_name: Name of the object in storage Returns: bool: True if successful """ pass @abstractmethod def generate_presigned_url( self, bucket_name: str, object_name: str, expires_in: int = 3600 ) -> str: """ Generate a presigned URL for file access Args: bucket_name: Name of the bucket object_name: Name of the object in storage expires_in: URL expiration time in seconds Returns: str: Presigned URL """ pass @abstractmethod def file_exists(self, bucket_name: str, object_name: str) -> bool: """ Check if a file exists in storage Args: bucket_name: Name of the bucket object_name: Name of the object in storage Returns: bool: True if file exists """ pass @abstractmethod def get_file_info(self, bucket_name: str, object_name: str) -> dict: """ Get file metadata Args: bucket_name: Name of the bucket object_name: Name of the object in storage Returns: dict: File metadata """ pass @abstractmethod def ensure_bucket_exists(self, bucket_name: str) -> None: """ Ensure a bucket exists, create if it doesn't Args: bucket_name: Name of the bucket """ pass