Spaces:
Runtime error
Runtime error
| """ | |
| Exceções customizadas para para.AI API v3.0 | |
| Define hierarquia de exceções para tratamento de erros | |
| """ | |
| from typing import Optional, Dict, Any | |
| class ParaAIException(Exception): | |
| """ | |
| Exceção base para todas as exceções customizadas do para.AI. | |
| Todas as outras exceções devem herdar desta classe. | |
| """ | |
| def __init__( | |
| self, | |
| message: str, | |
| details: Optional[Dict[str, Any]] = None, | |
| status_code: int = 500 | |
| ): | |
| """ | |
| Args: | |
| message: Mensagem de erro principal | |
| details: Dicionário com detalhes adicionais do erro | |
| status_code: Código HTTP sugerido para este erro | |
| """ | |
| self.message = message | |
| self.details = details or {} | |
| self.status_code = status_code | |
| super().__init__(self.message) | |
| def to_dict(self) -> Dict[str, Any]: | |
| """Converte exceção para dicionário (útil para JSON responses).""" | |
| return { | |
| "error": self.__class__.__name__, | |
| "message": self.message, | |
| "details": self.details, | |
| "status_code": self.status_code | |
| } | |
| def __str__(self) -> str: | |
| """String representation.""" | |
| if self.details: | |
| return f"{self.message} | Details: {self.details}" | |
| return self.message | |
| # ============================================================================ | |
| # EXCEÇÕES DE DATABASE | |
| # ============================================================================ | |
| class DatabaseException(ParaAIException): | |
| """Exceção genérica de banco de dados.""" | |
| def __init__(self, message: str, details: Optional[Dict[str, Any]] = None): | |
| super().__init__(message, details, status_code=500) | |
| class DatabaseConnectionError(DatabaseException): | |
| """Erro de conexão com banco de dados.""" | |
| def __init__(self, message: str = "Falha ao conectar com banco de dados", details: Optional[Dict[str, Any]] = None): | |
| super().__init__(message, details) | |
| class RecordNotFoundError(DatabaseException): | |
| """Registro não encontrado no banco.""" | |
| def __init__(self, message: str = "Registro não encontrado", details: Optional[Dict[str, Any]] = None): | |
| super().__init__(message, details) | |
| self.status_code = 404 | |
| class DuplicateRecordError(DatabaseException): | |
| """Tentativa de inserir registro duplicado.""" | |
| def __init__(self, message: str = "Registro duplicado", details: Optional[Dict[str, Any]] = None): | |
| super().__init__(message, details) | |
| self.status_code = 409 | |
| # ============================================================================ | |
| # EXCEÇÕES DE LLM | |
| # ============================================================================ | |
| class LLMException(ParaAIException): | |
| """Exceção genérica de LLM.""" | |
| def __init__(self, message: str, details: Optional[Dict[str, Any]] = None): | |
| super().__init__(message, details, status_code=500) | |
| class LLMProviderNotAvailable(LLMException): | |
| """Provedor LLM não disponível.""" | |
| def __init__(self, provider: str, details: Optional[Dict[str, Any]] = None): | |
| message = f"Provedor LLM '{provider}' não disponível ou não configurado" | |
| super().__init__(message, details) | |
| self.status_code = 503 | |
| class LLMAPIError(LLMException): | |
| """Erro na chamada da API do LLM.""" | |
| def __init__(self, message: str, details: Optional[Dict[str, Any]] = None): | |
| super().__init__(f"Erro na API do LLM: {message}", details) | |
| class LLMTimeoutError(LLMException): | |
| """Timeout na chamada do LLM.""" | |
| def __init__(self, timeout: int, details: Optional[Dict[str, Any]] = None): | |
| message = f"Timeout de {timeout}s excedido na chamada do LLM" | |
| super().__init__(message, details) | |
| self.status_code = 504 | |
| class LLMResponseParseError(LLMException): | |
| """Erro ao fazer parse da resposta do LLM.""" | |
| def __init__(self, message: str = "Falha ao processar resposta do LLM", details: Optional[Dict[str, Any]] = None): | |
| super().__init__(message, details) | |
| # ============================================================================ | |
| # EXCEÇÕES DE PROCESSAMENTO | |
| # ============================================================================ | |
| class ProcessingException(ParaAIException): | |
| """Exceção genérica de processamento.""" | |
| def __init__(self, message: str, details: Optional[Dict[str, Any]] = None): | |
| super().__init__(message, details, status_code=500) | |
| class ProcessorNotFoundError(ProcessingException): | |
| """Processador não encontrado.""" | |
| def __init__(self, processor_name: str, details: Optional[Dict[str, Any]] = None): | |
| message = f"Processador '{processor_name}' não encontrado" | |
| super().__init__(message, details) | |
| self.status_code = 404 | |
| class ProcessingTimeoutError(ProcessingException): | |
| """Timeout no processamento.""" | |
| def __init__(self, timeout: int, details: Optional[Dict[str, Any]] = None): | |
| message = f"Timeout de {timeout}s excedido no processamento" | |
| super().__init__(message, details) | |
| self.status_code = 504 | |
| class ValidationError(ProcessingException): | |
| """Erro de validação de dados.""" | |
| def __init__(self, message: str = "Dados inválidos", details: Optional[Dict[str, Any]] = None): | |
| super().__init__(message, details) | |
| self.status_code = 422 | |
| # ============================================================================ | |
| # EXCEÇÕES DE ARQUIVO | |
| # ============================================================================ | |
| class FileException(ParaAIException): | |
| """Exceção genérica de arquivo.""" | |
| def __init__(self, message: str, details: Optional[Dict[str, Any]] = None): | |
| super().__init__(message, details, status_code=500) | |
| class FileNotFoundError(FileException): | |
| """Arquivo não encontrado.""" | |
| def __init__(self, filepath: str, details: Optional[Dict[str, Any]] = None): | |
| message = f"Arquivo não encontrado: {filepath}" | |
| super().__init__(message, details) | |
| self.status_code = 404 | |
| class FileUploadError(FileException): | |
| """Erro no upload de arquivo.""" | |
| def __init__(self, message: str = "Erro ao fazer upload do arquivo", details: Optional[Dict[str, Any]] = None): | |
| super().__init__(message, details) | |
| self.status_code = 400 | |
| class FileFormatError(FileException): | |
| """Formato de arquivo inválido.""" | |
| def __init__(self, message: str = "Formato de arquivo inválido", details: Optional[Dict[str, Any]] = None): | |
| super().__init__(message, details) | |
| self.status_code = 415 | |
| class FileSizeExceededError(FileException): | |
| """Tamanho de arquivo excedido.""" | |
| def __init__(self, size: int, max_size: int, details: Optional[Dict[str, Any]] = None): | |
| message = f"Arquivo muito grande: {size} bytes (máximo: {max_size} bytes)" | |
| super().__init__(message, details) | |
| self.status_code = 413 | |
| # ============================================================================ | |
| # EXCEÇÕES DE CONFIGURAÇÃO | |
| # ============================================================================ | |
| class ConfigurationError(ParaAIException): | |
| """Erro de configuração.""" | |
| def __init__(self, message: str, details: Optional[Dict[str, Any]] = None): | |
| super().__init__(f"Erro de configuração: {message}", details) | |
| self.status_code = 500 | |
| class MissingConfigurationError(ConfigurationError): | |
| """Configuração obrigatória ausente.""" | |
| def __init__(self, config_name: str, details: Optional[Dict[str, Any]] = None): | |
| message = f"Configuração obrigatória ausente: {config_name}" | |
| super().__init__(message, details) | |
| # ============================================================================ | |
| # EXCEÇÕES DE AUTENTICAÇÃO/AUTORIZAÇÃO | |
| # ============================================================================ | |
| class AuthenticationError(ParaAIException): | |
| """Erro de autenticação.""" | |
| def __init__(self, message: str = "Falha na autenticação", details: Optional[Dict[str, Any]] = None): | |
| super().__init__(message, details) | |
| self.status_code = 401 | |
| class AuthorizationError(ParaAIException): | |
| """Erro de autorização.""" | |
| def __init__(self, message: str = "Acesso negado", details: Optional[Dict[str, Any]] = None): | |
| super().__init__(message, details) | |
| self.status_code = 403 | |
| class InvalidAPIKeyError(AuthenticationError): | |
| """API Key inválida.""" | |
| def __init__(self, details: Optional[Dict[str, Any]] = None): | |
| super().__init__("API Key inválida ou expirada", details) | |
| # ============================================================================ | |
| # FUNÇÃO AUXILIAR | |
| # ============================================================================ | |
| def handle_exception(exc: Exception) -> Dict[str, Any]: | |
| """ | |
| Converte qualquer exceção para dicionário padronizado. | |
| Args: | |
| exc: Exceção a ser convertida | |
| Returns: | |
| Dicionário com informações do erro | |
| """ | |
| if isinstance(exc, ParaAIException): | |
| return exc.to_dict() | |
| # Exceção genérica | |
| return { | |
| "error": exc.__class__.__name__, | |
| "message": str(exc), | |
| "details": {}, | |
| "status_code": 500 | |
| } | |