Files
orion/app/exceptions/cart.py
Samir Boulahtit b8a46e1746 fix: protect critical re-export imports from linter removal
Problem:
- Ruff removed 'from app.core.database import Base' from models/database/base.py
- Import appeared "unused" (F401) but was actually a critical re-export
- Caused ImportError: cannot import name 'Base' at runtime
- Re-export pattern: import in one file to export from package

Solution:
1. Added F401 ignore for models/database/base.py in pyproject.toml
2. Created scripts/verify_critical_imports.py verification script
3. Integrated verification into make check and CI pipeline
4. Updated documentation with explanation

New Verification Script:
- Checks all critical re-export imports exist
- Detects import variations (parentheses, 'as' clauses)
- Handles SQLAlchemy declarative_base alternatives
- Runs as part of make check automatically

Protected Files:
- models/database/base.py - Re-exports Base for all models
- models/__init__.py - Exports Base for Alembic
- models/database/__init__.py - Exports Base from package
- All __init__.py files (already protected)

Makefile Changes:
- make verify-imports - Run import verification
- make check - Now includes verify-imports
- make ci - Includes verify-imports in pipeline

Documentation Updated:
- Code quality guide explains re-export protection
- Pre-commit workflow includes verification
- Examples of why re-exports matter

This prevents future issues where linters remove seemingly
"unused" imports that are actually critical for application structure.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 20:10:22 +01:00

108 lines
3.3 KiB
Python

# app/exceptions/cart.py
"""
Shopping cart specific exceptions.
"""
from .base import BusinessLogicException, ResourceNotFoundException, ValidationException
class CartItemNotFoundException(ResourceNotFoundException):
"""Raised when a cart item is not found."""
def __init__(self, product_id: int, session_id: str):
super().__init__(
resource_type="CartItem",
identifier=str(product_id),
message=f"Product {product_id} not found in cart",
error_code="CART_ITEM_NOT_FOUND",
)
self.details.update({"product_id": product_id, "session_id": session_id})
class EmptyCartException(ValidationException):
"""Raised when trying to perform operations on an empty cart."""
def __init__(self, session_id: str):
super().__init__(message="Cart is empty", details={"session_id": session_id})
self.error_code = "CART_EMPTY"
class CartValidationException(ValidationException):
"""Raised when cart data validation fails."""
def __init__(
self,
message: str = "Cart validation failed",
field: str | None = None,
details: dict | None = None,
):
super().__init__(
message=message,
field=field,
details=details,
)
self.error_code = "CART_VALIDATION_FAILED"
class InsufficientInventoryForCartException(BusinessLogicException):
"""Raised when product doesn't have enough inventory for cart operation."""
def __init__(
self,
product_id: int,
product_name: str,
requested: int,
available: int,
):
message = f"Insufficient inventory for product '{product_name}'. Requested: {requested}, Available: {available}"
super().__init__(
message=message,
error_code="INSUFFICIENT_INVENTORY_FOR_CART",
details={
"product_id": product_id,
"product_name": product_name,
"requested_quantity": requested,
"available_quantity": available,
},
)
class InvalidCartQuantityException(ValidationException):
"""Raised when cart quantity is invalid."""
def __init__(
self, quantity: int, min_quantity: int = 1, max_quantity: int | None = None
):
if quantity < min_quantity:
message = f"Quantity must be at least {min_quantity}"
elif max_quantity and quantity > max_quantity:
message = f"Quantity cannot exceed {max_quantity}"
else:
message = f"Invalid quantity: {quantity}"
super().__init__(
message=message,
field="quantity",
details={
"quantity": quantity,
"min_quantity": min_quantity,
"max_quantity": max_quantity,
},
)
self.error_code = "INVALID_CART_QUANTITY"
class ProductNotAvailableForCartException(BusinessLogicException):
"""Raised when product is not available for adding to cart."""
def __init__(self, product_id: int, reason: str):
super().__init__(
message=f"Product {product_id} cannot be added to cart: {reason}",
error_code="PRODUCT_NOT_AVAILABLE_FOR_CART",
details={
"product_id": product_id,
"reason": reason,
},
)