32k pixel as hard group limit, better manual resolution support

This commit is contained in:
sebastien committed 2026-09-22 11:42:16 +02:00
1 parent a9c0703f03
commit 5009831c7c
9 files changed
+322 -58

No files matched your search

+26 -9
View File
@@ -132,6 +132,18 @@ def set_suffix_and_clean_error(
result["error"] = error
def pending_manual_conflicts(results: dict[str, Any]) -> set[tuple[str, str, str]]:
"""Return the copy/source/target conflicts listed by correction's manual file."""
return {
(item["id"], label, target)
for label, batches in results.items()
for batch in batches
for item in batch
for kind, target in item.get("result", {}).get("delayed", [])
if kind in {"wrong-label", "add-label"}
}
def get_actual_pdf(copies_dir: Path, copy_id: str, label: str) -> Path:
base = copies_dir / f"Copie{copy_id}" / f"{label}.pdf"
for candidate in (
@@ -157,13 +169,7 @@ def _validate_pdf_inputs(
missing: set[Path] = set()
for instruction in instructions:
source = initial_paths[(instruction.copy_id, instruction.old_label)]
destination = initial_paths[(instruction.copy_id, instruction.new_label)]
if instruction.should_merge:
if not source.exists():
missing.add(source)
if not destination.exists():
missing.add(destination)
elif instruction.should_copy and not source.exists():
if (instruction.should_merge or instruction.should_copy) and not source.exists():
missing.add(source)
if missing:
rendered = ", ".join(str(path) for path in sorted(missing))
@@ -178,6 +184,10 @@ def resolve_manual(workspace: EvaluationWorkspace) -> ExitCode:
raise CliError("correction.json must contain a JSON object")
results: dict[str, Any] = loaded
instructions = parse_instructions(workspace.manual_resolutions_file)
retained_conflicts = {
(item.copy_id, item.old_label, item.new_label) for item in instructions
}
dismissed_conflicts = pending_manual_conflicts(results) - retained_conflicts
cut_sources = [(item.copy_id, item.old_label) for item in instructions if item.cut]
if len(set(cut_sources)) != len(cut_sources):
raise CliError("Une seule coupe par label source est autorisée dans une résolution.")
@@ -226,9 +236,11 @@ def resolve_manual(workspace: EvaluationWorkspace) -> ExitCode:
try:
if instruction.pipe_first:
writer.append(source)
writer.append(destination)
if destination.exists():
writer.append(destination)
else:
writer.append(destination)
if destination.exists():
writer.append(destination)
writer.append(source)
writer.write(temp_output)
except Exception:
@@ -285,6 +297,9 @@ def resolve_manual(workspace: EvaluationWorkspace) -> ExitCode:
if temporary not in used_temps:
temporary.unlink(missing_ok=True)
for copy_id, label, target in dismissed_conflicts:
# A removed instruction acknowledges the conflict without touching PDFs.
set_suffix_and_clean_error(results, copy_id, label, None, target)
atomic_write_json(workspace.correction_file, results)
refaire_tasks = [[copy_name, labels] for copy_name, labels in refaire_by_copy.items()]
if refaire_tasks:
@@ -292,6 +307,8 @@ def resolve_manual(workspace: EvaluationWorkspace) -> ExitCode:
workspace.manual_resolutions_file.unlink()
print("Manual resolutions successfully applied.")
if dismissed_conflicts:
print(f"{len(dismissed_conflicts)} removed conflict(s) dismissed; their PDFs were kept unchanged.")
if refaire_tasks:
print(
f"File {workspace.refaire_file.name} generated. Run "