Remove `Arguments supplémentaires' boxes
This commit is contained in:
+39
-5
@@ -178,6 +178,7 @@ class CopienatorApp(tk.Tk):
|
||||
self.api_key_var = tk.StringVar(value=os.environ.get("GEMINI_API_KEY", ""))
|
||||
self.proxy_var = tk.StringVar(value=DEFAULT_HTTPS_PROXY)
|
||||
self.use_proxy_var = tk.BooleanVar(value=False)
|
||||
self.verbose_var = tk.BooleanVar(value=False)
|
||||
self.copy_var = tk.StringVar()
|
||||
self.variant_var = tk.StringVar()
|
||||
self.extra_var = tk.StringVar()
|
||||
@@ -186,6 +187,7 @@ class CopienatorApp(tk.Tk):
|
||||
|
||||
self._build_ui(show_personal_steps)
|
||||
self.extra_var.trace_add("write", lambda *_args: self._update_command_preview())
|
||||
self.verbose_var.trace_add("write", lambda *_args: self._update_command_preview())
|
||||
self.after(60, self._poll_runner)
|
||||
|
||||
if initial_evaluation and initial_evaluation.is_dir():
|
||||
@@ -237,6 +239,11 @@ class CopienatorApp(tk.Tk):
|
||||
).pack(side="left", padx=(0, 6))
|
||||
self.proxy_entry = ttk.Entry(environment, textvariable=self.proxy_var, width=28, state="disabled")
|
||||
self.proxy_entry.pack(side="left")
|
||||
ttk.Checkbutton(
|
||||
environment,
|
||||
text="Afficher les détails en cas d’erreur (--verbose)",
|
||||
variable=self.verbose_var,
|
||||
).pack(side="left", padx=(10, 0))
|
||||
profile = "standard + personnel" if show_personal_steps else "standard"
|
||||
ttk.Label(environment, text=f"Profil : {profile}").pack(side="left", padx=(12, 0))
|
||||
|
||||
@@ -672,12 +679,24 @@ class CopienatorApp(tk.Tk):
|
||||
row += 1
|
||||
row += 1
|
||||
|
||||
if not step.is_manual and step.section != REFAIRE_SECTION:
|
||||
show_extra = bool(step.extra_arguments_help) and (
|
||||
not step.extra_arguments_variants
|
||||
or variant.id in step.extra_arguments_variants
|
||||
)
|
||||
if show_extra and not step.is_manual and step.section != REFAIRE_SECTION:
|
||||
ttk.Label(self.form, text="Arguments supplémentaires").grid(
|
||||
row=row, column=0, sticky="w", pady=(10, 4), padx=(0, 8)
|
||||
)
|
||||
ttk.Entry(self.form, textvariable=self.extra_var).grid(row=row, column=1, sticky="ew", pady=(10, 4))
|
||||
row += 1
|
||||
ttk.Label(
|
||||
self.form,
|
||||
text=step.extra_arguments_help,
|
||||
foreground="#666666",
|
||||
wraplength=540,
|
||||
justify="left",
|
||||
).grid(row=row, column=1, sticky="w")
|
||||
row += 1
|
||||
|
||||
if self.show_personal_steps and step.id == "statement":
|
||||
actions = ttk.LabelFrame(self.form, text="Après génération — facultatif", padding=7)
|
||||
@@ -953,7 +972,11 @@ class CopienatorApp(tk.Tk):
|
||||
self.current_step.id,
|
||||
variant=self.variant_var.get() or self.current_step.variants[0].id,
|
||||
values=merged_values,
|
||||
extra=self.extra_var.get(),
|
||||
extra=(
|
||||
self.extra_var.get()
|
||||
if self.current_step.extra_arguments_help
|
||||
else ""
|
||||
),
|
||||
)
|
||||
|
||||
def _evaluation_arg(self) -> str:
|
||||
@@ -1020,21 +1043,32 @@ class CopienatorApp(tk.Tk):
|
||||
choice = self.state_store.step("refaire_selection").get("values", {}).get("layout", "auto")
|
||||
layout = resolve_layout(selection, EvaluationWorkspace(self.evaluation).read_labels(), choice)
|
||||
variant = replace(variant, program="annotate-grouped" if layout == "grouped" else "annotate-checks")
|
||||
return [build_command(self.repository, self.current_step, variant,
|
||||
{**values, "target": target}, self._evaluation_arg()) for target in targets]
|
||||
return [build_command(
|
||||
self.repository,
|
||||
self.current_step,
|
||||
variant,
|
||||
{**values, "target": target},
|
||||
self._evaluation_arg(),
|
||||
verbose=bool(self.verbose_var.get()),
|
||||
) for target in targets]
|
||||
|
||||
def _make_command(self) -> list[str]:
|
||||
if not self.current_step:
|
||||
return []
|
||||
if self.current_step.section == REFAIRE_SECTION:
|
||||
return self._refaire_commands()[0]
|
||||
allow_extra = bool(self.current_step.extra_arguments_help) and (
|
||||
not self.current_step.extra_arguments_variants
|
||||
or self._current_variant().id in self.current_step.extra_arguments_variants
|
||||
)
|
||||
return build_command(
|
||||
self.repository,
|
||||
self.current_step,
|
||||
self._current_variant(),
|
||||
self._values(),
|
||||
self._evaluation_arg(),
|
||||
self.extra_var.get(),
|
||||
self.extra_var.get() if allow_extra else "",
|
||||
verbose=bool(self.verbose_var.get()),
|
||||
)
|
||||
|
||||
def _update_command_preview(self) -> None:
|
||||
|
||||
+83
-12
@@ -7,6 +7,8 @@ from collections.abc import Iterable
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
from copienator.configuration import ALWAYS_CROP
|
||||
|
||||
EVALUATION = "${evaluation}"
|
||||
|
||||
|
||||
@@ -33,6 +35,7 @@ class CommandVariant:
|
||||
fixed_args_before_positionals: bool = False
|
||||
dangerous: bool = False
|
||||
danger_warning: str | None = None
|
||||
supports_verbose: bool = False
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -50,6 +53,8 @@ class StepDefinition:
|
||||
auto_start_first_visit: bool = False
|
||||
skip_for_live_correction: bool = False
|
||||
skip_without_manual_conflicts: bool = False
|
||||
extra_arguments_help: str = ""
|
||||
extra_arguments_variants: tuple[str, ...] = ()
|
||||
|
||||
@property
|
||||
def is_manual(self) -> bool:
|
||||
@@ -68,9 +73,16 @@ def arg_target(help_text: str = "Dossier d’évaluation ou fichier à traiter")
|
||||
|
||||
|
||||
def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
python = lambda ident, label, script, **kwargs: CommandVariant(
|
||||
ident, label, script, "python", **kwargs
|
||||
)
|
||||
def python(ident, label, script, **kwargs):
|
||||
supports_verbose = kwargs.pop("supports_verbose", True)
|
||||
return CommandVariant(
|
||||
ident,
|
||||
label,
|
||||
script,
|
||||
"python",
|
||||
supports_verbose=supports_verbose,
|
||||
**kwargs,
|
||||
)
|
||||
manual = lambda ident, label="Étape manuelle": CommandVariant(
|
||||
ident, label, None, "manual"
|
||||
)
|
||||
@@ -111,7 +123,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
"statement_groups", "Prétraitement de l’énoncé", "Regrouper les questions avec Gemini",
|
||||
"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.",
|
||||
(CommandVariant("default", "Groupes Gemini", "statement", fixed_args=("--groups-only",)),),
|
||||
(python("default", "Groupes Gemini", "statement", fixed_args=("--groups-only",)),),
|
||||
arguments=(arg_target("Dossier de l’évaluation"),),
|
||||
optional=True, personal=True, requires=("labels", "Text2", "Sol2"),
|
||||
),
|
||||
@@ -119,7 +131,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
"statement_persp", "Prétraitement de l’énoncé", "Remplacer les barèmes par Gemini",
|
||||
"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.",
|
||||
(CommandVariant("default", "Barèmes Gemini", "statement", fixed_args=("--persp-only",)),),
|
||||
(python("default", "Barèmes Gemini", "statement", fixed_args=("--persp-only",)),),
|
||||
arguments=(arg_target("Dossier de l’évaluation"),),
|
||||
optional=True, personal=True, requires=("labels", "label_groups", "Text2", "Sol2"),
|
||||
),
|
||||
@@ -145,6 +157,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
"python",
|
||||
("rotate",),
|
||||
fixed_args_before_positionals=True,
|
||||
supports_verbose=True,
|
||||
),
|
||||
),
|
||||
arguments=(arg_target("Dossier de l’évaluation"),),
|
||||
@@ -163,6 +176,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
"python",
|
||||
("rename",),
|
||||
fixed_args_before_positionals=True,
|
||||
supports_verbose=True,
|
||||
),
|
||||
),
|
||||
arguments=(arg_target("Dossier de l’évaluation"),),
|
||||
@@ -188,6 +202,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
ArgumentSpec("workers", "Copies traitées en parallèle", "int", "--workers", default=5)),
|
||||
optional=True,
|
||||
requires=("Copies",),
|
||||
auto_start_first_visit=ALWAYS_CROP,
|
||||
),
|
||||
StepDefinition(
|
||||
"cutleft",
|
||||
@@ -215,6 +230,10 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
),
|
||||
requires=("labels", "Copies", "Cutleft"),
|
||||
artifacts=("Copies/*.json",),
|
||||
extra_arguments_help=(
|
||||
"PDF de copie ou images Cutleft supplémentaires de cette évaluation, "
|
||||
"séparés par des espaces. Mettez entre guillemets les chemins contenant des espaces."
|
||||
),
|
||||
),
|
||||
StepDefinition(
|
||||
"plotting",
|
||||
@@ -257,6 +276,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
),
|
||||
optional=True,
|
||||
requires=("Copies/Copie*/*.pdf",),
|
||||
auto_start_first_visit=ALWAYS_CROP,
|
||||
),
|
||||
StepDefinition(
|
||||
"grouping",
|
||||
@@ -289,12 +309,29 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
),
|
||||
arguments=(
|
||||
arg_target("Évaluation ou image Group_X.jpg"),
|
||||
ArgumentSpec("overwrite", "Écraser les corrections existantes", "bool", "--overwrite", variants=("live",)),
|
||||
ArgumentSpec("limit", "Limite d’appels Pro", "int", "--limit", variants=("live",)),
|
||||
ArgumentSpec(
|
||||
"overwrite",
|
||||
"Écraser les corrections existantes",
|
||||
"bool",
|
||||
"--overwrite",
|
||||
variants=("live", "batch", "hybrid", "refaire"),
|
||||
),
|
||||
ArgumentSpec(
|
||||
"limit",
|
||||
"Limite d’appels Pro",
|
||||
"int",
|
||||
"--limit",
|
||||
variants=("live", "hybrid", "refaire"),
|
||||
),
|
||||
ArgumentSpec("batch_from", "Premier label envoyé en batch", "text", "--batch-from", variants=("hybrid",)),
|
||||
),
|
||||
requires=("Par label", "Persp", "labels"),
|
||||
artifacts=("correction.json", "batch_requests_*.jsonl"),
|
||||
extra_arguments_help=(
|
||||
"Images Group_X.jpg supplémentaires de cette évaluation, séparées par des espaces. "
|
||||
"Mettez entre guillemets les chemins contenant des espaces."
|
||||
),
|
||||
extra_arguments_variants=("live", "batch", "hybrid", "refaire"),
|
||||
),
|
||||
StepDefinition(
|
||||
"submit_batches",
|
||||
@@ -313,7 +350,16 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
"Consulter l’état des batchs",
|
||||
"Affiche les jobs Gemini en cours. L’identifiant de téléchargement est facultatif.",
|
||||
(python("default", "État des batchs", "batch-status"),),
|
||||
arguments=(ArgumentSpec("download", "Télécharger le job", "text", "--download"),),
|
||||
arguments=(
|
||||
ArgumentSpec("download", "Télécharger le job", "text", "--download"),
|
||||
ArgumentSpec(
|
||||
"output",
|
||||
"Fichier JSONL de destination",
|
||||
"path",
|
||||
"--output",
|
||||
help="Utilisé avec un identifiant de téléchargement.",
|
||||
),
|
||||
),
|
||||
optional=True,
|
||||
skip_for_live_correction=True,
|
||||
),
|
||||
@@ -360,7 +406,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
arguments=(
|
||||
arg_target("Dossier de l’évaluation"),
|
||||
ArgumentSpec("overwrite", "Écraser les sorties", "bool", "--overwrite"),
|
||||
ArgumentSpec("refaire", "Mode refaire", "bool", "--refaire", variants=("checks",)),
|
||||
ArgumentSpec("refaire", "Mode refaire", "bool", "--refaire", variants=("checks", "grouped")),
|
||||
),
|
||||
requires=("correction.json",),
|
||||
artifacts=("Anot", "Bnot", "BGnot"),
|
||||
@@ -424,6 +470,15 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
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",)),
|
||||
ArgumentSpec(
|
||||
"annotation_dir",
|
||||
"Passage principal du mode refaire",
|
||||
"choice",
|
||||
"--annotation-dir",
|
||||
default="BGnot",
|
||||
choices=("BGnot", "Bnot", "Anot"),
|
||||
variants=("grouped",),
|
||||
),
|
||||
),
|
||||
),
|
||||
StepDefinition(
|
||||
@@ -466,7 +521,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
"Étapes personnelles",
|
||||
"Mettre à jour le fichier ODS",
|
||||
"Transfère les scores, avec la possibilité de n’écrire que leur somme.",
|
||||
(python("default", "Mise à jour ODS", "update-ods"),),
|
||||
(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"),
|
||||
@@ -494,7 +549,7 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
"Étapes personnelles",
|
||||
"Ajouter le score final",
|
||||
"Génère les fichiers de diffusion avec le score final.",
|
||||
(python("default", "Score final", "add-final-score"),),
|
||||
(python("default", "Score final", "add-final-score", supports_verbose=False),),
|
||||
arguments=(arg_target("Dossier de l’évaluation"),),
|
||||
personal=True,
|
||||
),
|
||||
@@ -540,6 +595,12 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
"Continuer ?"
|
||||
),
|
||||
),
|
||||
python(
|
||||
"dry_run",
|
||||
"Prévisualiser sans supprimer",
|
||||
"clean",
|
||||
fixed_args=("--dry-run",),
|
||||
),
|
||||
),
|
||||
arguments=(arg_target("Dossier de l’évaluation"),),
|
||||
optional=True,
|
||||
@@ -580,7 +641,14 @@ def build_refaire_workflow() -> list[StepDefinition]:
|
||||
requirements += ("BRnot",)
|
||||
steps.append(StepDefinition(
|
||||
f"refaire_{suffix}", SECTION, title, description,
|
||||
(CommandVariant("default", title, program, "python" if program else "manual", flags),),
|
||||
(CommandVariant(
|
||||
"default",
|
||||
title,
|
||||
program,
|
||||
"python" if program else "manual",
|
||||
flags,
|
||||
supports_verbose=program is not None,
|
||||
),),
|
||||
arguments=arguments, optional=optional, requires=requirements,
|
||||
))
|
||||
return steps
|
||||
@@ -597,6 +665,7 @@ def build_command(
|
||||
values: dict[str, object],
|
||||
evaluation_arg: str,
|
||||
extra_arguments: str = "",
|
||||
verbose: bool = False,
|
||||
) -> list[str]:
|
||||
if variant.kind == "manual" or not variant.program:
|
||||
return []
|
||||
@@ -633,6 +702,8 @@ def build_command(
|
||||
if not variant.fixed_args_before_positionals:
|
||||
command.extend(variant.fixed_args)
|
||||
command.extend(options)
|
||||
if verbose and variant.supports_verbose:
|
||||
command.append("--verbose")
|
||||
if extra_arguments.strip():
|
||||
command.extend(shlex.split(extra_arguments, posix=os.name != "nt"))
|
||||
return command
|
||||
|
||||
Reference in New Issue
Block a user