api_service.py in Python
A small FastAPI service: models, dependency-injected store, routes, tests.
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.testclient import TestClient
from pydantic import BaseModel, Field
class TourIn(BaseModel):
slug: str = Field(pattern=r"^[a-z][a-z0-9_-]{1,31}$")
title: str = Field(max_length=60)
steps: int = Field(default=0, ge=0)
class TourOut(TourIn):
id: int
class Store:
"""An in-memory stand-in for a database."""
def __init__(self):
self._rows: dict[int, TourOut] = {}
self._next = 1
def add(self, tour: TourIn) -> TourOut:
if any(row.slug == tour.slug for row in self._rows.values()):
raise KeyError(tour.slug)
row = TourOut(id=self._next, **tour.model_dump())
self._rows[self._next] = row
self._next += 1
return row
def all(self) -> list[TourOut]:
return list(self._rows.values())
def get(self, tour_id: int) -> TourOut | None:
return self._rows.get(tour_id)
store = Store()
app = FastAPI(title="tours")
def get_store() -> Store:
return store
@app.get("/healthz")
def healthz():
return {"status": "ok"}
@app.get("/tours", response_model=list[TourOut])
def list_tours(shop: Store = Depends(get_store)):
return shop.all()
@app.post("/tours", response_model=TourOut,
status_code=status.HTTP_201_CREATED)
def create_tour(tour: TourIn, shop: Store = Depends(get_store)):
try:
return shop.add(tour)
except KeyError:
raise HTTPException(status.HTTP_409_CONFLICT, f"{tour.slug} exists")
@app.get("/tours/{tour_id}", response_model=TourOut)
def read_tour(tour_id: int, shop: Store = Depends(get_store)):
found = shop.get(tour_id)
if found is None:
raise HTTPException(status.HTTP_404_NOT_FOUND, "no such tour")
return found
def main():
client = TestClient(app)
print(client.get("/healthz").json())
made = client.post("/tours", json={"slug": "basics",
"title": "Language basics",
"steps": 60})
print(made.status_code, made.json())
again = client.post("/tours", json={"slug": "basics", "title": "Dup"})
print(again.status_code, again.json()["detail"])
bad = client.post("/tours", json={"slug": "Bad Slug", "title": "x"})
print(bad.status_code, bad.json()["detail"][0]["loc"])
print(client.get("/tours/1").json()["title"])
print(client.get("/tours/99").status_code)
print(len(client.get("/tours").json()))
if __name__ == "__main__":
main()
How it works
- Pydantic models define the request and response shapes.
- The store arrives through Depends, so a test can replace it.
- The TestClient exercises every route at the bottom.
Keywords and builtins used here
StoreTourInTourOutaddallanyclasscreate_tourdefdictexceptforgetget_storehealthzidifintlenlistlist_toursmainprintraiseread_tourreturnselfstrtry
The run, in numbers
- Lines
- 94
- Characters to type
- 2223
- Tokens
- 668
- Three-star pace
- 115 tpm
At the three-star pace of 115 tokens a minute, this run takes about 349 seconds.
Step 1 of 2 in Encore, step 18 of 19 in Web services & data access.