"""Packaging contract: a PEP 561 typed package with exactly one dependency. Consumers run mypy --strict against the inline annotations; without the py.typed marker mypy degrades every imported symbol to Any. """ from __future__ import annotations import re from pathlib import Path import pytest import llm_ingestion_okf PROJECT_ROOT = Path(__file__).resolve().parents[1] def test_package_ships_py_typed_marker() -> None: package_dir = Path(llm_ingestion_okf.__file__).parent assert (package_dir / "py.typed").is_file() def test_the_only_runtime_dependency_is_the_security_boundary() -> None: """The stdlib-only rule, enforced rather than asserted in prose. One dependency is permitted — the guard — because security is the one thing this library must not implement. Everything else stays stdlib, so a consumer vendoring this package takes on no transitive surface. The version RANGE is the pin: it resolves against a package index, and is satisfied by the git+https tag install until that index exists. """ tomllib = pytest.importorskip("tomllib") # stdlib from 3.11; the pin holds on 3.10 too pyproject = tomllib.loads((PROJECT_ROOT / "pyproject.toml").read_text(encoding="utf-8")) assert pyproject["project"]["dependencies"] == ["llm-ingestion-guard>=1.2,<2.0"] def test_the_extract_extra_pins_exactly_what_it_ships() -> None: """`project.dependencies` was pinned; the extra's contents were not. The single-dependency test above reads `project.dependencies` only, so a second package could be added to `[extract]` and no test would notice -- and an extra is exactly where an unexamined transitive tree arrives. The extra is opt-in, but "opt-in" is a statement about who installs it, not about whether its contents were chosen. Both entries are pins with a stated reason, not conveniences: `pdfplumber` for the pdf reader, `pypandoc-binary` because the converter BINARY travels with the wheel. Vendoring the binary is what makes the output reproducible -- see the resolver, which refuses any version but the pinned one. """ tomllib = pytest.importorskip("tomllib") pyproject = tomllib.loads((PROJECT_ROOT / "pyproject.toml").read_text(encoding="utf-8")) assert pyproject["project"]["optional-dependencies"]["extract"] == [ "pdfplumber>=0.11.10,<0.12", "pypandoc-binary==1.17", ] def test_the_ocr_group_is_pinned_and_is_not_a_runtime_dependency() -> None: """An inference runtime is the last thing that may arrive by accident. Two claims, and the second is the one worth a test: the group's contents are pinned like the extra's, AND none of them appears in `project.dependencies`. The single-dependency test above would already catch that, but it reads the list and this reads the names -- so a future entry named differently still fails here. """ tomllib = pytest.importorskip("tomllib") pyproject = tomllib.loads((PROJECT_ROOT / "pyproject.toml").read_text(encoding="utf-8")) assert pyproject["project"]["optional-dependencies"]["ocr"] == [ "rapidocr>=3.9,<4", "onnxruntime>=1.20,<2", "pypdfium2>=4,<6", ] runtime = " ".join(pyproject["project"]["dependencies"]) for package in ("rapidocr", "onnxruntime", "pypdfium2"): assert package not in runtime def test_the_declared_version_agrees_with_the_packaged_one() -> None: """The two places a version is written must not drift apart. The install channel is a direct git reference, so a consumer pins a TAG while pip records `project.version`. Nothing in the run path reads `__version__` — which is exactly why a stale one survives a green suite, and why a consumer installing at a pre-release tag can end up with a package that reports the previous release. This is the only machine check on that; the tag name itself remains a human step. """ tomllib = pytest.importorskip("tomllib") pyproject = tomllib.loads((PROJECT_ROOT / "pyproject.toml").read_text(encoding="utf-8")) assert llm_ingestion_okf.__version__ == pyproject["project"]["version"] def test_operational_tooling_stays_out_of_the_wheel() -> None: """`tools/` is ours, not the consumer's. The upstream watch drives git and the coord mailbox — machinery that is meaningful on this machine and meaningless in a consumer's site-packages. It lives outside `src/` so it cannot ship, and this test is what makes that a promise instead of an accident of the current build config. """ tomllib = pytest.importorskip("tomllib") pyproject = tomllib.loads((PROJECT_ROOT / "pyproject.toml").read_text(encoding="utf-8")) packages = pyproject["tool"]["hatch"]["build"]["targets"]["wheel"]["packages"] assert packages == ["src/llm_ingestion_okf"] assert (PROJECT_ROOT / "tools" / "okf_watch.py").is_file(), "the test must have a subject" def test_every_place_that_publishes_a_version_names_the_packaged_one() -> None: """A tag is a promise about bytes, and nine places here repeat it. `test_the_declared_version_agrees_with_the_packaged_one` binds two of them. An independent review of 0.10.1 found the other seven unbound and all of them stale: four README install lines telling a consumer to install `@v0.10.0`, two prose lines about what that tag declares, the "current tag" entry, and a CHANGELOG whose 0.10.1 content sat under `[Unreleased]`. A `v0.10.1` tag cut from that tree would have shipped a package reporting 0.10.0 and a README installing the release before it -- and the suite was green, because nothing looked. The guard tag is bound the same way and for the same reason: the README tells a plain-pip user to install a specific guard tag first, and that instruction is wrong the moment `[tool.uv.sources]` moves without it. """ tomllib = pytest.importorskip("tomllib") pyproject = tomllib.loads((PROJECT_ROOT / "pyproject.toml").read_text(encoding="utf-8")) version = llm_ingestion_okf.__version__ guard = pyproject["tool"]["uv"]["sources"]["llm-ingestion-guard"]["tag"] readme = (PROJECT_ROOT / "README.md").read_text(encoding="utf-8") install = re.findall(r"llm-ingestion-okf\.git@(v[0-9][^\"\s]*)", readme) assert install, "the test must have a subject" assert set(install) == {f"v{version}"}, f"install lines name {sorted(set(install))}" guard_lines = re.findall(r"llm-ingestion-pipeline-security\.git@(v[0-9][^\"\s]*)", readme) assert guard_lines, "the test must have a subject" assert set(guard_lines) == {guard}, f"guard install lines name {sorted(set(guard_lines))}" current = re.search(r"^- `(v[^`]+)` — the current tag", readme, re.MULTILINE) assert current is not None, "the test must have a subject" assert current.group(1) == f"v{version}" # The prose between "## Install in detail" and the history list explains # what THIS tag declares and which guard tag it is paired to. A stale # number there is an instruction that fails, not a historical note. detail = readme.split("## Install in detail", 1)[1].split("### Earlier tags, as history", 1)[0] named = set(re.findall(r"`(v\d+\.\d+\.\d+[^`]*)`", detail)) assert named, "the test must have a subject" assert named <= {f"v{version}", guard}, f"stale tags in the install prose: {sorted(named)}" # The tenth place, which uv rewrites on its own and which is therefore the # easiest of all to commit stale. lock = (PROJECT_ROOT / "uv.lock").read_text(encoding="utf-8") locked = re.search(r'name = "llm-ingestion-okf"\nversion = "([^"]+)"', lock) assert locked is not None, "the test must have a subject" assert locked.group(1) == version def test_the_changelog_heads_with_the_packaged_version() -> None: """The release notes for the version being shipped are not `[Unreleased]`. `[Unreleased]` is the right place for work in flight and the wrong place for the content of a tag someone is about to cut: a reader arriving at `v0.10.1` would find its own entry under a heading saying it had not been released. Found by an independent review of 0.10.1. """ changelog = (PROJECT_ROOT / "CHANGELOG.md").read_text(encoding="utf-8") heading = re.search(r"^## \[([^\]]+)\](?: — (\d{4}-\d{2}-\d{2}))?$", changelog, re.MULTILINE) assert heading is not None, "the test must have a subject" assert heading.group(1) == llm_ingestion_okf.__version__, ( f"the changelog heads with [{heading.group(1)}], the package is " f"{llm_ingestion_okf.__version__}" ) assert heading.group(2), "a released section carries its date"