feat(gui): échec amont clair si dossier de sortie non inscriptible (P1-6)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -99,6 +99,10 @@ def discover_documents(input_path, extensions: Optional[Sequence[str]] = None) -
|
||||
return []
|
||||
|
||||
|
||||
class OutputNotWritableError(RuntimeError):
|
||||
"""Le dossier de sortie n'est pas inscriptible (échec amont, message clair)."""
|
||||
|
||||
|
||||
@dataclass
|
||||
class DocResult:
|
||||
"""Détail anonymisé d'un document traité (pour la télémétrie d'usage).
|
||||
@@ -195,6 +199,19 @@ class ProcessingRunner:
|
||||
log("Aucun document supporté détecté.")
|
||||
return summary
|
||||
|
||||
# Sonde amont : on vérifie une seule fois que le dossier de sortie est
|
||||
# inscriptible AVANT la boucle, pour un échec clair et unique (P1-6)
|
||||
# plutôt qu'une erreur cryptique répétée à chaque document.
|
||||
try:
|
||||
out_root.mkdir(parents=True, exist_ok=True)
|
||||
probe = out_root / ".anon_write_test"
|
||||
probe.write_text("", encoding="utf-8")
|
||||
probe.unlink()
|
||||
except Exception as exc:
|
||||
raise OutputNotWritableError(
|
||||
f"Dossier de sortie non inscriptible : {out_root} ({exc})"
|
||||
) from exc
|
||||
|
||||
for index, doc in enumerate(docs, start=1):
|
||||
if stop_event is not None and stop_event.is_set():
|
||||
summary.stopped = True
|
||||
|
||||
@@ -197,6 +197,23 @@ def test_progress_callbacks(tmp_path):
|
||||
assert (2, 2) in events # progression finale atteinte
|
||||
|
||||
|
||||
def test_run_fails_fast_when_output_not_writable(tmp_path, monkeypatch):
|
||||
from gui_v6.processing_runner import ProcessingRunner, OutputNotWritableError
|
||||
src = tmp_path / "in"
|
||||
src.mkdir()
|
||||
(src / "a.txt").write_text("x", encoding="utf-8")
|
||||
out = tmp_path / "ro"
|
||||
out.mkdir()
|
||||
|
||||
def boom(*a, **k):
|
||||
raise PermissionError("read-only")
|
||||
|
||||
monkeypatch.setattr("gui_v6.processing_runner.Path.mkdir", boom)
|
||||
runner = ProcessingRunner(process_fn=lambda d, o: {})
|
||||
with pytest.raises(OutputNotWritableError):
|
||||
runner.run(src, out)
|
||||
|
||||
|
||||
def test_no_double_run(tmp_path):
|
||||
_touch(tmp_path / "a.pdf")
|
||||
started = threading.Event()
|
||||
|
||||
Reference in New Issue
Block a user