""" Custom exception classes for the GradeM8 application. This module defines a hierarchy of domain-specific exceptions that provide better error handling and clearer failure modes throughout the application. """ class GradeM8Error(Exception): """Base exception for all GradeM8 application errors.""" pass # ============================================================================= # Document Processing Errors # ============================================================================= class DocumentError(GradeM8Error): """Base exception for document processing errors.""" pass class DocumentExtractionError(DocumentError): """Raised when text extraction from a document fails.""" pass class UnsupportedFileTypeError(DocumentError): """Raised when an unsupported file type is encountered.""" def __init__(self, filename: str, supported_types: list[str]) -> None: self.filename = filename self.supported_types = supported_types super().__init__( f"Unsupported file type for '{filename}'. " f"Supported types: {', '.join(supported_types)}" ) class CorruptedDocumentError(DocumentError): """Raised when a document is corrupted or cannot be read.""" pass class DocumentConversionError(DocumentError): """Raised when document conversion fails.""" pass # ============================================================================= # AI Grading Errors # ============================================================================= class GradingError(GradeM8Error): """Base exception for AI grading errors.""" pass class ResponseParseError(GradingError): """Raised when the AI response cannot be parsed as valid JSON.""" def __init__(self, message: str, raw_response: str | None = None) -> None: self.raw_response = raw_response super().__init__(message) class InvalidResponseError(GradingError): """Raised when the AI response is valid JSON but missing required fields.""" pass class APIKeyError(GradingError): """Raised when the API key is missing or invalid.""" pass class AIServiceError(GradingError): """Raised when the AI service returns an error.""" def __init__(self, message: str, status_code: int | None = None) -> None: self.status_code = status_code super().__init__(message) # ============================================================================= # Configuration Errors # ============================================================================= class ConfigurationError(GradeM8Error): """Raised when there's a configuration issue."""