Split native Periscope (periscope/src) from inherited PinScope (periscope/dependency).
Keep validate.py and the finding engine as-is. AGPL LICENSE stays at the repo root. Docker overlays dependency then src. Do not delete the inherited tree.
This commit is contained in:
+8
-2
@@ -10,8 +10,14 @@ import pytest
|
||||
# Ensure the repo root is on sys.path so `import backend.*` works whether
|
||||
# pytest is invoked from the repo root or a subdirectory.
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
if str(REPO_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(REPO_ROOT))
|
||||
for p in (
|
||||
REPO_ROOT / "periscope" / "dependency",
|
||||
REPO_ROOT / "periscope" / "src",
|
||||
REPO_ROOT,
|
||||
):
|
||||
s = str(p)
|
||||
if p.is_dir() and s not in sys.path:
|
||||
sys.path.insert(0, s)
|
||||
|
||||
from backend.vendor_path import ensure_impedancefinder
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
"""Shared fixture paths after the periscope/src vs periscope/dependency split."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
SIMPLE_PROJECT = REPO_ROOT / "periscope" / "dependency" / "simple_project"
|
||||
TAXONOMY = REPO_ROOT / "periscope" / "dependency" / "taxonomy"
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from tests.paths import SIMPLE_PROJECT
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -14,9 +14,6 @@ from backend.services.cost_estimator import (
|
||||
)
|
||||
|
||||
|
||||
SIMPLE_PROJECT = Path(__file__).resolve().parents[1] / "simple_project"
|
||||
|
||||
|
||||
def _seed_project(storage, user_id: str, project_id: str) -> None:
|
||||
"""Create a minimal project with the simple_project BOM uploaded."""
|
||||
proj_svc.create_project(storage, user_id, "Fixture")
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from tests.paths import SIMPLE_PROJECT, TAXONOMY
|
||||
|
||||
from backend.periscopex.crystal_cl_check import check_crystal_cl
|
||||
from backend.periscopex.models import (
|
||||
Component,
|
||||
@@ -92,6 +94,6 @@ def test_with_stray_mismatch_warns():
|
||||
def test_simple_project_without_cl_silent():
|
||||
from pathlib import Path
|
||||
from backend.periscopex.models import DesignGraph
|
||||
path = Path(__file__).resolve().parents[1] / "simple_project" / "design_graph.json"
|
||||
path = SIMPLE_PROJECT / "design_graph.json"
|
||||
g = DesignGraph.model_validate_json(path.read_text())
|
||||
assert check_crystal_cl(g) == []
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from tests.paths import SIMPLE_PROJECT, TAXONOMY
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
@@ -19,7 +21,7 @@ from backend.periscopex.validation_tools import (
|
||||
from backend.services.llm.types import PdfBlock
|
||||
from backend.services.validation import _signal_neighbors
|
||||
|
||||
GRAPH = Path(__file__).resolve().parent.parent / "simple_project" / "design_graph.json"
|
||||
GRAPH = SIMPLE_PROJECT / "design_graph.json"
|
||||
IC_MPNS = {
|
||||
"U1": "SPX3819M5-L-3-3/TR",
|
||||
"U2": "CH340E",
|
||||
|
||||
@@ -8,6 +8,8 @@ Unverified quotes are citation misses, not hits.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from tests.paths import SIMPLE_PROJECT, TAXONOMY
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from backend.periscopex.eval_report import (
|
||||
@@ -80,7 +82,7 @@ def test_citation_rate_ignores_deterministic_and_counts_unverified():
|
||||
|
||||
|
||||
def test_simple_project_eval_matches_committed_golden():
|
||||
root = Path(__file__).resolve().parents[1] / "simple_project"
|
||||
root = SIMPLE_PROJECT
|
||||
scores = eval_simple_project(root)
|
||||
assert scores.graph_ok, scores.graph_errors
|
||||
assert scores.precision == 1.0
|
||||
@@ -94,7 +96,7 @@ def test_simple_project_eval_rejects_truncated_graph(tmp_path: Path):
|
||||
import json
|
||||
import shutil
|
||||
|
||||
src = Path(__file__).resolve().parents[1] / "simple_project"
|
||||
src = SIMPLE_PROJECT
|
||||
dest = tmp_path / "simple_project"
|
||||
shutil.copytree(src, dest)
|
||||
g = json.loads((dest / "design_graph.json").read_text())
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from tests.paths import SIMPLE_PROJECT, TAXONOMY
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from backend.periscopex.functional_groups import build_functional_groups
|
||||
from backend.periscopex.models import DesignGraph
|
||||
|
||||
SIMPLE = Path(__file__).resolve().parents[1] / "simple_project"
|
||||
SIMPLE = SIMPLE_PROJECT
|
||||
|
||||
|
||||
def _graph() -> DesignGraph:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from tests.paths import SIMPLE_PROJECT, TAXONOMY
|
||||
from backend.services.passive_from_distributor import specs_from_distributor
|
||||
|
||||
|
||||
@@ -91,7 +92,7 @@ def test_auto_resolve_skips_llm_when_catalog_parses(monkeypatch):
|
||||
raise AssertionError("LLM must not run")
|
||||
|
||||
monkeypatch.setattr("backend.services.extraction.call_with_fallback", boom)
|
||||
tax = Path(__file__).resolve().parents[1] / "taxonomy"
|
||||
tax = TAXONOMY
|
||||
model = asyncio.run(
|
||||
auto_resolve_specs(
|
||||
mpn="CL21B225KPFNNNE",
|
||||
@@ -115,7 +116,7 @@ def test_auto_resolve_use_llm_false_on_ferrite(monkeypatch):
|
||||
raise AssertionError("LLM must not run")
|
||||
|
||||
monkeypatch.setattr("backend.services.extraction.call_with_fallback", boom)
|
||||
tax = Path(__file__).resolve().parents[1] / "taxonomy"
|
||||
tax = TAXONOMY
|
||||
model = asyncio.run(
|
||||
auto_resolve_specs(
|
||||
mpn="BLM18PG121SN1D",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from tests.paths import SIMPLE_PROJECT, TAXONOMY
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
@@ -57,7 +58,7 @@ def test_resolve_from_value_skips_llm_when_parseable(monkeypatch):
|
||||
raise AssertionError("LLM must not run")
|
||||
|
||||
monkeypatch.setattr("backend.services.extraction.call_with_fallback", boom)
|
||||
tax = Path(__file__).resolve().parents[1] / "taxonomy"
|
||||
tax = TAXONOMY
|
||||
model = asyncio.run(
|
||||
resolve_from_value(
|
||||
mpn="18pF",
|
||||
@@ -76,7 +77,7 @@ def test_resolve_from_value_placeholder_no_llm(monkeypatch):
|
||||
raise AssertionError("LLM must not run")
|
||||
|
||||
monkeypatch.setattr("backend.services.extraction.call_with_fallback", boom)
|
||||
tax = Path(__file__).resolve().parents[1] / "taxonomy"
|
||||
tax = TAXONOMY
|
||||
with pytest.raises(ValueError, match="Placeholder"):
|
||||
asyncio.run(
|
||||
resolve_from_value(
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from tests.paths import SIMPLE_PROJECT, TAXONOMY
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from backend.periscopex.functional_groups import FunctionalGroupsReport, PlacementDomain, PlacementIcGroup
|
||||
@@ -26,7 +28,7 @@ from backend.periscopex.pcb_net_match import check_pcb_net_match
|
||||
from backend.periscopex.pcb_review import build_pcb_layout_context
|
||||
from backend.services.projects import ProjectMeta, STATUS_QUEUED, STATUS_RUNNING
|
||||
|
||||
SIMPLE = Path(__file__).resolve().parents[1] / "simple_project"
|
||||
SIMPLE = SIMPLE_PROJECT
|
||||
|
||||
|
||||
def _graph() -> DesignGraph:
|
||||
|
||||
@@ -13,6 +13,8 @@ Locks in:
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from tests.paths import SIMPLE_PROJECT, TAXONOMY
|
||||
|
||||
from backend.periscopex.models import (
|
||||
Component,
|
||||
ComponentConstraints,
|
||||
@@ -184,7 +186,7 @@ def test_simple_project_uart0_nets_are_feasible_on_mspm0_pins():
|
||||
from backend.periscopex.models import DesignGraph
|
||||
|
||||
graph = DesignGraph.model_validate_json(
|
||||
(Path(__file__).resolve().parents[1] / "simple_project" / "design_graph.json").read_text()
|
||||
(SIMPLE_PROJECT / "design_graph.json").read_text()
|
||||
)
|
||||
cmap = {
|
||||
"MSPM0G3507SPTR": _constraints(
|
||||
@@ -206,7 +208,7 @@ def test_simple_project_uart0_swapped_on_mspm0_is_error():
|
||||
from backend.periscopex.models import DesignGraph
|
||||
|
||||
graph = DesignGraph.model_validate_json(
|
||||
(Path(__file__).resolve().parents[1] / "simple_project" / "design_graph.json").read_text()
|
||||
(SIMPLE_PROJECT / "design_graph.json").read_text()
|
||||
)
|
||||
cmap = {
|
||||
"MSPM0G3507SPTR": _constraints(
|
||||
|
||||
@@ -6,6 +6,8 @@ Against: no PCB; same copper; same_layer unset; via in courtyard.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from tests.paths import SIMPLE_PROJECT, TAXONOMY
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from backend.periscopex.eval_report import eval_simple_project
|
||||
@@ -21,7 +23,7 @@ from backend.periscopex.models import (
|
||||
)
|
||||
from backend.periscopex.placement_check import _in_poly, check_placement
|
||||
|
||||
SIMPLE = Path(__file__).resolve().parents[1] / "simple_project"
|
||||
SIMPLE = SIMPLE_PROJECT
|
||||
|
||||
|
||||
def _graph() -> DesignGraph:
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from tests.paths import SIMPLE_PROJECT, TAXONOMY
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from backend.periscopex.functional_groups import (
|
||||
@@ -18,7 +20,7 @@ from backend.periscopex.models import (
|
||||
)
|
||||
from backend.periscopex.placement_pack import build_placement_pack
|
||||
|
||||
SIMPLE = Path(__file__).resolve().parents[1] / "simple_project"
|
||||
SIMPLE = SIMPLE_PROJECT
|
||||
|
||||
|
||||
def _graph() -> DesignGraph:
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from tests.paths import SIMPLE_PROJECT, TAXONOMY
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
@@ -14,7 +16,7 @@ from backend.periscopex.models import DesignGraph
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SIMPLE = ROOT / "simple_project"
|
||||
SIMPLE = SIMPLE_PROJECT
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -7,6 +7,8 @@ I2C/GPIO/CC are not 50/90 Ω. ImpedenceFinder numbers vs layout_rules only.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from tests.paths import SIMPLE_PROJECT, TAXONOMY
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from backend.periscopex.eval_report import eval_simple_project
|
||||
@@ -26,7 +28,7 @@ from backend.periscopex.models import (
|
||||
)
|
||||
from backend.periscopex.si_check import bus_class, check_si, partner_net, skip_si_net
|
||||
|
||||
SIMPLE = Path(__file__).resolve().parents[1] / "simple_project"
|
||||
SIMPLE = SIMPLE_PROJECT
|
||||
|
||||
|
||||
def _graph() -> DesignGraph:
|
||||
|
||||
@@ -9,6 +9,8 @@ so it survives future prompt regressions.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from tests.paths import SIMPLE_PROJECT, TAXONOMY
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
@@ -20,7 +22,7 @@ from backend.services import validation as val
|
||||
from backend.services.llm.types import Completion, ToolCall, Usage
|
||||
from backend.services.storage import LocalStorageBackend
|
||||
|
||||
GRAPH = Path(__file__).resolve().parent.parent / "simple_project" / "design_graph.json"
|
||||
GRAPH = SIMPLE_PROJECT / "design_graph.json"
|
||||
IC_MPNS = {
|
||||
"U1": "SPX3819M5-L-3-3/TR",
|
||||
"U2": "CH340E",
|
||||
|
||||
@@ -8,6 +8,8 @@ and that trace failures never break the review/report.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from tests.paths import SIMPLE_PROJECT, TAXONOMY
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
@@ -20,7 +22,7 @@ from backend.services import validation as val
|
||||
from backend.services.llm.types import Completion, ToolCall, Usage
|
||||
from backend.services.storage import LocalStorageBackend
|
||||
|
||||
GRAPH = Path(__file__).resolve().parent.parent / "simple_project" / "design_graph.json"
|
||||
GRAPH = SIMPLE_PROJECT / "design_graph.json"
|
||||
IC_MPNS = {
|
||||
"U1": "SPX3819M5-L-3-3/TR",
|
||||
"U2": "CH340E",
|
||||
|
||||
Reference in New Issue
Block a user