GUI documentation

This commit is contained in:
2026-09-10 07:23:39 +02:00
parent f7b3689f23
commit dfce79f240
6 changed files with 418 additions and 63 deletions
+148 -39
View File
@@ -61,14 +61,14 @@ class StepDefinition:
return all(variant.kind == "manual" for variant in self.variants)
def arg_target(help_text: str = "Dossier d’évaluation ou fichier à traiter") -> ArgumentSpec:
def arg_target(help_text: str = "un dossier d’évaluation ou un fichier à traiter") -> ArgumentSpec:
return ArgumentSpec(
"target",
"Cible",
kind="path",
default=EVALUATION,
positional=True,
help=help_text,
help=f"La cible peut être {help_text.rstrip('.')}.",
)
@@ -107,12 +107,13 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
) + ((python("personal", "Énoncés et solutions personnels (SHEETINFO)", "statement-personal"),)
if show_personal_steps else ()),
arguments=(
arg_target("Dossier de l’évaluation"),
arg_target("le dossier de l’évaluation"),
ArgumentSpec(
"restart",
"Ignorer le cache (--restart)",
kind="bool",
flag="--restart",
help="Ignore les résultats Gemini mis en cache et recommence entièrement lanalyse de l’énoncé.",
variants=("gemini",),
),
),
@@ -124,7 +125,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Facultatif après la génération : remplace les groupes par exercice par des groupes "
"proposés par Gemini, en conservant les labels, les énoncés, les solutions et les barèmes.",
(python("default", "Groupes Gemini", "statement", fixed_args=("--groups-only",)),),
arguments=(arg_target("Dossier de l’évaluation"),),
arguments=(arg_target("le dossier de l’évaluation"),),
optional=True, personal=True, requires=("labels", "Text2", "Sol2"),
),
StepDefinition(
@@ -132,7 +133,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Facultatif : remplace Persp par des barèmes Gemini sur 4 points, pour les groupes actuels. "
"Les énoncés et les solutions personnels sont conservés.",
(python("default", "Barèmes Gemini", "statement", fixed_args=("--persp-only",)),),
arguments=(arg_target("Dossier de l’évaluation"),),
arguments=(arg_target("le dossier de l’évaluation"),),
optional=True, personal=True, requires=("labels", "label_groups", "Text2", "Sol2"),
),
StepDefinition(
@@ -160,7 +161,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
supports_verbose=True,
),
),
arguments=(arg_target("Dossier de l’évaluation"),),
arguments=(arg_target("le dossier de l’évaluation"),),
optional=True,
),
StepDefinition(
@@ -179,7 +180,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
supports_verbose=True,
),
),
arguments=(arg_target("Dossier de l’évaluation"),),
arguments=(arg_target("le dossier de l’évaluation"),),
),
StepDefinition(
"page_splitter",
@@ -187,7 +188,16 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Séparer et réordonner les pages",
"Ouvre loutil interactif de découpage A3 vers A4. La cible peut être un dossier ou un PDF.",
(python("default", "Séparation des pages", "page-split"),),
arguments=(arg_target(), ArgumentSpec("marked", "Copies signalées uniquement", "bool", "--marked")),
arguments=(
arg_target(),
ArgumentSpec(
"marked",
"Copies signalées uniquement",
"bool",
"--marked",
help="Limite lopération aux copies signalées dans linterface au lieu de traiter toutes les copies.",
),
),
artifacts=("Copies", "Copies Originales"),
),
StepDefinition(
@@ -198,8 +208,17 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"puis remplace les PDF dans Copies. Les versions non rognées sont sauvegardées. "
"À effectuer avant la détection des labels. Traite plusieurs copies en parallèle.",
(python("default", "Rognage des zones vides", "crop-margins"),),
arguments=(arg_target("Dossier de l’évaluation ou PDF dans Copies"),
ArgumentSpec("workers", "Copies traitées en parallèle", "int", "--workers", default=5)),
arguments=(
arg_target("le dossier de l’évaluation ou un PDF du dossier Copies"),
ArgumentSpec(
"workers",
"Copies traitées en parallèle",
"int",
"--workers",
default=5,
help="Fixe le nombre maximal de copies rognées simultanément. Une valeur élevée accélère le traitement si la machine possède assez de cœurs et de mémoire.",
),
),
optional=True,
requires=("Copies",),
auto_start_first_visit=ALWAYS_CROP,
@@ -212,8 +231,20 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
(python("default", "Découpe", "crop-labels"),),
arguments=(
arg_target(),
ArgumentSpec("fullpage", "Toujours utiliser la page entière", "bool", "--fullpage"),
ArgumentSpec("marked", "Copies signalées uniquement", "bool", "--marked"),
ArgumentSpec(
"fullpage",
"Toujours utiliser la page entière",
"bool",
"--fullpage",
help="Désactive la découpe habituelle de la marge gauche et transmet chaque page entière à la détection des labels.",
),
ArgumentSpec(
"marked",
"Copies signalées uniquement",
"bool",
"--marked",
help="Limite lopération aux copies signalées dans linterface au lieu de traiter toutes les copies.",
),
),
requires=("Copies",),
artifacts=("Cutleft",),
@@ -226,7 +257,13 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
(python("default", "Détection des labels", "labels"),),
arguments=(
arg_target(),
ArgumentSpec("overwrite", "Régénérer les résultats", "bool", "--overwrite"),
ArgumentSpec(
"overwrite",
"Régénérer les résultats",
"bool",
"--overwrite",
help="Relance la détection même lorsquun fichier JSON de labels existe déjà pour la copie.",
),
),
requires=("labels", "Copies", "Cutleft"),
artifacts=("Copies/*.json",),
@@ -265,13 +302,14 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"sauvegardés et plusieurs fichiers sont analysés en parallèle.",
(python("default", "Rognage du bas", "crop-answer-bottoms"),),
arguments=(
arg_target("Dossier de l’évaluation"),
arg_target("le dossier de l’évaluation"),
ArgumentSpec(
"workers",
"PDF traités en parallèle",
"int",
"--workers",
default=5,
help="Fixe le nombre maximal de PDF de réponse analysés simultanément. Une valeur élevée accélère le traitement si la machine possède assez de cœurs et de mémoire.",
),
),
optional=True,
@@ -284,7 +322,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Regrouper les réponses",
"Regroupe les réponses portant le même label pour préparer les requêtes.",
(python("default", "Regroupement", "group-answers"),),
arguments=(arg_target("Dossier de l’évaluation"),),
arguments=(arg_target("le dossier de l’évaluation"),),
requires=("Copies",),
artifacts=("Par label",),
auto_start_first_visit=True,
@@ -308,12 +346,13 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
python("reset", "Réinitialiser les corrections", "correct", fixed_args=("--reset",), dangerous=True),
),
arguments=(
arg_target("Évaluation ou image Group_X.jpg"),
arg_target("le dossier de l’évaluation ou une image Group_X.jpg"),
ArgumentSpec(
"overwrite",
"Écraser les corrections existantes",
"bool",
"--overwrite",
help="Relance les corrections demandées même lorsquun résultat existe déjà.",
variants=("live", "batch", "hybrid", "refaire"),
),
ArgumentSpec(
@@ -321,9 +360,17 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Limite dappels Pro",
"int",
"--limit",
help="Limite le nombre dappels au modèle Pro pendant cette exécution. Laissez ce champ vide pour ne pas imposer de limite.",
variants=("live", "hybrid", "refaire"),
),
ArgumentSpec("batch_from", "Premier label envoyé en batch", "text", "--batch-from", variants=("hybrid",)),
ArgumentSpec(
"batch_from",
"Premier label envoyé en batch",
"text",
"--batch-from",
help="Indique le premier label traité en batch ; les labels précédents sont corrigés immédiatement.",
variants=("hybrid",),
),
),
requires=("Par label", "Persp", "labels"),
artifacts=("correction.json", "batch_requests_*.jsonl"),
@@ -339,7 +386,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Envoyer les batchs",
"Envoie à Gemini les fichiers JSONL produits par le mode batch.",
(python("default", "Envoi", "batch-submit"),),
arguments=(arg_target("Dossier de l’évaluation"),),
arguments=(arg_target("le dossier de l’évaluation"),),
optional=True,
artifacts=("batch_jobs.json",),
skip_for_live_correction=True,
@@ -351,13 +398,19 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Affiche les jobs Gemini en cours. Lidentifiant de téléchargement est facultatif.",
(python("default", "État des batchs", "batch-status"),),
arguments=(
ArgumentSpec("download", "Télécharger le job", "text", "--download"),
ArgumentSpec(
"download",
"Télécharger le job",
"text",
"--download",
help="Saisissez lidentifiant complet dun job Gemini terminé pour télécharger son fichier de résultats.",
),
ArgumentSpec(
"output",
"Fichier JSONL de destination",
"path",
"--output",
help="Utilisé avec un identifiant de téléchargement.",
help="Choisissez le fichier JSONL dans lequel enregistrer le job téléchargé. Ce champ nest utilisé que si un identifiant de job est fourni.",
),
),
optional=True,
@@ -369,7 +422,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Récupérer les résultats batch",
"Télécharge et rassemble les réponses des jobs terminés.",
(python("default", "Récupération", "batch-fetch"),),
arguments=(arg_target("Dossier de l’évaluation"),),
arguments=(arg_target("le dossier de l’évaluation"),),
optional=True,
skip_for_live_correction=True,
),
@@ -379,7 +432,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Nettoyer la correction",
"Corrige certains problèmes dencodage et prépare le texte pour LaTeX.",
(python("default", "Post-correction", "post-correction"),),
arguments=(arg_target("Dossier de l’évaluation"),),
arguments=(arg_target("le dossier de l’évaluation"),),
requires=("correction.json",),
),
StepDefinition(
@@ -388,7 +441,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Résoudre les conflits manuels",
"Étape conditionnelle, uniquement si manual_resolutions.txt contient des conflits à traiter.",
(python("default", "Résolution", "resolve-manual"),),
arguments=(arg_target("Dossier de l’évaluation"),),
arguments=(arg_target("le dossier de l’évaluation"),),
optional=True,
requires=("manual_resolutions.txt", "correction.json"),
skip_without_manual_conflicts=True,
@@ -404,9 +457,22 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
python("grouped", "Annotations groupées (BGnot)", "annotate-grouped"),
),
arguments=(
arg_target("Dossier de l’évaluation"),
ArgumentSpec("overwrite", "Écraser les sorties", "bool", "--overwrite"),
ArgumentSpec("refaire", "Mode refaire", "bool", "--refaire", variants=("checks", "grouped")),
arg_target("le dossier de l’évaluation"),
ArgumentSpec(
"overwrite",
"Écraser les sorties",
"bool",
"--overwrite",
help="Remplace les annotations déjà générées dans le dossier de sortie sélectionné.",
),
ArgumentSpec(
"refaire",
"Mode refaire",
"bool",
"--refaire",
help="Génère uniquement les copies et questions inscrites dans refaire.json, dans le dossier réservé à la reprise.",
variants=("checks", "grouped"),
),
),
requires=("correction.json",),
artifacts=("Anot", "Bnot", "BGnot"),
@@ -418,16 +484,23 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Exporte les annotations vers le dossier EXPORT_DIR défini dans config.py.",
(python("default", "Export", "export"),),
arguments=(
arg_target("Dossier de l’évaluation"),
arg_target("le dossier de l’évaluation"),
ArgumentSpec(
"annotation_dir",
"Dossier dannotations",
"choice",
default="BGnot",
choices=("BGnot", "Bnot", "Anot"),
help="Choisissez le dossier dannotations à exporter : groupées, avec cases, ou simples.",
positional=True,
),
ArgumentSpec("refaire", "Mode refaire", "bool", "--refaire"),
ArgumentSpec(
"refaire",
"Mode refaire",
"bool",
"--refaire",
help="Exporte les annotations du passage de reprise BRnot au lieu du dossier principal.",
),
),
optional=True,
),
@@ -445,16 +518,23 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Copie les PDF présents dans IMPORT_DIR vers l’évaluation.",
(python("default", "Import", "import"),),
arguments=(
arg_target("Dossier de l’évaluation"),
arg_target("le dossier de l’évaluation"),
ArgumentSpec(
"annotation_dir",
"Dossier dannotations",
"choice",
default="BGnot",
choices=("BGnot", "Bnot", "Anot"),
help="Choisissez le dossier principal dans lequel importer les annotations manuscrites.",
positional=True,
),
ArgumentSpec("refaire", "Mode refaire", "bool", "--refaire"),
ArgumentSpec(
"refaire",
"Mode refaire",
"bool",
"--refaire",
help="Importe les annotations manuscrites dans BRnot pour le passage de reprise.",
),
),
),
StepDefinition(
@@ -467,9 +547,22 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
python("grouped", "Lecture BGnot", "read-grouped"),
),
arguments=(
arg_target("Dossier de l’évaluation"),
ArgumentSpec("update_score", "Réappliquer les score.json", "bool", "--update-score"),
ArgumentSpec("refaire", "Mode refaire", "bool", "--refaire", variants=("grouped",)),
arg_target("le dossier de l’évaluation"),
ArgumentSpec(
"update_score",
"Réappliquer les score.json",
"bool",
"--update-score",
help="Réutilise les valeurs présentes dans les fichiers score.json pour remplacer les scores lus dans les annotations.",
),
ArgumentSpec(
"refaire",
"Mode refaire",
"bool",
"--refaire",
help="Lit les annotations du passage de reprise BRnot et les fusionne avec les copies principales.",
variants=("grouped",),
),
ArgumentSpec(
"annotation_dir",
"Passage principal du mode refaire",
@@ -477,6 +570,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"--annotation-dir",
default="BGnot",
choices=("BGnot", "Bnot", "Anot"),
help="Indique le dossier dannotations du passage principal dans lequel intégrer les questions refaites.",
variants=("grouped",),
),
),
@@ -488,13 +582,14 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Crée le dossier A Rendre à partir du dossier dannotations choisi.",
(python("default", "Attribution des noms", "giving-names"),),
arguments=(
arg_target("Dossier de l’évaluation"),
arg_target("le dossier de l’évaluation"),
ArgumentSpec(
"annotation_dir",
"Dossier dannotations",
"choice",
default="BGnot",
choices=("BGnot", "Bnot", "Anot"),
help="Choisissez le dossier dannotations utilisé pour construire les fichiers nommés dans A Rendre.",
positional=True,
),
),
@@ -523,8 +618,14 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Transfère les scores, avec la possibilité de n’écrire que leur somme.",
(python("default", "Mise à jour ODS", "update-ods", supports_verbose=False),),
arguments=(
arg_target("Dossier de l’évaluation"),
ArgumentSpec("sum", "Écrire seulement la somme", "bool", "--sum"),
arg_target("le dossier de l’évaluation"),
ArgumentSpec(
"sum",
"Écrire seulement la somme",
"bool",
"--sum",
help="Écrit uniquement la note totale de chaque élève dans le fichier ODS, sans détailler les scores par question.",
),
),
personal=True,
),
@@ -550,7 +651,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
"Ajouter le score final",
"Génère les fichiers de diffusion avec le score final.",
(python("default", "Score final", "add-final-score", supports_verbose=False),),
arguments=(arg_target("Dossier de l’évaluation"),),
arguments=(arg_target("le dossier de l’évaluation"),),
personal=True,
),
StepDefinition(
@@ -602,7 +703,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
fixed_args=("--dry-run",),
),
),
arguments=(arg_target("Dossier de l’évaluation"),),
arguments=(arg_target("le dossier de l’évaluation"),),
optional=True,
requires=("Copies", "correction.json", "A Rendre"),
),
@@ -635,7 +736,15 @@ def build_refaire_workflow() -> list[StepDefinition]:
for suffix, title, description, program, flags, optional in definitions:
arguments = (arg_target(),) if program else ()
if suffix == "merge":
arguments += (ArgumentSpec("annotation_dir", "Passage principal", "choice", "--annotation-dir", default="BGnot", choices=("BGnot", "Bnot", "Anot")),)
arguments += (ArgumentSpec(
"annotation_dir",
"Passage principal",
"choice",
"--annotation-dir",
default="BGnot",
choices=("BGnot", "Bnot", "Anot"),
help="Indique le dossier dannotations du passage principal dans lequel intégrer les questions refaites.",
),)
requirements = ("refaire.json", "Copies", "labels", "correction.json")
if suffix in {"export", "tablet", "import", "merge"}:
requirements += ("BRnot",)