Backend Development
Guide to developing the Patrimoine backend — a FastAPI application running on Python 3.13 with SQLAlchemy 2.0 async, Alembic migrations, and SQLite (or PostgreSQL).
Prerequisites
Section titled “Prerequisites”- Python 3.13
- uv — the Python package manager
cd backenduv sync --extra devThe --extra dev flag installs pytest and ruff in addition to runtime
dependencies.
Linting
Section titled “Linting”uv run ruff check .Auto-fix:
uv run ruff check --fix .Ruff configuration lives in backend/pyproject.toml. See
Code Style & Linting for rule details.
Testing
Section titled “Testing”uv run pytest tests/ -qTests use asyncio_mode=auto (configured in pyproject.toml). The suite
contains about 6,300 tests across 310 files (uv run pytest tests --collect-only -q | tail -1 gives the current number). A filterwarnings entry suppresses the
known aiosqlite _connection_worker_thread event-loop-closed warning that
occurs when the background thread outlives the test event loop. See
Testing for fixture details.
Running the Dev Server
Section titled “Running the Dev Server”uv run uvicorn app.main:app --reload --port 8000The API is available at http://localhost:8000. Interactive docs at
http://localhost:8000/docs, served when DEBUG=true or EXPOSE_API_DOCS=true is set
(both are off by default).
Creating a Migration
Section titled “Creating a Migration”-
Generate a new revision:
Terminal window uv run alembic revision -m "description" -
Open the new file in
alembic/versions/and write theupgrade()anddowngrade()functions. -
Use a sequential numeric revision ID — the next number after the latest migration (for example, with
129as the latest, the next is130). -
Test the migration round-trip:
Terminal window uv run alembic upgrade headuv run alembic downgrade base
Adding a New Router
Section titled “Adding a New Router”-
Create
app/routers/thing.py:from fastapi import APIRouterrouter = APIRouter() -
Define endpoints using
Depends(get_current_user)for auth andDepends(get_db)for database access. -
Register the router in
app/main.py:app.include_router(thing.router, prefix="/api/v1/things", tags=["things"]) -
Add a test in
backend/tests/(happy path plus one failure case). -
Regenerate the OpenAPI schema:
Terminal window cd backend && uv run python scripts/export_openapi.py -
Bump
versioninbackend/pyproject.toml(feat = minor, fix = patch), runcd backend && uv lockand re-exportopenapi.json; see Contributing.
Adding a New Model
Section titled “Adding a New Model”-
Create
app/models/thing.py:from app.models.base import Base, TimestampMixinclass Thing(Base, TimestampMixin):... -
Export the model in
app/models/__init__.py. -
Create a migration (see Creating a Migration).
-
Create Pydantic schemas in
app/schemas/thing.py(ThingCreate,ThingUpdate,ThingOut). -
Create a service in
app/services/thing_service.py.
OpenAPI Schema
Section titled “OpenAPI Schema”After any API change (new endpoint, modified schema, etc.), regenerate and
commit openapi.json:
cd backend && uv run python scripts/export_openapi.pyCI verifies the schema is up to date with the --check flag:
cd backend && uv run python scripts/export_openapi.py --checkIf CI fails on this step, run the export command locally and commit the
updated openapi.json.