Initial public ModelForge release
This commit is contained in:
commit
7082ab955a
490 files changed
+104252
No files matched your search
@@ -0,0 +1,38 @@
|
||||
from collections.abc import Generator
|
||||
from typing import Any, cast
|
||||
|
||||
from sqlalchemy import CursorResult, Engine, create_engine
|
||||
from sqlalchemy.engine import Result
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from modelforge_api.persistence.runtime_engine import register_application_engine
|
||||
from modelforge_api.settings import get_settings
|
||||
|
||||
|
||||
def rows_affected(result: Result[Any]) -> int:
|
||||
"""How many rows a DML statement actually changed.
|
||||
|
||||
`Session.execute` is typed as returning `Result`, which carries no `rowcount`; a DML statement
|
||||
always returns a `CursorResult`, which does. SQLAlchemy 2.0.52 narrowed that return type, so
|
||||
reading `.rowcount` directly stopped type-checking — while continuing to work at runtime.
|
||||
|
||||
The cast is where that knowledge lives, once, rather than at ten call sites. It matters more
|
||||
than it looks: every single-use claim in the platform is a conditional UPDATE whose row count
|
||||
decides the winner, and that is what makes enrolment tokens and lifecycle claims atomic instead
|
||||
of merely usually-correct.
|
||||
"""
|
||||
|
||||
return cast("CursorResult[Any]", result).rowcount
|
||||
|
||||
|
||||
def build_engine(database_url: str | None = None) -> Engine:
|
||||
url = database_url or get_settings().database_url
|
||||
return register_application_engine(create_engine(url, pool_pre_ping=True))
|
||||
|
||||
|
||||
engine = build_engine()
|
||||
|
||||
|
||||
def get_session() -> Generator[Session, None, None]:
|
||||
with Session(engine) as session:
|
||||
yield session
|
||||
Reference in new issue
Block a user