from __future__ import annotations from datetime import datetime, timezone from typing import Any from sqlalchemy import MetaData from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column from sqlalchemy.types import DateTime NAMING_CONVENTION = { "ix": "ix_%(column_0_label)s", "uq": "uq_%(table_name)s_%(column_0_name)s", "ck": "ck_%(table_name)s_%(constraint_name)s", "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", "pk": "pk_%(table_name)s", } def utcnow() -> datetime: return datetime.now(timezone.utc) class Base(DeclarativeBase): metadata = MetaData(naming_convention=NAMING_CONVENTION) type_annotation_map = { dict[str, Any]: __import__("sqlalchemy").JSON, list[dict[str, Any]]: __import__("sqlalchemy").JSON, list[str]: __import__("sqlalchemy").JSON, } class TimestampMixin: created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utcnow, nullable=False) updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=utcnow, onupdate=utcnow, nullable=False)