- shared/ = portable Android-origin sources vendored from deferred/desktop-server (app/build.gradle.kts srcDir repointed; PlaybackController.kt excluded as Android-only) - backend/ = bundled-lite engine (SQLite + inline queue); .venv symlinked from the old checkout, PYTHONPATH pins THIS backend's code over any editable install - repoRoot() resolves this project dir (env SHONAR_REPO still wins); desktop-dev.sh watches shared/ + backend/ - Verified: :app:compileKotlin + :app:test green (23 tests); engine boots on :8010, self-migrates, /healthz ok
50 lines
1.5 KiB
Python
50 lines
1.5 KiB
Python
"""Public SQLAlchemy model base."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import uuid
|
|
from datetime import UTC, datetime
|
|
|
|
from sqlalchemy import DateTime, TypeDecorator, Uuid
|
|
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
|
|
|
|
|
class UTCDT(TypeDecorator):
|
|
"""Timezone-aware datetime that survives SQLite round-trips.
|
|
|
|
Postgres returns aware values (impl is a no-op there); SQLite has no
|
|
tz info and hands back naive datetimes, which crash comparisons with
|
|
``utcnow()``. Attach UTC on read whenever the driver lost it.
|
|
"""
|
|
|
|
impl = DateTime(timezone=True)
|
|
cache_ok = True
|
|
|
|
def process_result_value(self, value, dialect): # noqa: ANN001, ANN201
|
|
if value is not None and value.tzinfo is None:
|
|
return value.replace(tzinfo=UTC)
|
|
return value
|
|
|
|
|
|
def utcnow() -> datetime:
|
|
return datetime.now(UTC)
|
|
|
|
|
|
def new_uuid() -> uuid.UUID:
|
|
return uuid.uuid4()
|
|
|
|
|
|
class Base(DeclarativeBase):
|
|
pass
|
|
|
|
|
|
class PublicIdMixin:
|
|
"""Gives every table a UUID public id; integer PKs stay internal."""
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=new_uuid)
|
|
created_at: Mapped[datetime] = mapped_column(UTCDT(), default=utcnow, nullable=False)
|
|
# default= as well as onupdate=: SQLite enforces NOT NULL on insert
|
|
# (Postgres silently stored NULL for rows that never got an UPDATE).
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
UTCDT(), default=utcnow, onupdate=utcnow, nullable=False
|
|
)
|