From 8fae12d2189cfdf5cc0cea086ea416111a688ee9 Mon Sep 17 00:00:00 2001 From: Cliff Hill Date: Thu, 21 Aug 2025 18:55:53 -0400 Subject: [PATCH] Adding in sql.py, setting up connection and session management. Signed-off-by: Cliff Hill --- backend/src/backend/sql.py | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 backend/src/backend/sql.py diff --git a/backend/src/backend/sql.py b/backend/src/backend/sql.py new file mode 100644 index 00000000..131183ed --- /dev/null +++ b/backend/src/backend/sql.py @@ -0,0 +1,64 @@ +"""SQL code for the Numinar coding project backend.""" + +from collections.abc import Coroutine +from functools import wraps +from typing import Any +from typing import Callable +from typing import TypeVar + +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.ext.asyncio import async_sessionmaker +from sqlalchemy.ext.asyncio import create_async_engine +from sqlalchemy.orm import sessionmaker +from sqlmodel import SQLModel + +from backend import config + + +# from backend import models + + +T = TypeVar("T") + +sync_maker = sessionmaker( + autocommit=False, + autoflush=False, + expire_on_commit=False, +) +async_maker = async_sessionmaker( + autocommit=False, + autoflush=False, + expire_on_commit=False, + sync_session_class=sync_maker, +) + +engine = create_async_engine( + config("DATABASE_URL"), echo=config("ENVIRONMENT") == "development" +) + + +async def sessionize( + func: Callable[..., Coroutine[Any, Any, T]], +) -> Callable[..., Coroutine[Any, Any, T]]: + """Decorate a sql function and inject a session if it doesn't exist. + + This checks the function signature for a `session` parameter. If it does + not exist, it creates a new session and passes it to the function. + """ + + @wraps(func) + async def wrapper( + *args: Any, session: AsyncSession | None = None, **kwargs: Any + ) -> T: + if session is None: + async with async_maker() as session: + return await func(*args, session=session, **kwargs) + else: + return await func(*args, session=session, **kwargs) + + return wrapper + + +def create_db_and_tables() -> None: + """Create the database and tables.""" + SQLModel.metadata.create_all(engine.sync_engine)