from __future__ import annotations from typing import Mapping class ApplicationException(Exception): def __init__( self, status_code: int, message: str, headers: Mapping[str, str] | None = None, ): super().__init__(message) self.status_code = status_code self.message = message self.headers = headers def __str__(self) -> str: return f'{self.status_code}: {self.message}' class BadRequestException(ApplicationException): def __init__(self, message: str, headers: Mapping[str, str] | None = None): super().__init__(400, message, headers) class UnauthorizedException(ApplicationException): def __init__(self, message: str = 'Unauthorized', headers: Mapping[str, str] | None = None): super().__init__(401, message, headers) class ForbiddenException(ApplicationException): def __init__(self, message: str = 'Forbidden', headers: Mapping[str, str] | None = None): super().__init__(403, message, headers) class NotFoundException(ApplicationException): def __init__(self, message: str = 'Not found', headers: Mapping[str, str] | None = None): super().__init__(404, message, headers) class ConflictException(ApplicationException): def __init__(self, message: str, headers: Mapping[str, str] | None = None): super().__init__(409, message, headers) class TooManyRequestsException(ApplicationException): def __init__(self, message: str, headers: Mapping[str, str] | None = None): super().__init__(429, message, headers) class ServiceUnavailableException(ApplicationException): def __init__(self, message: str, headers: Mapping[str, str] | None = None): super().__init__(503, message, headers) class InternalException(ApplicationException): def __init__(self, message: str = 'Internal Server Error', headers: Mapping[str, str] | None = None): super().__init__(500, message, headers)