import os from fastapi import FastAPI, HTTPException, Response from app import crud from app.db import get_engine, make_session_factory, init_db from app.schemas import ItemCreate, ItemUpdate, ItemOut def create_app(session_factory=None) -> FastAPI: if session_factory is None: db_url = os.environ.get("CHORUS_DB_URL", "sqlite:///./chorus.db") engine = get_engine(db_url) init_db(engine) session_factory = make_session_factory(engine) app = FastAPI(title="Chorus API") @app.post("/items", response_model=ItemOut) def post_item(payload: ItemCreate, response: Response): session = session_factory() try: item, created = crud.create_item(session, **payload.model_dump()) response.status_code = 201 if created else 200 return item finally: session.close() @app.get("/items", response_model=list[ItemOut]) def get_items(stage: str | None = None, modality: str | None = None, include_done: bool = False): session = session_factory() try: return crud.list_items(session, stage=stage, modality=modality, include_done=include_done) finally: session.close() @app.get("/items/{item_id}", response_model=ItemOut) def get_item(item_id: int): session = session_factory() try: item = crud.get_item(session, item_id) if item is None: raise HTTPException(status_code=404, detail="Item not found") return item finally: session.close() @app.patch("/items/{item_id}", response_model=ItemOut) def patch_item(item_id: int, payload: ItemUpdate): session = session_factory() try: fields = {k: v for k, v in payload.model_dump().items() if v is not None} try: item = crud.update_item(session, item_id, **fields) except ValueError as exc: raise HTTPException(status_code=422, detail=str(exc)) if item is None: raise HTTPException(status_code=404, detail="Item not found") return item finally: session.close() return app app = create_app()