"""SQLAlchemy base model and common mixins. This module provides the declarative base class and common column mixins used by all database models. Example: from app.db.base import Base class User(Base): __tablename__ = "users" email = Column(String, unique=True, nullable=False) display_name = Column(String, nullable=False) """ from datetime import datetime from typing import Any from uuid import uuid4 from sqlalchemy import DateTime, func from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import DeclarativeBase, Mapped, declared_attr, mapped_column class Base(DeclarativeBase): """Base class for all SQLAlchemy models. Provides common columns and functionality: - id: UUID primary key (auto-generated) - created_at: Timestamp when record was created - updated_at: Timestamp when record was last updated All models should inherit from this class. Example: class User(Base): __tablename__ = "users" email: Mapped[str] = mapped_column(unique=True) """ # Type annotation for type checkers __tablename__: str # Common columns for all models id: Mapped[str] = mapped_column( UUID(as_uuid=False), primary_key=True, default=lambda: str(uuid4()), doc="Unique identifier (UUID)", ) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), nullable=False, doc="Timestamp when record was created", ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False, doc="Timestamp when record was last updated", ) @declared_attr.directive @classmethod def __tablename__(cls) -> str: """Generate table name from class name. Converts CamelCase to snake_case and pluralizes. Example: UserProfile -> user_profiles Can be overridden by setting __tablename__ directly. """ # Convert CamelCase to snake_case name = cls.__name__ result = [name[0].lower()] for char in name[1:]: if char.isupper(): result.append("_") result.append(char.lower()) else: result.append(char) # Simple pluralization (add 's') table_name = "".join(result) if not table_name.endswith("s"): table_name += "s" return table_name def to_dict(self) -> dict[str, Any]: """Convert model instance to dictionary. Returns: Dictionary with all column values. """ return {column.name: getattr(self, column.name) for column in self.__table__.columns} def __repr__(self) -> str: """Generate string representation of model instance.""" class_name = self.__class__.__name__ return f"<{class_name}(id={self.id!r})>"