Harden regional dataset split validation
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s

This commit is contained in:
Jens
2026-07-30 01:27:05 +02:00
parent 410959cacd
commit 3e66c78694
2 changed files with 49 additions and 6 deletions
+37 -6
View File
@@ -46,11 +46,17 @@ def build(
if sample is None:
unknown.append(tile["sample_slug"])
continue
split = str(tile.get("split") or sample.get("split") or "")
if split in PROTECTED_SPLITS:
tile_split = str(tile.get("split") or "")
manifest_split = str(sample.get("split") or "")
if tile_split in PROTECTED_SPLITS or manifest_split in PROTECTED_SPLITS:
protected.append(tile["sample_slug"])
continue
if sample.get("region") == region and split in {"train", "val"}:
if tile_split != manifest_split:
raise ValueError(
f"tile/manifest split mismatch for {tile['sample_slug']}: "
f"{tile_split!r} != {manifest_split!r}"
)
if sample.get("region") == region and tile_split in {"train", "val"}:
selected.append((tile, sample))
if unknown:
raise ValueError(f"summary references unknown samples: {sorted(set(unknown))}")
@@ -98,6 +104,31 @@ def build(
return train, val, evidence
def select_paths(
summary: dict[str, Any], manifest: dict[str, Any], region: str
) -> tuple[list[str], list[str]]:
"""Backward-compatible unweighted regional selection API."""
samples = {item["sample_slug"]: item for item in manifest["samples"]}
compatible_summary = {
**summary,
"tiles": [
tile
for tile in summary["tiles"]
if tile["sample_slug"] in samples
and samples[tile["sample_slug"]].get("split") in {"train", "val"}
],
}
train, val, _evidence = build(
summary=compatible_summary,
manifest=manifest,
region=region,
priority_contexts=set(),
priority_repeat=1,
negative_repeat=1,
)
return sorted(train), sorted(val)
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--summary", type=Path, required=True)
@@ -139,9 +170,9 @@ def main() -> int:
"validation_sha256": sha256(val_path),
"dataset_yaml": str(yaml_path),
})
(args.output_dir / "regional-dataset-evidence.json").write_text(
json.dumps(evidence, indent=2), encoding="utf-8"
)
encoded_evidence = json.dumps(evidence, indent=2)
(args.output_dir / "regional-dataset-evidence.json").write_text(encoded_evidence, encoding="utf-8")
(args.output_dir / "regional-dataset.json").write_text(encoded_evidence, encoding="utf-8")
print(json.dumps(evidence, indent=2))
return 0
+12
View File
@@ -45,3 +45,15 @@ def test_regional_dataset_rejects_protected_tiles() -> None:
summary=summary, manifest=manifest, region="flanders",
priority_contexts=set(), priority_repeat=1, negative_repeat=1,
)
def test_regional_dataset_rejects_manifest_protection_hidden_by_tile_split() -> None:
manifest = {"samples": [
{"sample_slug": "f-cal", "region": "flanders", "split": "calibration", "context": "ribbon"},
]}
summary = {"tiles": [{"sample_slug": "f-cal", "split": "train", "image_path": "/cal.png"}]}
with pytest.raises(ValueError, match="protected"):
module.build(
summary=summary, manifest=manifest, region="flanders",
priority_contexts=set(), priority_repeat=1, negative_repeat=1,
)