<>
Stack: Python <<FILL IN: 3.12>>, FastAPI, Pydantic v2, SQLAlchemy 2.0 (async), Alembic. Package/deps: <<FILL IN: uv | poetry | pip-tools>>.
- Layered:
routers/(HTTP only) →services/(business logic) →repositories/(DB). Routers must not touch the DB directly; services must not build HTTP responses. - Pydantic models for all I/O. Separate
schemas/(API contracts) from ORM models (models/). Never return ORM objects directly from an endpoint. - Async all the way down. Use
async defendpoints and the async SQLAlchemy session. Never call blocking I/O inside an async path — offload withrun_in_threadpool. - Dependencies via FastAPI
Depends(), not module-level globals.
- Type-hint everything. Code must pass
mypy --strict. - Validate config with a Pydantic
Settingsclass reading from env — no bareos.getenv. - Raise
HTTPExceptionfor client errors; let a global handler format unexpected errors. - Migrations: never edit the DB by hand — always
alembic revision --autogenerate.
- Run:
<<FILL IN: uv run uvicorn app.main:app --reload>> - Typecheck:
mypy --strict . - Lint/format:
ruff check . && ruff format . - Test:
pytest -q
Run mypy, ruff, and pytest before reporting a task complete.
- Don't use sync
requests/time.sleepin async code — usehttpx.AsyncClient/asyncio.sleep. - Don't put secrets in code or commit
.env. - Don't catch bare
except:— catch specific exceptions and handle them. - Don't add a dependency before checking the stdlib or existing deps can do it.