improve autoid

This commit is contained in:
lda
2026-05-19 01:25:27 +07:00 Verified
parent 8210ae3b85
commit 2d5762dd26
3 changed files with 30 additions and 17 deletions
+17 -4
View File
@@ -21,6 +21,7 @@ from wf_core import (
) )
from wf_core.errors import WorkflowExecutionError from wf_core.errors import WorkflowExecutionError
from wf_core.models.conditions import Condition as CoreCondition from wf_core.models.conditions import Condition as CoreCondition
from wf_core.models.conditions import BinaryCondition, ExistsCondition, PathOperand
from wf_core.runtime.ops.merges import ReducerDefinition from wf_core.runtime.ops.merges import ReducerDefinition
from ..dsl import Expr, PathArg, PathExpr, compile_condition from ..dsl import Expr, PathArg, PathExpr, compile_condition
@@ -40,6 +41,17 @@ from .mapping import (
from .refs import BranchRef, RouteRef, StepRef, is_node_spec, step_id from .refs import BranchRef, RouteRef, StepRef, is_node_spec, step_id
def _condition_base(condition: CoreCondition) -> str:
"""Return a small source-derived id base when one path is obvious."""
if isinstance(condition, ExistsCondition):
return slug_id(condition.path)
if isinstance(condition, BinaryCondition) and isinstance(
condition.left, PathOperand
):
return slug_id(condition.left.path)
return "condition"
@dataclass(slots=True) @dataclass(slots=True)
class WorkflowBuilder: class WorkflowBuilder:
name: str name: str
@@ -162,10 +174,11 @@ class WorkflowBuilder:
def condition( def condition(
self, *, id: str | None = None, check: CoreCondition | Expr self, *, id: str | None = None, check: CoreCondition | Expr
) -> ConditionNode: ) -> ConditionNode:
compiled = compile_condition(check)
node = ConditionNode( node = ConditionNode(
id=id or self._next_step_id("condition"), id=id or self._next_step_id(_condition_base(compiled)),
type="condition", type="condition",
check=compile_condition(check), check=compiled,
) )
self.nodes.append(node) self.nodes.append(node)
return node return node
@@ -273,7 +286,7 @@ class WorkflowBuilder:
conditions: list[ConditionNode] = [] conditions: list[ConditionNode] = []
default_target = self.use(default) if is_node_spec(default) else default default_target = self.use(default) if is_node_spec(default) else default
previous_condition: ConditionNode | None = None previous_condition: ConditionNode | None = None
condition_base = id or "condition" condition_base = id or slug_id(value.path)
for case_value, target in cases.items(): for case_value, target in cases.items():
condition = self.condition( condition = self.condition(
id=self._next_step_id(condition_base), id=self._next_step_id(condition_base),
@@ -334,7 +347,7 @@ class WorkflowBuilder:
conditions: list[ConditionNode] = [] conditions: list[ConditionNode] = []
resolved_targets: dict[object, StepRef] = {} resolved_targets: dict[object, StepRef] = {}
previous_condition: ConditionNode | None = None previous_condition: ConditionNode | None = None
condition_base = id or "condition" condition_base = id or _condition_base(compile_condition(clauses[0][0]))
for index, (condition_expr, target) in enumerate(clauses): for index, (condition_expr, target) in enumerate(clauses):
condition = self.condition( condition = self.condition(
id=self._next_step_id(condition_base), id=self._next_step_id(condition_base),
+2 -2
View File
@@ -164,8 +164,8 @@ def test_builder_can_auto_id_condition_foreach_and_interrupt() -> None:
foreach = builder.foreach(over="state.tags", as_="tag") foreach = builder.foreach(over="state.tags", as_="tag")
interrupt = builder.interrupt(kind="approval") interrupt = builder.interrupt(kind="approval")
assert first_condition.id == "condition" assert first_condition.id == "state_count"
assert second_condition.id == "condition_2" assert second_condition.id == "state_count_2"
assert foreach.id == "foreach_tag" assert foreach.id == "foreach_tag"
assert interrupt.id == "interrupt_approval" assert interrupt.id == "interrupt_approval"
+11 -11
View File
@@ -84,15 +84,15 @@ def test_builder_match_expands_state_value_cases_into_condition_chain() -> None:
) )
assert [node.id for node in targets.conditions] == [ assert [node.id for node in targets.conditions] == [
"condition", "state_value",
"condition_2", "state_value_2",
] ]
assert targets.entry.id == "condition" assert targets.entry.id == "state_value"
assert [(edge.from_, edge.outcome, edge.to) for edge in builder.edges] == [ assert [(edge.from_, edge.outcome, edge.to) for edge in builder.edges] == [
("condition", "true", "left"), ("state_value", "true", "left"),
("condition", "false", "condition_2"), ("state_value", "false", "state_value_2"),
("condition_2", "true", "right"), ("state_value_2", "true", "right"),
("condition_2", "false", "fallback"), ("state_value_2", "false", "fallback"),
] ]
assert targets["left"] is left assert targets["left"] is left
assert targets["right"] is right assert targets["right"] is right
@@ -135,11 +135,11 @@ def test_builder_when_routes_one_boolean_condition_expression() -> None:
targets = builder.when(state("count").ge(1), then=left, otherwise=right) targets = builder.when(state("count").ge(1), then=left, otherwise=right)
assert targets.entry.id == "condition" assert targets.entry.id == "state_count"
assert [node.id for node in targets.conditions] == ["condition"] assert [node.id for node in targets.conditions] == ["state_count"]
assert [(edge.from_, edge.outcome, edge.to) for edge in builder.edges] == [ assert [(edge.from_, edge.outcome, edge.to) for edge in builder.edges] == [
("condition", "true", "left"), ("state_count", "true", "left"),
("condition", "false", "right"), ("state_count", "false", "right"),
] ]
assert targets[True] is left assert targets[True] is left
assert targets[False] is right assert targets[False] is right