feat(inbox): accept one segmentation plan per document
This commit is contained in:
parent
a60312a5f3
commit
81c6a01c86
2 changed files with 175 additions and 17 deletions
|
|
@ -119,6 +119,7 @@ def run(
|
|||
tmp: Path,
|
||||
*,
|
||||
plan: SegmentationPlan | None,
|
||||
plans: dict[str, SegmentationPlan] | None = None,
|
||||
profile=SEGMENTED_V1,
|
||||
values: dict[str, str] | None = None,
|
||||
round_name: str = "round",
|
||||
|
|
@ -133,6 +134,7 @@ def run(
|
|||
profile=profile,
|
||||
root_frontmatter_values={"bundle_id": "b-1"} if values is None else values,
|
||||
segmentation=plan,
|
||||
segmentations=plans,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -499,3 +501,109 @@ def test_the_observed_extractor_version_is_not_the_proposers_own(tmp_path: Path)
|
|||
with pytest.raises(SegmentationError) as excinfo:
|
||||
observed_extractor_version("nothing-registers-this")
|
||||
assert excinfo.value.code == "segmentation_extractor_mismatch"
|
||||
|
||||
|
||||
# --- one plan per document, so a corpus can be run at all ------------------
|
||||
#
|
||||
# `process_inbox` took ONE plan, so a round over a heterogeneous corpus with
|
||||
# several segmented documents was not expressible: arm B cannot execute
|
||||
# without this. The single-plan form stays exactly as it was -- the mapping
|
||||
# arrives as a new keyword-only parameter with a default, so every existing
|
||||
# call site is source-compatible and no golden moves.
|
||||
#
|
||||
# The mapping is keyed by SOURCE FILENAME because that is what an operator
|
||||
# reads, but selection stays by CONTENT IDENTITY: `_plan_covering` matches on
|
||||
# `source_sha256`, so a renamed file still finds its plan and a plan pointed at
|
||||
# the wrong name still refuses rather than segmenting the wrong document.
|
||||
|
||||
OTHER = "A Innledning: hva dette dokumentet dekker.\nB Virkeomraade: hvilke anlegg det gjelder.\n"
|
||||
|
||||
OTHER_PATHS = ("annen/innledning.md", "annen/virkeomraade.md")
|
||||
|
||||
|
||||
def test_two_documents_with_two_plans_both_segment_in_one_run(tmp_path: Path) -> None:
|
||||
first = drop(tmp_path / "round", "n500.md", DOCUMENT)
|
||||
second = drop(tmp_path / "round", "n200.md", OTHER)
|
||||
run(
|
||||
tmp_path,
|
||||
plan=None,
|
||||
plans={
|
||||
"n500.md": build_plan(first.read_bytes(), DOCUMENT),
|
||||
"n200.md": build_plan(second.read_bytes(), OTHER, paths=OTHER_PATHS),
|
||||
},
|
||||
)
|
||||
found = concepts(tmp_path / "bundle")
|
||||
assert set(found) == set(PATHS) | set(OTHER_PATHS)
|
||||
|
||||
|
||||
def test_a_mapping_selects_by_content_not_by_the_name_it_is_keyed_under(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
"""The key is for the operator; the hash is what decides.
|
||||
|
||||
Keyed under a name no dropped file carries, the plan still finds the bytes
|
||||
it was adjudicated over. Anything else would make a rename silently produce
|
||||
a flat bundle.
|
||||
"""
|
||||
source = drop(tmp_path / "round", "n500.md", DOCUMENT)
|
||||
run(
|
||||
tmp_path,
|
||||
plan=None,
|
||||
plans={"whatever-i-called-it.md": build_plan(source.read_bytes(), DOCUMENT)},
|
||||
)
|
||||
assert set(concepts(tmp_path / "bundle")) == set(PATHS)
|
||||
|
||||
|
||||
def test_a_plan_in_the_mapping_that_matches_nothing_is_still_refused(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
"""The silent-skip refusal has to survive the wider input.
|
||||
|
||||
One plan matching is not enough: a corpus run where four of five plans
|
||||
matched would otherwise report success over four segmented documents and
|
||||
one flat one, which is exactly the silent zero this refusal exists for.
|
||||
"""
|
||||
source = drop(tmp_path / "round", "n500.md", DOCUMENT)
|
||||
with pytest.raises(SegmentationError) as excinfo:
|
||||
run(
|
||||
tmp_path,
|
||||
plan=None,
|
||||
plans={
|
||||
"n500.md": build_plan(source.read_bytes(), DOCUMENT),
|
||||
"ghost.md": build_plan(source.read_bytes(), DOCUMENT, source_sha256="0" * 64),
|
||||
},
|
||||
)
|
||||
assert excinfo.value.code == "segmentation_plan_unmatched"
|
||||
assert tree(tmp_path / "bundle") == {}
|
||||
|
||||
|
||||
def test_passing_both_forms_at_once_is_refused(tmp_path: Path) -> None:
|
||||
"""Two ways to say the same thing invite a silent disagreement."""
|
||||
source = drop(tmp_path / "round", "n500.md", DOCUMENT)
|
||||
plan = build_plan(source.read_bytes(), DOCUMENT)
|
||||
with pytest.raises(SegmentationError) as excinfo:
|
||||
run(tmp_path, plan=plan, plans={"n500.md": plan})
|
||||
assert excinfo.value.code == "segmentation_plan_invalid"
|
||||
assert tree(tmp_path / "bundle") == {}
|
||||
|
||||
|
||||
def test_two_plans_claiming_the_same_bytes_are_refused(tmp_path: Path) -> None:
|
||||
"""Which one would have segmented the document is not a coin toss."""
|
||||
source = drop(tmp_path / "round", "n500.md", DOCUMENT)
|
||||
with pytest.raises(SegmentationError) as excinfo:
|
||||
run(
|
||||
tmp_path,
|
||||
plan=None,
|
||||
plans={
|
||||
"a.md": build_plan(source.read_bytes(), DOCUMENT),
|
||||
"b.md": build_plan(source.read_bytes(), DOCUMENT, paths=OTHER_PATHS + PATHS[2:]),
|
||||
},
|
||||
)
|
||||
assert excinfo.value.code == "segmentation_plan_invalid"
|
||||
assert tree(tmp_path / "bundle") == {}
|
||||
|
||||
|
||||
def test_the_single_plan_form_is_unchanged(tmp_path: Path) -> None:
|
||||
source = drop(tmp_path / "round", "n500.md", DOCUMENT)
|
||||
run(tmp_path, plan=build_plan(source.read_bytes(), DOCUMENT))
|
||||
assert set(concepts(tmp_path / "bundle")) == set(PATHS)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue