"""
Run with:
pip install -r requirements.txt
uvicorn app:app --reload
Try:
curl -X POST http://127.0.0.1:8000/todos \
-H "Content-Type: application/json" \
-d '{"title": "Write docs", "priority": 2, "tags": ["docs"]}'
"""
from typing import Dict, List, Optional
from micropie import App
from pydantic import BaseModel, ConfigDict, Field, ValidationError
class TodoCreate(BaseModel):
model_config = ConfigDict(extra="forbid")
title: str = Field(min_length=1, max_length=120)
priority: int = Field(default=3, ge=1, le=5)
tags: List[str] = Field(default_factory=list)
class Todo(TodoCreate):
id: int
completed: bool = False
class Root(App):
def __init__(self):
super().__init__()
self._todos: Dict[int, Todo] = {}
self._next_id = 1
async def index(self):
return {
"message": "MicroPie + pydantic example",
"routes": {
"GET /todos": "List todos",
"GET /todos/<id>": "Fetch one todo",
"POST /todos": "Create a todo from a JSON body",
},
"example": {
"title": "Write a MicroPie example",
"priority": 2,
"tags": ["docs", "pydantic"],
},
}
async def todos(self, todo_id: Optional[str] = None):
if self.request.method == "GET":
if todo_id is None:
return {"todos": [todo.model_dump() for todo in self._todos.values()]}
try:
todo = self._todos[int(todo_id)]
except (KeyError, ValueError):
return 404, {"error": "Todo not found"}
return todo.model_dump()
if self.request.method == "POST":
try:
todo_in = TodoCreate.model_validate(self.request.json())
except ValidationError as exc:
return 422, {"errors": exc.errors()}
todo = Todo(id=self._next_id, **todo_in.model_dump())
self._todos[todo.id] = todo
self._next_id += 1
return 201, todo.model_dump()
return 405, {"error": "Method not allowed"}
app = Root() # Run with `uvicorn app:app --reload`