# Copyright 2026 The Gitea Authors. All rights reserved. # SPDX-License-Identifier: MIT """Exception classes for the Gitea SDK.""" from typing import Optional, Dict, Any class GiteaError(Exception): """Base exception for all Gitea SDK errors.""" def __init__(self, message: str): self.message = message super().__init__(message) class APIError(GiteaError): """Raised when the API returns an error response.""" def __init__( self, message: str, code: Optional[str] = None, status: int = 0, details: Optional[Dict[str, Any]] = None, ): super().__init__(message) self.code = code self.status = status self.details = details or {} def __str__(self) -> str: if self.code: return f"[{self.code}] {self.message}" return self.message class AuthenticationError(APIError): """Raised when authentication fails.""" def __init__(self, message: str = "Authentication failed", code: str = "AUTH_FAILED"): super().__init__(message, code=code, status=401) class NotFoundError(APIError): """Raised when a resource is not found.""" def __init__(self, resource: str, identifier: str = ""): message = f"{resource} not found" if identifier: message = f"{resource} '{identifier}' not found" super().__init__(message, code="NOT_FOUND", status=404) self.resource = resource self.identifier = identifier class ValidationError(APIError): """Raised when request validation fails.""" def __init__(self, message: str, field: Optional[str] = None): super().__init__(message, code="VALIDATION_FAILED", status=400) self.field = field class UploadError(GiteaError): """Raised when an upload fails.""" def __init__(self, message: str, session_id: Optional[str] = None, chunk: Optional[int] = None): super().__init__(message) self.session_id = session_id self.chunk = chunk def __str__(self) -> str: parts = [self.message] if self.session_id: parts.append(f"session={self.session_id}") if self.chunk is not None: parts.append(f"chunk={self.chunk}") return " ".join(parts) class RateLimitError(APIError): """Raised when rate limit is exceeded.""" def __init__(self, retry_after: Optional[int] = None): message = "Rate limit exceeded" if retry_after: message += f". Retry after {retry_after} seconds" super().__init__(message, code="RATE_LIMIT_EXCEEDED", status=429) self.retry_after = retry_after