diff --git a/app/api/stuff.py b/app/api/stuff.py index 6da3c5f..0703458 100644 --- a/app/api/stuff.py +++ b/app/api/stuff.py @@ -1,5 +1,9 @@ +from collections.abc import Callable +from typing import Annotated, Any + from fastapi import APIRouter, Depends, HTTPException, Request, status -from app.services.logging import get_logger +from pydantic import ValidationError, WrapValidator +from rotoger import get_logger from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.ext.asyncio import AsyncSession @@ -22,12 +26,26 @@ async def create_random_stuff( return {"id": str(random_stuff.id)} +failed_items: list[dict] = [] # Global or pass via context + +def catch_invalid(v: Any, handler: Callable[[Any], Any] ) -> Any: + try: + return handler(v) + except ValidationError: + failed_items.append(v) # Intercept here! + return None # Or raise if needed + @router.post("/add_many", status_code=status.HTTP_201_CREATED) async def create_multi_stuff( - payload: list[StuffSchema], db_session: AsyncSession = Depends(get_db) + payload: list[Annotated[StuffSchema, WrapValidator(catch_invalid)]], db_session: AsyncSession = Depends(get_db) ): + await logger.ainfo(f">>>{failed_items}") try: - stuff_instances = [Stuff(**stuff.model_dump()) for stuff in payload] + await logger.ainfo(f">>>{failed_items}") + await logger.ainfo(f">>>{payload}") + stuff_instances = [ + Stuff(**stuff.model_dump()) for stuff in payload if stuff is not None + ] db_session.add_all(stuff_instances) await db_session.commit() except SQLAlchemyError as ex: @@ -39,6 +57,7 @@ async def create_multi_stuff( await logger.ainfo( f"{len(stuff_instances)} Stuff instances inserted into the database." ) + return {"inserted": len(stuff_instances)} return True diff --git a/app/main.py b/app/main.py index 7bc0ed8..75c6acd 100644 --- a/app/main.py +++ b/app/main.py @@ -5,7 +5,7 @@ import asyncpg from fastapi import Depends, FastAPI, Request from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates -from app.services.logging import get_logger +from rotoger import get_logger from starlette.middleware import Middleware from starlette.middleware.gzip import GZipMiddleware @@ -21,7 +21,6 @@ from app.middleware.profiler import ProfilingMiddleware from app.redis import get_redis from app.services.auth import AuthBearer -# logger = get_logger() templates = Jinja2Templates(directory=Path(__file__).parent.parent / "templates") diff --git a/app/schemas/stuff.py b/app/schemas/stuff.py index 098d776..6343cdc 100644 --- a/app/schemas/stuff.py +++ b/app/schemas/stuff.py @@ -1,7 +1,7 @@ -from typing import Any, Callable +from typing import Any from uuid import UUID -from pydantic import BaseModel, ConfigDict, Field, WrapValidator, ValidationError +from pydantic import BaseModel, ConfigDict, Field config = ConfigDict(from_attributes=True) diff --git a/app/server.py b/app/server.py index 40d297f..744463d 100644 --- a/app/server.py +++ b/app/server.py @@ -1,5 +1,6 @@ from granian import Granian + def startup(): print("Server starting up...") @@ -16,4 +17,4 @@ server = Granian( ) server.on_startup(startup) server.on_shutdown(shutdown) -server.serve_forever() \ No newline at end of file +server.serve_forever()