Skip to content

Commit 7d10e5e

Browse files
committed
[DEV-2766] NetworkTrace/Traversal now correctly respects can_stop_on_start when providing multiple start items.
Signed-off-by: Max Chesterfield <max.chesterfield@zepben.com>
1 parent 3092642 commit 7d10e5e

6 files changed

Lines changed: 46 additions & 76 deletions

File tree

changelog.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@
2323
### Fixes
2424
* When finding `LvFeeders` in the `Site` we will now exclude `LvFeeders` that start with an open `Switch`
2525
* The follow fixes were added to Traversal and NetworkTrace:
26-
* `canStopAtStartItem` now works for branching traversals.
26+
* `can_stop_on_start_item` now works for branching traversals.
2727
* Traversal start items are added to the queue before traversal starts, so that the start items honour the queue type order.
28-
* Stop conditions on the `NetworkTrace` now are checked based on a step type, like `QueueCondition` does, rather than by checking `canActionItem`.
28+
* Stop conditions on the `NetworkTrace` now are checked based on a step type, like `QueueCondition` does, rather than by checking `can_action_item`.
2929
* `Cut` and `Clamp` are now correctly supported in `SetDirection` and `DirectionCondition`.
3030
* `NetworkTrace` now handles starting on `Cut` , `Clamp`, and `AcLineSegment` and their terminals in a explicit / sensible way.
3131
* `NetworkTracePathProvider` now correctly handles next paths when starting on a `Clamp` terminal.
32+
* `NetworkTrace`/`Traversal` now correctly respects `can_stop_on_start_item` when providing multiple start items.
33+
3234

3335
### Notes
3436
* None.

src/zepben/evolve/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,5 @@
436436
from zepben.evolve.services.network.tracing.phases.set_phases import *
437437

438438
from zepben.evolve.testing.test_network_builder import *
439-
from zepben.evolve.testing.test_traversal import *
440439

441440
# @formatter:on

src/zepben/evolve/services/network/tracing/traversal/traversal.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ def add_step_action(self, action: Union[StepActionFunc, StepAction[T]]) -> D:
280280

281281
raise RuntimeError(f'Condition [{action.__class__.__name__}] does not match expected: [StepAction | StepActionWithContextValue | Callable]')
282282

283-
def if_not_stopping(self, action: Callable) -> D:
283+
def if_not_stopping(self, action: Callable[[T, StepContext], None]) -> D:
284284
"""
285285
Adds an action to be performed on each item that does not match any stop condition.
286286
@@ -291,7 +291,7 @@ def if_not_stopping(self, action: Callable) -> D:
291291
return self
292292

293293

294-
def if_stopping(self, action: Callable) -> D:
294+
def if_stopping(self, action: Callable[[T, StepContext], None]) -> D:
295295
"""
296296
Adds an action to be performed on each item that matches a stop condition.
297297
@@ -449,10 +449,10 @@ async def _traverse(self, can_stop_on_start_item: bool):
449449
else:
450450
self.queue.append(start_item)
451451

452-
can_stop = can_stop_on_start_item
453452
while self.queue.has_next():
454453
current = self.queue.pop()
455454
context = self._get_step_context(current)
455+
can_stop = can_stop_on_start_item or (not context.is_start_item)
456456
if self.can_visit_item(current, context):
457457
context.is_stopping = can_stop and self.matches_any_stop_condition(current, context)
458458

@@ -464,7 +464,6 @@ async def _traverse(self, can_stop_on_start_item: bool):
464464
if not context.is_stopping:
465465
self.queue_next(current, context)
466466

467-
can_stop = True
468467

469468
def _get_step_context(self, item: T) -> StepContext:
470469
try:

src/zepben/evolve/testing/test_traversal.py

Lines changed: 0 additions & 66 deletions
This file was deleted.

test/services/network/tracing/networktrace/test_network_trace.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import pytest
1212

1313
from services.network.tracing.networktrace.test_network_trace_step_path_provider import PathTerminal, _verify_paths
14-
from zepben.evolve import AcLineSegment, Clamp, Terminal, NetworkTraceStep, Cut, ConductingEquipment, TraversalQueue, Junction, ngen
14+
from zepben.evolve import AcLineSegment, Clamp, Terminal, NetworkTraceStep, Cut, ConductingEquipment, TraversalQueue, Junction, ngen, NetworkTraceActionType
1515
from zepben.evolve.services.network.tracing.networktrace.tracing import Tracing
1616
from zepben.evolve.testing.test_network_builder import TestNetworkBuilder
1717

@@ -178,8 +178,7 @@ async def test_can_Stop_on_start_item_when_running_from_conducting_equipment_bra
178178
assert set(map(lambda it: (it.num_equipment_steps, it.path.to_equipment.mrid), steps)) \
179179
== {(0, 'b0')}
180180

181-
if 'TOX_ENV_NAME' not in os.environ:
182-
181+
if 'TOX_ENV_NAME' not in os.environ: # Skips the test during tox runs as variable hardware will affect speed
183182
@pytest.mark.asyncio
184183
async def test_can_run_large_branching_traces(self):
185184
try:
@@ -202,3 +201,27 @@ async def test_can_run_large_branching_traces(self):
202201
except Exception as e:
203202
sys.setrecursionlimit(1000) # back to default
204203
raise e
204+
205+
@pytest.mark.asyncio
206+
async def test_multiple_start_items_can_stop_on_start_doesnt_prevent_stop_checks_when_visiting_via_loop(self):
207+
ns = (TestNetworkBuilder()
208+
.from_acls() # c0
209+
.to_acls() # c1
210+
.to_acls() # c2
211+
.connect_to('c0')
212+
).network
213+
214+
stop_checks: List[str] = []
215+
steps: List[str] = []
216+
217+
def stop_condition(item, _):
218+
stop_checks.append(item.path.to_terminal.mrid)
219+
return item.path.to_equipment.mrid == 'c1'
220+
221+
trace = Tracing.network_trace(action_step_type=NetworkTraceActionType.ALL_STEPS) \
222+
.add_stop_condition(stop_condition) \
223+
.if_not_stopping(lambda item, _: steps.append(item.path.to_terminal.mrid))
224+
await trace.run(ns.get('c1', ConductingEquipment), can_stop_on_start_item=False)
225+
226+
assert stop_checks == ['c2-t1', 'c2-t2', 'c0-t1', 'c0-t2', 'c1-t1']
227+
assert steps == ['c1-t2', 'c2-t1', 'c2-t2', 'c0-t1', 'c0-t2']

test/services/network/tracing/traversal/test_traversal.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,3 +363,16 @@ async def test_start_items_are_queued_before_traversal_starts_so_queue_type_is_h
363363
).run()
364364

365365
assert steps == [-1, 1, -2, 2]
366+
367+
@pytest.mark.asyncio
368+
async def test_multiple_start_items_respect_can_stop_on_start(self):
369+
steps = []
370+
traversal = (_create_traversal(queue=TraversalQueue.breadth_first())
371+
.add_stop_condition(lambda item, x: True)
372+
.add_step_action(lambda item, x: steps.append(item))
373+
.add_start_item(1)
374+
.add_start_item(11)
375+
)
376+
await traversal.run(can_stop_on_start_item=False)
377+
378+
assert steps == [1, 11, 2, 12]

0 commit comments

Comments
 (0)