161 lines
5.1 KiB
Python
161 lines
5.1 KiB
Python
from pathlib import Path
|
|||
|
|
import json
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
|
||
|
|
|
||
|
|
def _write_species(path: Path, taxa: list[tuple[str, str]]) -> None:
|
||
|
|
rows = [
|
||
|
|
"#taxon_id\tSTRING_type\tSTRING_name_compact\tofficial_name_NCBI\tdomain"
|
||
|
|
]
|
||
|
|
rows.extend(
|
||
|
|
f"{taxon_id}\tcore\t{name}\t{name}\tEukaryota"
|
||
|
|
for taxon_id, name in taxa
|
||
|
|
)
|
||
|
|
path.write_text("\n".join(rows) + "\n", encoding="utf-8")
|
||
|
|
|
||
|
|
|
||
|
|
def _write_tree(path: Path, rows: list[tuple[str, str, str, str]]) -> None:
|
||
|
|
content = ["#taxon_id\tparent_taxon_id\ttaxon_name\tis_STRING_species"]
|
||
|
|
content.extend("\t".join(row) for row in rows)
|
||
|
|
path.write_text("\n".join(content) + "\n", encoding="utf-8")
|
||
|
|
|
||
|
|
|
||
|
|
def test_snapshot_rejects_missing_parent_and_missing_required_nodes(tmp_path: Path) -> None:
|
||
|
|
from scripts.prepare_string_species_snapshot import validate_snapshot
|
||
|
|
|
||
|
|
species = tmp_path / "species.txt"
|
||
|
|
tree = tmp_path / "tree.txt"
|
||
|
|
_write_species(species, [("3702", "Arabidopsis thaliana")])
|
||
|
|
_write_tree(
|
||
|
|
tree,
|
||
|
|
[
|
||
|
|
("1", "1", "root", "f"),
|
||
|
|
("3702", "999999", "Arabidopsis thaliana", "t"),
|
||
|
|
],
|
||
|
|
)
|
||
|
|
|
||
|
|
with pytest.raises(ValueError, match="parent|33090|3702"):
|
||
|
|
validate_snapshot(species, tree)
|
||
|
|
|
||
|
|
|
||
|
|
def test_snapshot_accepts_official_root_self_loop_and_strict_tf(tmp_path: Path) -> None:
|
||
|
|
from scripts.prepare_string_species_snapshot import validate_snapshot
|
||
|
|
|
||
|
|
species = tmp_path / "species.txt"
|
||
|
|
tree = tmp_path / "tree.txt"
|
||
|
|
_write_species(species, [("3702", "Arabidopsis thaliana")])
|
||
|
|
_write_tree(
|
||
|
|
tree,
|
||
|
|
[
|
||
|
|
("1", "1", "root", "f"),
|
||
|
|
("33090", "1", "Viridiplantae", "f"),
|
||
|
|
("3702", "33090", "Arabidopsis thaliana", "t"),
|
||
|
|
],
|
||
|
|
)
|
||
|
|
|
||
|
|
result = validate_snapshot(species, tree)
|
||
|
|
|
||
|
|
assert result["viridiplantae_taxon_id"] == "33090"
|
||
|
|
assert result["arabidopsis_taxon_id"] == "3702"
|
||
|
|
assert result["tree_node_count"] == 3
|
||
|
|
assert result["string_species_count"] == 1
|
||
|
|
|
||
|
|
|
||
|
|
def test_snapshot_rejects_non_root_cycle(tmp_path: Path) -> None:
|
||
|
|
from scripts.prepare_string_species_snapshot import validate_snapshot
|
||
|
|
|
||
|
|
species = tmp_path / "species.txt"
|
||
|
|
tree = tmp_path / "tree.txt"
|
||
|
|
_write_species(species, [("3702", "Arabidopsis thaliana")])
|
||
|
|
_write_tree(
|
||
|
|
tree,
|
||
|
|
[
|
||
|
|
("1", "1", "root", "f"),
|
||
|
|
("33090", "3702", "Viridiplantae", "f"),
|
||
|
|
("3702", "33090", "Arabidopsis thaliana", "t"),
|
||
|
|
],
|
||
|
|
)
|
||
|
|
|
||
|
|
with pytest.raises(ValueError, match="cycle"):
|
||
|
|
validate_snapshot(species, tree)
|
||
|
|
|
||
|
|
|
||
|
|
def test_snapshot_rejects_registry_tree_string_species_mismatch(tmp_path: Path) -> None:
|
||
|
|
from scripts.prepare_string_species_snapshot import validate_snapshot
|
||
|
|
|
||
|
|
species = tmp_path / "species.txt"
|
||
|
|
tree = tmp_path / "tree.txt"
|
||
|
|
_write_species(
|
||
|
|
species,
|
||
|
|
[("3702", "Arabidopsis thaliana"), ("3708", "Brassica napus")],
|
||
|
|
)
|
||
|
|
_write_tree(
|
||
|
|
tree,
|
||
|
|
[
|
||
|
|
("1", "1", "root", "f"),
|
||
|
|
("33090", "1", "Viridiplantae", "f"),
|
||
|
|
("3702", "33090", "Arabidopsis thaliana", "t"),
|
||
|
|
("3708", "33090", "Brassica napus", "f"),
|
||
|
|
],
|
||
|
|
)
|
||
|
|
|
||
|
|
with pytest.raises(ValueError, match="registry|STRING species"):
|
||
|
|
validate_snapshot(species, tree)
|
||
|
|
|
||
|
|
|
||
|
|
def test_prepare_snapshot_writes_validated_local_files_and_manifest(
|
||
|
|
tmp_path: Path,
|
||
|
|
) -> None:
|
||
|
|
import scripts.prepare_string_species_snapshot as snapshot_module
|
||
|
|
|
||
|
|
sources = tmp_path / "sources"
|
||
|
|
sources.mkdir()
|
||
|
|
species = sources / "species.v12.0.txt"
|
||
|
|
tree = sources / "species.tree.v12.0.txt"
|
||
|
|
_write_species(species, [("3702", "Arabidopsis thaliana")])
|
||
|
|
_write_tree(
|
||
|
|
tree,
|
||
|
|
[
|
||
|
|
("1", "1", "root", "f"),
|
||
|
|
("33090", "1", "Viridiplantae", "f"),
|
||
|
|
("3702", "33090", "Arabidopsis thaliana", "t"),
|
||
|
|
],
|
||
|
|
)
|
||
|
|
destination = tmp_path / "snapshot"
|
||
|
|
manifest = snapshot_module.prepare_snapshot(
|
||
|
|
destination,
|
||
|
|
source_directory=sources,
|
||
|
|
)
|
||
|
|
|
||
|
|
saved = json.loads((destination / "source_manifest.json").read_text(encoding="utf-8"))
|
||
|
|
assert saved == manifest
|
||
|
|
assert saved["string_version"] == "12.0"
|
||
|
|
assert saved["transfer_mode"] == "local_files"
|
||
|
|
assert saved["snapshot_id"]
|
||
|
|
assert saved["validation"]["string_species_count"] == 1
|
||
|
|
for name in snapshot_module.SOURCE_URLS:
|
||
|
|
assert (destination / name).is_file()
|
||
|
|
assert saved["files"][name]["size"] > 0
|
||
|
|
assert len(saved["files"][name]["sha256"]) == 64
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.mark.parametrize("value", ["false", "0", "yes", "T"])
|
||
|
|
def test_snapshot_rejects_non_official_boolean_tokens(tmp_path: Path, value: str) -> None:
|
||
|
|
from scripts.prepare_string_species_snapshot import validate_snapshot
|
||
|
|
|
||
|
|
species = tmp_path / "species.txt"
|
||
|
|
tree = tmp_path / "tree.txt"
|
||
|
|
_write_species(species, [("3702", "Arabidopsis thaliana")])
|
||
|
|
_write_tree(
|
||
|
|
tree,
|
||
|
|
[
|
||
|
|
("1", "1", "root", "f"),
|
||
|
|
("33090", "1", "Viridiplantae", "f"),
|
||
|
|
("3702", "33090", "Arabidopsis thaliana", value),
|
||
|
|
],
|
||
|
|
)
|
||
|
|
|
||
|
|
with pytest.raises(ValueError, match="is_STRING_species"):
|
||
|
|
validate_snapshot(species, tree)
|