Native PipelineWorkspace and event broker in periscope/src.
PCB and placement jobs import job_workspace instead of PinScope pipeline.py. Analysis run_pipeline re-exports the same broker singleton.
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
"""Prove native workspace/broker before PCB/placement stop importing pipeline.py."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
import inspect
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from backend.services.job_workspace import (
|
||||
EventBroker,
|
||||
PipelineWorkspace,
|
||||
set_broker,
|
||||
)
|
||||
from backend.services.job_workspace import broker as native_broker
|
||||
from backend.services.pipeline import EventBroker as InheritedBroker
|
||||
from backend.services.pipeline import PipelineWorkspace as InheritedWorkspace
|
||||
from backend.services.storage import LocalStorageBackend
|
||||
|
||||
|
||||
def test_native_job_workspace_does_not_import_pipeline():
|
||||
import backend.services.job_workspace as jw
|
||||
|
||||
tree = ast.parse(Path(jw.__file__).read_text())
|
||||
imported = [
|
||||
node.module
|
||||
for node in ast.walk(tree)
|
||||
if isinstance(node, ast.ImportFrom) and node.module
|
||||
]
|
||||
assert "backend.services.pipeline" not in imported
|
||||
assert "backend.periscopex.graph" not in imported
|
||||
assert "backend.periscopex.parsers" not in imported
|
||||
|
||||
|
||||
def test_event_broker_publish_subscribe_and_replay():
|
||||
b = EventBroker()
|
||||
b.publish("p1", "pcb_step_update", {"stage": "parse_pcb"})
|
||||
q = b.subscribe("p1")
|
||||
msg = q.get_nowait()
|
||||
assert msg == {"event": "pcb_step_update", "data": {"stage": "parse_pcb"}}
|
||||
b.publish("p1", "pcb_complete", {"findings": 1})
|
||||
msg2 = q.get_nowait()
|
||||
assert msg2["event"] == "pcb_complete"
|
||||
b.unsubscribe("p1", q)
|
||||
b.clear_history("p1")
|
||||
q2 = b.subscribe("p1")
|
||||
assert q2.empty()
|
||||
|
||||
|
||||
def test_set_broker_swaps_module_singleton():
|
||||
original = native_broker
|
||||
replacement = EventBroker()
|
||||
set_broker(replacement)
|
||||
import backend.services.job_workspace as jw
|
||||
assert jw.broker is replacement
|
||||
set_broker(original)
|
||||
assert jw.broker is original
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_workspace_mirrors_storage_and_netlist_like_inherited(tmp_path):
|
||||
storage = LocalStorageBackend(tmp_path)
|
||||
prefix = "users/local/projects/ws1"
|
||||
storage.write_json(f"{prefix}/project.json", {"id": "ws1"})
|
||||
bom = tmp_path / "bom.csv"
|
||||
bom.write_text("Reference,MPN\nU1,PART\n")
|
||||
storage.upload_from_local(bom, f"{prefix}/uploads/bom.csv")
|
||||
net = tmp_path / "netlist.edn"
|
||||
net.write_text("(edif dummy)")
|
||||
storage.upload_from_local(net, f"{prefix}/uploads/netlist.edn")
|
||||
|
||||
native_net = None
|
||||
inherited_net = None
|
||||
async with PipelineWorkspace(storage, "local", "ws1") as nws:
|
||||
native_net = nws.netlist_local_path()
|
||||
assert nws.local_path("uploads/bom.csv").is_file()
|
||||
assert native_net.name == "netlist.edn"
|
||||
nws.local_path("pcb_report.json").write_text("{}")
|
||||
nws._upload_file("pcb_report.json")
|
||||
async with InheritedWorkspace(storage, "local", "ws1") as iws:
|
||||
inherited_net = iws.netlist_local_path()
|
||||
assert inherited_net.name == native_net.name
|
||||
assert storage.exists(f"{prefix}/pcb_report.json")
|
||||
|
||||
|
||||
def test_pcb_and_placement_do_not_import_pipeline_py():
|
||||
import backend.services.pcb_pipeline as pcb
|
||||
import backend.services.placement_pipeline as place
|
||||
|
||||
for mod in (pcb, place):
|
||||
tree = ast.parse(Path(mod.__file__).read_text())
|
||||
imported = [
|
||||
node.module
|
||||
for node in ast.walk(tree)
|
||||
if isinstance(node, ast.ImportFrom) and node.module
|
||||
]
|
||||
assert "backend.services.pipeline" not in imported
|
||||
assert "backend.services.job_workspace" in imported
|
||||
|
||||
|
||||
def test_pipeline_reexports_native_workspace():
|
||||
from backend.services import job_workspace as jw
|
||||
from backend.services import pipeline as pipe
|
||||
assert pipe.PipelineWorkspace is jw.PipelineWorkspace
|
||||
assert pipe.EventBroker is jw.EventBroker
|
||||
assert inspect.signature(EventBroker.publish) == inspect.signature(
|
||||
InheritedBroker.publish
|
||||
)
|
||||
native_methods = {"local_path", "netlist_local_path", "_upload_file", "_upload_dir"}
|
||||
for name in native_methods:
|
||||
assert hasattr(InheritedWorkspace, name)
|
||||
assert hasattr(PipelineWorkspace, name)
|
||||
Reference in New Issue
Block a user