"""Error envelope shared by every route: {"error": {"code", "message", "operation"}}.""" from __future__ import annotations from fastapi.responses import JSONResponse STATUS_BY_CODE = { "bad_request": 400, "invalid_path": 400, "unauthorized": 401, "too_large": 413, "unsupported": 501, "busy": 503, "internal": 500, } class MediaError(Exception): def __init__(self, code: str, message: str, operation: str | None = None) -> None: super().__init__(message) self.code = code self.message = message self.operation = operation @property def status(self) -> int: return STATUS_BY_CODE[self.code] class Unsupported(MediaError): def __init__(self, reason: str, operation: str | None = None) -> None: super().__init__("unsupported", reason, operation) class InvalidPath(MediaError): def __init__(self, message: str = "path is outside MEDIA_ROOT") -> None: super().__init__("invalid_path", message) class BadRequest(MediaError): def __init__(self, message: str) -> None: super().__init__("bad_request", message) class Busy(MediaError): def __init__(self) -> None: super().__init__("busy", "inference queue is full") class Cancelled(Exception): """The client went away or the request ran past MEDIA_MAX_SECONDS.""" def __init__(self, reason: str = "client disconnected") -> None: super().__init__(reason) self.reason = reason def error_response(code: str, message: str, operation: str | None, status: int | None = None) -> JSONResponse: return JSONResponse( status_code=status or STATUS_BY_CODE[code], content={"error": {"code": code, "message": message, "operation": operation}}, )