Files
wehub-resource-sync e4dcfc49aa
Tests / Import Check (Python 3.13) (push) Has been cancelled
Tests / Import Check (Python 3.14) (push) Has been cancelled
Tests / Python Tests (Python 3.11) (push) Has been cancelled
Tests / Python Tests (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.14) (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled
Tests / Lint and Format (push) Has been cancelled
Tests / Web Node Tests (push) Has been cancelled
Tests / Import Check (Python 3.11) (push) Has been cancelled
Tests / Import Check (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.13) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:00:43 +08:00

117 lines
3.8 KiB
Python

from __future__ import annotations
from pathlib import Path
import pytest
from deeptutor.services.parsing import base, signature
import deeptutor.services.parsing.service as svc_mod
from deeptutor.services.parsing.service import ParseService
from deeptutor.services.parsing.types import ParserError
class _FakeParser:
name = "fake"
needs_local_models = False
def __init__(self, *, ready: bool = True, sig: str = "v1", calls: list | None = None) -> None:
self._ready = ready
self._sig = sig
self.calls = calls if calls is not None else []
@classmethod
def is_available(cls) -> bool:
return True
def resolve_config(self):
return {}
def supported_formats(self):
return frozenset({".pdf"})
def signature(self, _config):
return signature.ParserSignature.build("fake", "1", {"v": self._sig})
def is_ready(self, _config):
return base.ReadinessReport(ready=self._ready, reason="gate", message="not ready")
def parse(self, source_path: Path, workdir: Path, *, config, on_output=None) -> None:
self.calls.append(source_path)
(workdir / f"{source_path.stem}.md").write_text("# md", encoding="utf-8")
def _use(monkeypatch, parser) -> None:
monkeypatch.setattr(svc_mod, "get_parser", lambda name: parser)
def _pdf(tmp_path: Path, data: bytes = b"%PDF data", name: str = "x.pdf") -> Path:
path = tmp_path / name
path.write_bytes(data)
return path
def test_cache_hit_skips_engine(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
parser = _FakeParser()
_use(monkeypatch, parser)
pdf = _pdf(tmp_path)
service = ParseService(cache_root=tmp_path / "cache")
first = service.parse(pdf, engine="fake")
second = service.parse(pdf, engine="fake")
assert len(parser.calls) == 1 # engine ran once; second call hit cache
assert first.markdown == "# md"
assert first.blocks is None
assert first.workdir == second.workdir
def test_signature_change_busts_cache(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
pdf = _pdf(tmp_path)
service = ParseService(cache_root=tmp_path / "cache")
p1 = _FakeParser(sig="v1")
_use(monkeypatch, p1)
service.parse(pdf, engine="fake")
p2 = _FakeParser(sig="v2")
_use(monkeypatch, p2)
service.parse(pdf, engine="fake")
assert len(p1.calls) == 1 and len(p2.calls) == 1 # different signature → re-parse
def test_same_bytes_different_name_share_cache(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
parser = _FakeParser()
_use(monkeypatch, parser)
service = ParseService(cache_root=tmp_path / "cache")
service.parse(_pdf(tmp_path, b"identical", "first.pdf"), engine="fake")
service.parse(_pdf(tmp_path, b"identical", "second.pdf"), engine="fake")
assert len(parser.calls) == 1
def test_not_ready_raises_before_parse(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
parser = _FakeParser(ready=False)
_use(monkeypatch, parser)
service = ParseService(cache_root=tmp_path / "cache")
with pytest.raises(ParserError, match="not ready"):
service.parse(_pdf(tmp_path), engine="fake")
assert parser.calls == []
def test_unsupported_format_raises(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
parser = _FakeParser()
_use(monkeypatch, parser)
service = ParseService(cache_root=tmp_path / "cache")
with pytest.raises(ParserError, match="support"):
service.parse(_pdf(tmp_path, b"data", "notes.txt"), engine="fake")
def test_missing_file_raises(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
_use(monkeypatch, _FakeParser())
service = ParseService(cache_root=tmp_path / "cache")
with pytest.raises(ParserError):
service.parse(tmp_path / "ghost.pdf", engine="fake")