Files
home-automation/app/db.py
T
tliu93 3d3c2bcc57 M1-T03: unify data layer, models, deps and routes onto single app DB
Collapse the three data layers into one. app/db.py now exposes a single
Base, a cached engine bound to app_database_url with SQLite WAL enabled, and
get_engine/get_session_local/reset_db_caches/get_db_session. Delete
app/auth_db.py, app/poo_db.py and app/models/base.py. All models (auth,
config, public_ip, location, poo) inherit the one Base and register on a
single metadata. Dependencies converge to a single get_db; all routes use it.

Also update the alembic env.py files (app/location/poo) and tests that
imported the removed modules so the suite stays green, and drop the obsolete
test_legacy_style_location_db test whose flow (app reading a separate location
DB) no longer exists. Location/poo Alembic chains, adopt scripts and adoption
tests remain for M1-T04; config fields remain for M1-T05.

pytest 109 passed; ruff clean (pre-existing only); WAL verified; single
Base.metadata holds all seven tables.
2026-06-12 16:35:07 +02:00

62 lines
1.6 KiB
Python

from collections.abc import Generator
from functools import lru_cache
from sqlalchemy import create_engine, event
from sqlalchemy.engine import Engine
from sqlalchemy.orm import DeclarativeBase, Session, sessionmaker
from app.config import get_settings
class Base(DeclarativeBase):
pass
def _build_connect_args(database_url: str) -> dict[str, object]:
connect_args: dict[str, object] = {}
if database_url.startswith("sqlite"):
connect_args["check_same_thread"] = False
return connect_args
@lru_cache
def _get_engine(database_url: str) -> Engine:
engine = create_engine(database_url, connect_args=_build_connect_args(database_url))
if database_url.startswith("sqlite"):
@event.listens_for(engine, "connect")
def _enable_sqlite_wal(dbapi_connection, _connection_record):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA journal_mode=WAL")
cursor.close()
return engine
@lru_cache
def _get_session_local(database_url: str) -> sessionmaker:
engine = _get_engine(database_url)
return sessionmaker(bind=engine, autoflush=False, autocommit=False, class_=Session)
def get_engine() -> Engine:
return _get_engine(get_settings().app_database_url)
def get_session_local() -> sessionmaker:
return _get_session_local(get_settings().app_database_url)
def reset_db_caches() -> None:
_get_session_local.cache_clear()
_get_engine.cache_clear()
def get_db_session() -> Generator[Session, None, None]:
session_local = get_session_local()
session = session_local()
try:
yield session
finally:
session.close()