fix: complete final OCR batch item normally

This commit is contained in:
LLLin000 2026-07-14 18:32:48 +08:00
parent 3a516add86
commit e556c8bab0
2 changed files with 76 additions and 3 deletions

View file

@ -342,7 +342,8 @@ def _run_ocr_redo(vault: Path, keys: list[str] | None = None, dry_run: bool = Fa
if failed_keys:
print(f"Redo OCR pending/failed={len(failed_keys)}: {', '.join(failed_keys)}", flush=True)
if batch and _is_stopped():
_real_stop = batch and _is_stopped() and _current[0] < total
if _real_stop:
print(f"Batch stopped (SIGINT) after {_current[0]} paper(s).")
if batch:
@ -350,7 +351,7 @@ def _run_ocr_redo(vault: Path, keys: list[str] | None = None, dry_run: bool = Fa
finally:
_restore_signal()
if batch and _is_stopped():
if batch and _is_stopped() and _current[0] < total:
return 130
return worker_exit_code
@ -591,7 +592,9 @@ def _run_ocr_rebuild(
print(f"OCR_REBUILD_DONE", flush=True)
finally:
_restore_signal()
return 0 if not _is_stopped() else 130
_real_stop = batch and _is_stopped() and _count < total
return 130 if _real_stop else 0

View file

@ -500,6 +500,76 @@ class TestCooperativeStop:
restore()
def test_redo_stop_flag_but_all_complete_returns_normal(self, capsys, monkeypatch, tmp_path):
"""Stop flag set after all papers done: normal exit, no 'stopped' message."""
_mock_run_ocr(monkeypatch)
_mock_validate_ocr_meta(monkeypatch)
vault = _make_minimal_vault(tmp_path)
_add_literature_note(vault, "KEY00001")
_add_literature_note(vault, "KEY00002")
# Mock _make_cooperative_stop; _StopChecker always returns False
# (so all papers process), but _is_stopped returns True after processing
# to simulate late SIGINT after all progress reached total
class _LateStop:
"""Return True only after being checked at least 3 times (past all papers)."""
def __init__(self):
self.count = 0
def __call__(self):
self.count += 1
return self.count >= 10 # always False during processing
checker = _LateStop()
def _fake_make():
return (checker, lambda: None)
monkeypatch.setattr(
"paperforge.commands.ocr._make_cooperative_stop",
_fake_make,
)
from paperforge.commands.ocr import _run_ocr_redo
rc = _run_ocr_redo(vault, keys=["KEY00001", "KEY00002"])
assert rc == 0, f"Expected 0 (all done), got {rc}"
captured = capsys.readouterr().out
assert "Batch stopped" not in captured
assert "OCR_REDO_DONE" in captured
def test_rebuild_stop_flag_but_all_complete_returns_normal(self, capsys, monkeypatch, tmp_path):
"""Rebuild stop flag after all done: normal exit, no 'stopped'."""
vault = _make_minimal_vault(tmp_path)
keys = ["KEY00001", "KEY00002"]
from tests.cli.test_ocr_progress_contracts import TestOcrRebuildProgressTokens
helper = TestOcrRebuildProgressTokens()
helper._setup_mock_selection_and_worker(vault, keys, monkeypatch)
# Late stop as above
class _LateStop:
def __init__(self):
self.count = 0
def __call__(self):
self.count += 1
return self.count >= 10
checker = _LateStop()
def _fake_make():
return (checker, lambda: None)
monkeypatch.setattr(
"paperforge.commands.ocr._make_cooperative_stop",
_fake_make,
)
from paperforge.commands.ocr import _run_ocr_rebuild
rc = _run_ocr_rebuild(vault, keys=keys)
assert rc == 0, f"Expected 0 (all done), got {rc}"
captured = capsys.readouterr().out
assert "OCR_REBUILD_DONE" in captured
assert "Batch stopped" not in captured
class TestOcrListNeedsRebuild:
"""OCR list --json includes needs_derived_rebuild."""