Pydantic v2 et l'outillage : uv, ruff, import-linter
Pydantic v2 : valider aux frontières
La règle implicite du projet : dataclasses à l'intérieur, Pydantic aux frontières — tout ce qui entre (HTTP, sortie LLM, config) passe par un modèle validé :
from pydantic import BaseModel, Field
class StructuredLine(BaseModel):
sku: str | None = None
label: str
quantity: float = Field(gt=0)
unit_price: float | None = None
Trois usages dans le projet :
- schémas d'API : FastAPI valide automatiquement les corps de requêtes/réponses ;
- sortie LLM : le JSON produit par le structurer est validé par un modèle Pydantic — un LLM qui renvoie
quantity: -3explose ici, pas trois couches plus loin (fail loud) ; - Settings :
pydantic-settingslit l'environnement en objets typés (DJUST_DB_SCHEMA, clés API…) — la config invalide tue le boot, pas la première requête.
uv workspace : le monorepo Python
Chaque module est un package du workspace uv (un pyproject.toml racine + un par package, un seul uv.lock). Tu as vu uv au cours ML (module 3) — la nouveauté ici est le workspace : uv sync installe tout l'arbre cohérent, et chaque package déclare SES dépendances (deptry vérifie qu'aucune n'est superflue).
La CI qui rend l'architecture obligatoire
Le projet ne « recommande » pas ses conventions — il les fait échouer en CI :
| Garde-fou | Ce qu'il casse |
|---|---|
ruff (E,W,F,I,B,UP,SIM,ASYNC,S…) | style, imports, appels bloquants en async, sécurité |
mypy --strict par package | tout trou de typage |
import-linter | un module domaine qui en importe un autre |
deptry / vulture | dépendance déclarée non utilisée / code mort |
| hooks pre-commit | commit sur main, filtre tenant manuel (module 3 !), schéma en dur |
Où le projet place-t-il Pydantic vs dataclasses ?