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 []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
class OutputNotWritableError(RuntimeError):
|
||||||
|
"""Le dossier de sortie n'est pas inscriptible (échec amont, message clair)."""
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DocResult:
|
class DocResult:
|
||||||
"""Détail anonymisé d'un document traité (pour la télémétrie d'usage).
|
"""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é.")
|
log("Aucun document supporté détecté.")
|
||||||
return summary
|
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):
|
for index, doc in enumerate(docs, start=1):
|
||||||
if stop_event is not None and stop_event.is_set():
|
if stop_event is not None and stop_event.is_set():
|
||||||
summary.stopped = True
|
summary.stopped = True
|
||||||
|
|||||||
@@ -197,6 +197,23 @@ def test_progress_callbacks(tmp_path):
|
|||||||
assert (2, 2) in events # progression finale atteinte
|
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):
|
def test_no_double_run(tmp_path):
|
||||||
_touch(tmp_path / "a.pdf")
|
_touch(tmp_path / "a.pdf")
|
||||||
started = threading.Event()
|
started = threading.Event()
|
||||||
|
|||||||
Reference in New Issue
Block a user