"""Typed exception hierarchy for MCIAS client errors.""" class MciasError(Exception): """Base exception for all MCIAS API errors.""" def __init__(self, status_code: int, message: str) -> None: super().__init__(f"HTTP {status_code}: {message}") self.status_code = status_code self.message = message class MciasAuthError(MciasError): """401 Unauthorized — token missing, invalid, or expired.""" class MciasForbiddenError(MciasError): """403 Forbidden — insufficient role.""" class MciasNotFoundError(MciasError): """404 Not Found — resource does not exist.""" class MciasInputError(MciasError): """400 Bad Request — malformed request.""" class MciasConflictError(MciasError): """409 Conflict — e.g. duplicate username.""" class MciasServerError(MciasError): """5xx — unexpected server error.""" def raise_for_status(status_code: int, message: str) -> None: """Raise the appropriate MciasError subclass for the given status code.""" exc_map = { 400: MciasInputError, 401: MciasAuthError, 403: MciasForbiddenError, 404: MciasNotFoundError, 409: MciasConflictError, } cls = exc_map.get(status_code, MciasServerError) raise cls(status_code, message)