Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions src/pydocvi/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,24 @@ def memory(self) -> Path:

@property
def manifests(self) -> Path:
return self.work / "manifests"
"""The committed manifests: the pin, the glossary, its history.

On the content repo, all of it. What lives here is either reviewed or
quoted, and the one spelling is so that a file cannot be written to one
directory and read from another.
"""
return self.content / "manifests"

@property
def upstream_pin(self) -> Path:
"""The commit every count in the project is quoted against.

Committed rather than kept under ``work`` because ``S01`` recounts the
corpus against it and ``S02`` needs the pinned upstream to say whether a
``msgid`` was edited. CI has no ``work`` directory and never will, so a
pin that lived there would mean the two checks that matter most are the
two that only ever run on the machine that already knows the answer.
"""
return self.manifests / "upstream.yaml"

@property
Expand Down Expand Up @@ -84,11 +98,11 @@ def glossary(self) -> Path:
committed and cited in every prompt. Run state is disposable and this is
not.
"""
return self.content / "manifests" / "glossary.yaml"
return self.manifests / "glossary.yaml"

@property
def candidates(self) -> Path:
return self.content / "manifests" / "glossary-candidates.yaml"
return self.manifests / "glossary-candidates.yaml"

@property
def proposal(self) -> Path:
Expand All @@ -98,12 +112,12 @@ def proposal(self) -> Path:
human pass happens here and neither overwriting the mining output nor
writing unreviewed rows into the contract is acceptable.
"""
return self.content / "manifests" / "glossary-proposed.yaml"
return self.manifests / "glossary-proposed.yaml"

@property
def versions(self) -> Path:
"""One file per past version, so ``glossary diff 6 7`` has two sides."""
return self.content / "manifests" / "glossary"
return self.manifests / "glossary"

@property
def glossary_markdown(self) -> Path:
Expand Down
18 changes: 18 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,24 @@
FAKE_KEY = "sk-" + "not-a-real-key-0123456789"


@pytest.fixture(autouse=True)
def _never_a_real_checkout(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
"""Point every path at ``tmp_path`` before any test runs.

Autouse, and belt and braces on top of the fixtures that already do this,
because the cost of getting it wrong is asymmetric. A test that forgets to
override ``PYDOCVI_CONTENT`` does not fail: it passes, having written a pin
or a glossary into a real checkout, and the next person finds it in ``git
status`` days later without knowing what put it there.
"""
for name, path in (
("UPSTREAM", tmp_path / "upstream"),
("CONTENT", tmp_path / "content"),
("WORK", tmp_path / "work"),
):
monkeypatch.setenv(f"PYDOCVI_{name}", str(path))


@pytest.fixture(scope="session")
def upstream() -> Path:
"""A local checkout of the upstream Transifex mirror."""
Expand Down
15 changes: 14 additions & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class TestSync:
def test_reports_the_counts_and_writes_the_pin(self, workspace: Path) -> None:
result = runner.invoke(app, ["sync"])
assert result.exit_code == ExitCode.OK
pin = (workspace / "work" / "manifests" / "upstream.yaml").read_text(encoding="utf-8")
pin = (workspace / "content" / "manifests" / "upstream.yaml").read_text(encoding="utf-8")
assert 'branch: "3.15"' in pin
assert "entries: 4" in pin
assert (workspace / "work" / "reports" / "sync.md").exists()
Expand Down Expand Up @@ -521,6 +521,19 @@ async def _stub(
class TestTranslate:
"""The one command that spends money, and the only one that writes the corpus."""

@pytest.fixture(autouse=True)
def _contract(self, workspace: Path) -> Path:
"""A glossary to quote in the prompt, in the scratch content repo.

Written here rather than left to whatever is on the machine. Until the
paths were pinned to ``tmp_path`` these tests read the real checkout's
glossary, which meant they passed here and nowhere else.
"""
target = workspace / "content" / "manifests" / "glossary.yaml"
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text('version: 1\nterms:\n - en: "iterable"\n vi: "khả lặp"\n', "utf-8")
return target

def test_a_dry_run_says_what_it_would_cost_and_queues_nothing(
self, workspace: Path, route_file: Path
) -> None:
Expand Down
Loading