Files
periscope/tests/test_periscope_taxonomy_rewrite.py
T
michele fe89851c10 Rewrite taxonomy loader; JSON path via repo_paths (2.48.0).
TAXONOMY_DIR is taxonomy_dir() so src reads dependency/taxonomy until a src tree exists. Inherited taxonomy.py stays on disk. Changelog covers models, parsers, and taxonomy.
2026-09-20 18:41:12 +02:00

97 lines
3.5 KiB
Python

"""Taxonomy loader is src; JSON is located via repo_paths (not Path(__file__))."""
from __future__ import annotations
from pathlib import Path
import pytest
import backend.periscopex.taxonomy as taxonomy
from backend.periscopex.taxonomy import (
SIMPLE_TYPES,
add_subtype,
get_subtype,
list_subtypes,
load_subtypes,
type_for_ref,
validate_subtype,
)
from backend.repo_paths import taxonomy_dir
def test_taxonomy_module_is_src():
path = Path(taxonomy.__file__).resolve()
assert path.parts[-5:] == ("periscope", "src", "backend", "periscopex", "taxonomy.py")
text = path.read_text(encoding="utf-8")
assert "from backend.repo_paths import taxonomy_dir" in text
assert "TAXONOMY_DIR = taxonomy_dir()" in text
assert "Native Periscope overlay" not in text
def test_taxonomy_dir_points_at_dependency_json():
d = taxonomy_dir()
assert d.parts[-2:] == ("dependency", "taxonomy")
assert (d / "ic.json").is_file()
assert taxonomy.TAXONOMY_DIR == d
assert not (Path(taxonomy.__file__).resolve().parent.parent.parent / "taxonomy" / "ic.json").is_file()
def test_emmaforo_ref_prefixes():
"""Emmaforo-style designators: MCU, USB, LEDs, passives — not layout primitives."""
assert type_for_ref("U1") == "ic"
assert type_for_ref("U3") == "ic"
assert type_for_ref("LED1") == "discrete"
assert type_for_ref("L1") == "passive"
assert type_for_ref("C12") == "passive"
assert type_for_ref("R10") == "passive"
assert type_for_ref("J1") == "connector"
assert type_for_ref("Y1") == "crystal"
assert type_for_ref("X1") == "crystal"
assert type_for_ref("TP1") == "test_point"
assert type_for_ref("FB1") == "passive"
assert type_for_ref("SW1") == "switch"
def test_emmaforo_ic_json_has_mcu_and_interface_keys():
ic = load_subtypes("ic")
assert "ic.mcu" in ic
assert ic["ic.mcu"]["example_mpn"] == "MSPM0G3507SPTR"
assert get_subtype("ic.interface.usb_uart_bridge") is not None
assert "ic.mcu" in list_subtypes("ic")
def test_validate_subtype_and_unknown_top():
assert validate_subtype("IC.MCU") == "ic.mcu"
assert validate_subtype("passive.resistor") == "passive.resistor"
with pytest.raises(ValueError, match="Unknown top-level"):
validate_subtype("notatype.foo")
with pytest.raises(ValueError, match="Invalid component_subtype"):
validate_subtype("ic..mcu")
assert type_for_ref("9") is None
assert type_for_ref("") is None
assert type_for_ref("RN4") is None # RN is not a taxonomy prefix (graph still maps RN→resistor)
def test_layout_primitives_are_not_taxonomy_types():
"""Pad≠Via≠Track≠Zone: layout kinds are not component_subtype tops."""
for bogus in ("pad.smd", "via.through", "track.microstrip", "zone.copper"):
with pytest.raises(ValueError, match="Unknown top-level"):
validate_subtype(bogus)
assert type_for_ref("VIA1") is None
assert type_for_ref("PAD1") is None
def test_simple_types_exclude_ic_and_passive():
assert "ic" not in SIMPLE_TYPES
assert "passive" not in SIMPLE_TYPES
assert "connector" in SIMPLE_TYPES
def test_add_subtype_writes_only_given_directory(tmp_path: Path):
add_subtype("ic.sensor.humidity", "Humidity sensor IC", directory=tmp_path)
written = tmp_path / "ic.json"
assert written.is_file()
assert "ic.sensor.humidity" in written.read_text(encoding="utf-8")
live = (taxonomy_dir() / "ic.json").read_text(encoding="utf-8")
assert "ic.sensor.humidity" not in live