Files
orion/app/exceptions/base.py
Samir Boulahtit e9253fbd84 refactor: rename Wizamart to Orion across entire codebase
Replace all ~1,086 occurrences of Wizamart/wizamart/WIZAMART/WizaMart
with Orion/orion/ORION across 184 files. This includes database
identifiers, email addresses, domain references, R2 bucket names,
DNS prefixes, encryption salt, Celery app name, config defaults,
Docker configs, CI configs, documentation, seed data, and templates.

Renames homepage-wizamart.html template to homepage-orion.html.
Fixes duplicate file_pattern key in api.yaml architecture rule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 16:46:56 +01:00

213 lines
5.6 KiB
Python

# app/exceptions/base.py
"""
Base exception classes for the application.
This module provides classes and functions for:
- Base exception class with consistent error formatting
- Common exception types for different error categories
- Standardized error response structure
"""
from typing import Any
class OrionException(Exception):
"""Base exception class for all custom exceptions."""
def __init__(
self,
message: str,
error_code: str,
status_code: int = 400,
details: dict[str, Any] | None = None,
):
self.message = message
self.error_code = error_code
self.status_code = status_code
self.details = details or {}
super().__init__(self.message)
def to_dict(self) -> dict[str, Any]:
"""Convert exception to dictionary for JSON response."""
result = {
"error_code": self.error_code,
"message": self.message,
"status_code": self.status_code,
}
if self.details:
result["details"] = self.details
return result
class ValidationException(OrionException):
"""Raised when request validation fails."""
def __init__(
self,
message: str,
field: str | None = None,
details: dict[str, Any] | None = None,
):
validation_details = details or {}
if field:
validation_details["field"] = field
super().__init__(
message=message,
error_code="VALIDATION_ERROR",
status_code=422,
details=validation_details,
)
class AuthenticationException(OrionException):
"""Raised when authentication fails."""
def __init__(
self,
message: str = "Authentication failed",
error_code: str = "AUTHENTICATION_FAILED",
details: dict[str, Any] | None = None,
):
super().__init__(
message=message,
error_code=error_code,
status_code=401,
details=details,
)
class AuthorizationException(OrionException):
"""Raised when user lacks permission for an operation."""
def __init__(
self,
message: str = "Access denied",
error_code: str = "AUTHORIZATION_FAILED",
details: dict[str, Any] | None = None,
):
super().__init__(
message=message,
error_code=error_code,
status_code=403,
details=details,
)
class ResourceNotFoundException(OrionException):
"""Raised when a requested resource is not found."""
def __init__(
self,
resource_type: str,
identifier: str,
message: str | None = None,
error_code: str | None = None,
):
if not message:
message = f"{resource_type} with identifier '{identifier}' not found"
if not error_code:
error_code = f"{resource_type.upper()}_NOT_FOUND"
super().__init__(
message=message,
error_code=error_code,
status_code=404,
details={
"resource_type": resource_type,
"identifier": identifier,
},
)
class ConflictException(OrionException):
"""Raised when a resource conflict occurs."""
def __init__(
self,
message: str,
error_code: str = "RESOURCE_CONFLICT",
details: dict[str, Any] | None = None,
):
super().__init__(
message=message,
error_code=error_code,
status_code=409,
details=details,
)
class BusinessLogicException(OrionException):
"""Raised when business logic rules are violated."""
def __init__(
self,
message: str,
error_code: str,
details: dict[str, Any] | None = None,
):
super().__init__(
message=message,
error_code=error_code,
status_code=400,
details=details,
)
class ExternalServiceException(OrionException):
"""Raised when an external service fails."""
def __init__(
self,
message: str,
service_name: str,
error_code: str = "EXTERNAL_SERVICE_ERROR",
details: dict[str, Any] | None = None,
):
service_details = details or {}
service_details["service_name"] = service_name
super().__init__(
message=message,
error_code=error_code,
status_code=502,
details=service_details,
)
class RateLimitException(OrionException):
"""Raised when rate limit is exceeded."""
def __init__(
self,
message: str = "Rate limit exceeded",
retry_after: int | None = None,
details: dict[str, Any] | None = None,
):
rate_limit_details = details or {}
if retry_after:
rate_limit_details["retry_after"] = retry_after
super().__init__(
message=message,
error_code="RATE_LIMIT_EXCEEDED",
status_code=429,
details=rate_limit_details,
)
class ServiceUnavailableException(OrionException):
"""Raised when service is unavailable."""
def __init__(self, message: str = "Service temporarily unavailable"):
super().__init__(
message=message,
error_code="SERVICE_UNAVAILABLE",
status_code=503,
)
# Note: Domain-specific exceptions like StoreNotFoundException, UserNotFoundException, etc.
# are defined in their respective domain modules (store.py, admin.py, etc.)
# to keep domain-specific logic separate from base exceptions.