Skip to content

Commit ada6971

Browse files
committed
Fix connector color propagation for closed valves and add unit test
1 parent e54aa79 commit ada6971

File tree

2 files changed

+68
-10
lines changed

2 files changed

+68
-10
lines changed

pychron/canvas/canvas2D/extraction_line_canvas2D.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,16 +227,16 @@ def _propagate_connector_colors(self) -> None:
227227
if not attached_items:
228228
attached_items = self._fallback_connected_items(item)
229229

230+
endpoint_states = [
231+
bool(getattr(attached, "state", False)) for attached in attached_items
232+
]
230233
color_item = self._preferred_connector_color_item(attached_items)
231234
color = self._connector_color_for_item(color_item)
232235
if color is not None:
233236
item.active_color = color
234-
item.state = True
237+
item.state = any(endpoint_states)
235238
continue
236239

237-
endpoint_states = [
238-
bool(getattr(attached, "state", False)) for attached in attached_items
239-
]
240240
if endpoint_states:
241241
item.state = any(endpoint_states)
242242
if hasattr(item, "default_color"):
@@ -246,6 +246,10 @@ def _connector_color_for_item(self, item: object) -> object | None:
246246
if item is None:
247247
return None
248248

249+
if isinstance(item, (BaseValve, Switch)) and not bool(getattr(item, "state", False)):
250+
# Closed valves/switches should not paint nearby connectors from the opposite side.
251+
return None
252+
249253
source_item = item
250254
if isinstance(item, BaseValve):
251255
source_name = getattr(item, "network_dominant_source_node", "") or ""

pychron/extraction_line/tests/network_state_test.py

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,27 @@
66
import unittest
77

88
if "yaml" not in sys.modules:
9+
10+
def _yaml_load(stream, Loader=None):
11+
data = stream.read() if hasattr(stream, "read") else stream
12+
return json.loads(data)
13+
14+
def _yaml_dump(obj, default_flow_style=False):
15+
return json.dumps(obj)
16+
917
yaml_stub = types.SimpleNamespace(
1018
FullLoader=object,
1119
Loader=object,
1220
YAMLError=Exception,
13-
load=lambda stream, Loader=None: json.loads(
14-
stream.read() if hasattr(stream, "read") else stream
15-
),
21+
load=_yaml_load,
22+
dump=_yaml_dump,
23+
safe_dump=_yaml_dump,
1624
)
1725
sys.modules["yaml"] = yaml_stub
1826

27+
from pychron.canvas.canvas2D.extraction_line_canvas2D import ExtractionLineCanvas2D
28+
from pychron.canvas.canvas2D.scene.primitives.connections import Connection
29+
from pychron.canvas.canvas2D.scene.primitives.valves import Switch
1930
from pychron.extraction_line.graph.extraction_line_graph import ExtractionLineGraph
2031
from pychron.extraction_line.graph.nodes import (
2132
Edge,
@@ -52,6 +63,51 @@ def make_graph() -> ExtractionLineGraph:
5263

5364

5465
class ExtractionLineNetworkStateTestCase(unittest.TestCase):
66+
def test_closed_valve_connector_does_not_inherit_other_side_state(self) -> None:
67+
class SceneStub:
68+
def __init__(self, items: list[object], by_name: dict[str, object]) -> None:
69+
self._items = items
70+
self._by_name = by_name
71+
72+
def get_items(self) -> list[object]:
73+
return self._items
74+
75+
def get_item(self, name: str) -> object | None:
76+
return self._by_name.get(name)
77+
78+
class SourceStub:
79+
state = True
80+
default_color = (0.5, 0.5, 0.5)
81+
active_color = (0.0, 1.0, 0.0)
82+
83+
connector = Connection((0, 0), (1, 0), name="C")
84+
connector.default_color = (1.0, 0.0, 0.0)
85+
connector.active_color = (0.0, 1.0, 0.0)
86+
connector.state = False
87+
88+
valve = Switch(0, 0, name="V")
89+
valve.state = False
90+
valve.network_dominant_source_node = "SRC"
91+
valve.connections = [("left", connector)]
92+
93+
source = SourceStub()
94+
scene = SceneStub([connector, valve], {"C": connector, "V": valve, "SRC": source})
95+
96+
class CanvasStub:
97+
_propagate_connector_colors = ExtractionLineCanvas2D._propagate_connector_colors
98+
_connected_items_for_connector = ExtractionLineCanvas2D._connected_items_for_connector
99+
_fallback_connected_items = ExtractionLineCanvas2D._fallback_connected_items
100+
_preferred_connector_color_item = ExtractionLineCanvas2D._preferred_connector_color_item
101+
_connector_color_for_item = ExtractionLineCanvas2D._connector_color_for_item
102+
103+
canvas = CanvasStub()
104+
canvas.scene = scene
105+
106+
canvas._propagate_connector_colors()
107+
108+
self.assertFalse(connector.state)
109+
self.assertEqual(connector.active_color, connector.default_color)
110+
55111
def test_open_network_is_single_region(self) -> None:
56112
graph = make_graph()
57113
graph.set_valve_state("V1", True)
@@ -179,9 +235,7 @@ def test_xml_and_yaml_loads_compute_equivalent_regions(self) -> None:
179235
yaml_snapshot = yaml_graph.compute_state()
180236

181237
self.assertEqual(xml_snapshot.region_count, yaml_snapshot.region_count)
182-
self.assertEqual(
183-
sorted(xml_snapshot.regions.keys()), sorted(yaml_snapshot.regions.keys())
184-
)
238+
self.assertEqual(sorted(xml_snapshot.regions.keys()), sorted(yaml_snapshot.regions.keys()))
185239
xml_volumes = sorted(region.volume for region in xml_snapshot.regions.values())
186240
yaml_volumes = sorted(region.volume for region in yaml_snapshot.regions.values())
187241
self.assertListEqual(xml_volumes, yaml_volumes)

0 commit comments

Comments
 (0)