L'échange CSV dans Forge (forge-mvc-import-export)¶
Ce document explique ce que fait l'opt-in forge-mvc-import-export, ce qu'il expose, et comment on s'en sert.
forge-mvc-import-export offre deux briques explicites : importer un CSV (lire, valider par champ, rapporter les erreurs, insérer les lignes valides) et exporter des lignes en CSV (to_csv).
Le cœur ne sait pas échanger du CSV : ce paquet fournit l'outillage, l'application fournit la fonction d'insertion et le SQL.
1. Rôle du module¶
Importer un fichier suppose de le lire, de valider chaque ligne, de signaler clairement les lignes fautives, et de n'insérer que les bonnes.
L'opt-in décompose ce flux : parse_csv lit, import_rows valide selon des FieldSpec et insère via une fonction fournie, ImportReport résume le résultat (importées + erreurs).
Pour l'export, to_csv rend des lignes en texte CSV, l'inverse de parse_csv, pour un script ou un rapport.
2. Vue d'ensemble rapide¶
| Élément | Valeur |
|---|---|
| Paquet | forge-mvc-import-export |
| Module | forge_mvc_import_export |
| Catégorie | Données et modélisation (ADR-055) |
| Couche | opt-in (brique optionnelle) |
| Dépend de | forge-mvc |
| API publique | parse_csv, to_csv, import_rows, FieldSpec, ImportReport, RowError, coerce_int, coerce_float, coerce_bool |
| Objets | FieldSpec (validation), ImportReport, RowError |
| Insertion | fonction fournie par l'application (le SQL vit dans le modèle) |
| Exception | CsvImportError |
| Installation | pip install --pre forge-mvc-import-export |
3. Schémas UML¶
Les deux schémas suivants montrent deux vues complémentaires de l'opt-in.
Le diagramme de classe montre les fonctions, les specs et le rapport.
Le diagramme de séquence montre un import validé ligne par ligne.
3.1 Diagramme de classe¶
Le diagramme de classe montre que import_rows valide selon des FieldSpec, insère via une fonction fournie, et renvoie un ImportReport.
classDiagram
direction LR
class csv {
<<module>>
+parse_csv(text, delimiter) list
+to_csv(rows, columns, delimiter) str
+import_rows(rows, specs, insert, partial) ImportReport
+coerce_int / coerce_float / coerce_bool
}
class FieldSpec {
<<dataclass>>
+str name
+bool required
+coerce
}
class ImportReport {
<<dataclass>>
+int imported
+list errors
}
class RowError {
<<dataclass>>
+int row
+str field
+str message
}
class insert {
<<callable>>
+insert(row) object
}
csv --> FieldSpec : valide selon
csv --> ImportReport : renvoie
ImportReport --> RowError : contient 0..*
csv --> insert : appelle (fournie)
À retenir :
import_rowsvalide chaque ligne selon lesFieldSpec;- les lignes valides sont insérées via la fonction
insertfournie ; - les lignes fautives deviennent des
RowError(numéro, champ, message) ; - le résultat est un
ImportReport(importées + erreurs).
3.2 Diagramme de séquence¶
Le diagramme de séquence montre un import CSV de bout en bout.
sequenceDiagram
participant App as Code applicatif
participant IO as forge_mvc_import_export
participant Insert as insert (fournie)
App->>IO: parse_csv(texte)
IO-->>App: lignes (dict en-tête -> valeur)
App->>IO: import_rows(lignes, specs, insert)
loop par ligne
IO->>IO: valide / coerce selon FieldSpec
alt ligne valide
IO->>Insert: insert(ligne typée)
else ligne invalide
IO->>IO: ajoute un RowError
end
end
IO-->>App: ImportReport (imported, errors)
À retenir :
- la validation est par champ (requis, coercition de type) ;
- une erreur sur une ligne n'interrompt pas l'import (elle est rapportée) ;
- l'insertion réelle est déléguée à l'application (le SQL lui appartient) ;
partial=Truepermet d'insérer les valides même s'il y a des erreurs.
4. API publique¶
| Élément | Signature | Rôle |
|---|---|---|
parse_csv |
parse_csv(text, *, delimiter=",") -> list[dict[str, str]] |
lit un CSV en lignes (dict) |
to_csv |
to_csv(rows, columns, delimiter=",") -> str |
rend des lignes en CSV |
import_rows |
import_rows(rows, specs, insert, partial=False) -> ImportReport |
valide et insère |
FieldSpec |
dataclass | name, required, coerce |
ImportReport |
dataclass | imported, errors |
RowError |
dataclass | row, field, message |
coerce_int / coerce_float / coerce_bool |
fonctions | coercition de valeurs |
CsvImportError |
exception | CSV illisible |
insert est une fonction dict -> object fournie par l'application (elle exécute le SQL d'insertion de votre modèle).
5. Contextes d'utilisation¶
| Besoin | Élément |
|---|---|
| Lire un CSV | parse_csv(text) |
| Valider par champ | FieldSpec(name, required, coerce) |
| Importer avec rapport | import_rows(rows, specs, insert) |
| Insérer malgré des erreurs | partial=True |
| Exporter des données | to_csv(rows, columns) |
| Coercer des valeurs | coerce_int, coerce_float, coerce_bool |
6. Exemples d'utilisation¶
6.1 Importer un CSV¶
from forge_mvc_import_export import parse_csv, import_rows, FieldSpec, coerce_int
specs = [
FieldSpec("nom", required=True),
FieldSpec("age", required=True, coerce=coerce_int),
]
def insert(row: dict) -> object:
return db.execute("INSERT INTO eleve (nom, age) VALUES (?, ?)", (row["nom"], row["age"]))
rows = parse_csv(csv_text)
report = import_rows(rows, specs, insert)
print(report.imported, "lignes importées,", len(report.errors), "erreurs")
Le SQL d'insertion vit dans votre code ; l'opt-in valide et orchestre.
6.2 Exporter en CSV¶
Aide-mémoire
Deux sens, des contrats clairs :
- import :
parse_csvpuisimport_rows(specs, insert)->ImportReport; - export :
to_csv(rows, columns).
7. Validation, rapport et frontière¶
La validation est par champ (FieldSpec) : champ requis manquant ou coercition impossible produit un RowError précis (numéro de ligne, champ, message).
Par défaut, l'import est tout-ou-rien sur les lignes valides rapportées ; partial=True insère les valides et liste les fautives.
Le SQL appartient à l'application
import_rows n'écrit pas en base lui-même : il appelle votre fonction insert.
Le SQL d'insertion vit dans le modèle de l'application (SQL visible, principe 5).
Frontière avec l'export web
Pour télécharger une entité depuis une page, la route d'export générée par le CRUD du cœur reste la voie officielle (principe 11).
to_csv sert l'export programmatique (script, rapport, données hors entité CRUD).
Indépendance du cœur
Le cœur de Forge ne dépend pas de forge-mvc-import-export : la dépendance va de l'opt-in vers le cœur.
Voir aussi¶
- Lecture CSV (csv_reader.py) :
parse_csv. - Moteur d'import (engine.py) :
import_rows,FieldSpec,ImportReport. - Export programmatique (csv_writer.py) :
to_csv. - Erreurs (errors.py) :
CsvImportError. - Progression Import/Export : apprendre l'opt-in pas à pas.