get end node support in builder and drafts
This commit is contained in:
@@ -5,7 +5,7 @@ from pydantic import ValidationError
|
||||
from wf_artifacts.drafts import WorkflowDraft
|
||||
from wf_artifacts.drafts.api import compile_workflow_draft, validate_workflow_draft
|
||||
from wf_artifacts.drafts.adapter import build_workflow_from_draft
|
||||
from wf_core import ConditionNode, ForeachNode, NodeUse
|
||||
from wf_core import ConditionNode, EndNode, ForeachNode, NodeUse
|
||||
from wf_core.models.steps import InputValueBinding
|
||||
|
||||
|
||||
@@ -213,6 +213,33 @@ def test_adapter_lowers_when_step_through_builder() -> None:
|
||||
]
|
||||
|
||||
|
||||
def test_adapter_lowers_explicit_end_step() -> None:
|
||||
draft = WorkflowDraft.model_validate(
|
||||
{
|
||||
"name": "end_example",
|
||||
"input_schema": {},
|
||||
"state_schema": {"fields": {}},
|
||||
"output_schema": {},
|
||||
"outcomes": ["ok", "error"],
|
||||
"start": "echo",
|
||||
"steps": {
|
||||
"echo": {"use": "demo.echo"},
|
||||
"end_error": {"end": {"outcome": "error"}},
|
||||
},
|
||||
"routes": {"echo": {"error": "end_error"}},
|
||||
}
|
||||
)
|
||||
|
||||
workflow = build_workflow_from_draft(draft)
|
||||
terminal = workflow.nodes[1]
|
||||
|
||||
assert isinstance(terminal, EndNode)
|
||||
assert terminal.id == "end_error"
|
||||
assert terminal.outcome == "error"
|
||||
assert workflow.outcomes == ["ok", "error"]
|
||||
assert workflow.edges[0].to == "end_error"
|
||||
|
||||
|
||||
def test_adapter_lowers_choose_step_through_builder() -> None:
|
||||
draft = WorkflowDraft.model_validate(
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ from pydantic import ValidationError
|
||||
|
||||
from wf_artifacts.drafts import (
|
||||
DraftChooseStep,
|
||||
DraftEndStep,
|
||||
DraftForeachStep,
|
||||
DraftMatchStep,
|
||||
DraftUseStep,
|
||||
@@ -135,6 +136,25 @@ def test_workflow_draft_accepts_when_step() -> None:
|
||||
assert isinstance(draft.steps["decide"], DraftWhenStep)
|
||||
|
||||
|
||||
def test_workflow_draft_accepts_explicit_end_step() -> None:
|
||||
draft = WorkflowDraft.model_validate(
|
||||
{
|
||||
**_keyed_echo_draft(),
|
||||
"outcomes": ["ok", "error"],
|
||||
"steps": {
|
||||
**_keyed_echo_draft()["steps"],
|
||||
"end_error": {"end": {"outcome": "error"}},
|
||||
},
|
||||
"routes": {"echo": {"error": "end_error"}},
|
||||
}
|
||||
)
|
||||
|
||||
terminal = draft.steps["end_error"]
|
||||
|
||||
assert isinstance(terminal, DraftEndStep)
|
||||
assert terminal.end.outcome == "error"
|
||||
|
||||
|
||||
def test_workflow_draft_accepts_choose_step() -> None:
|
||||
draft = WorkflowDraft.model_validate(
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ from wf_authoring import (
|
||||
state,
|
||||
state_path,
|
||||
)
|
||||
from wf_core import END, RunStatus, WorkflowExecutionError
|
||||
from wf_core import END, EndNode, RunStatus, WorkflowExecutionError
|
||||
from wf_core.models.steps import InputPathBinding, InputValueBinding
|
||||
from wf_core.paths import GraphSourcePath, LocalPath, StatePath
|
||||
from wf_platform import CapabilityRef
|
||||
@@ -455,6 +455,25 @@ def test_builder_rejects_mixed_canonical_and_deprecated_output_styles() -> None:
|
||||
)
|
||||
|
||||
|
||||
def test_builder_adds_explicit_end_node() -> None:
|
||||
builder = WorkflowBuilder(
|
||||
name="explicit_end",
|
||||
input_schema={},
|
||||
state_schema={"fields": {}},
|
||||
output_schema={},
|
||||
outcomes=["ok", "error"],
|
||||
)
|
||||
|
||||
terminal = builder.end("error", id="end_error")
|
||||
|
||||
assert isinstance(terminal, EndNode)
|
||||
assert terminal.id == "end_error"
|
||||
assert terminal.outcome == "error"
|
||||
assert builder.nodes[-1] is terminal
|
||||
builder.set_entry_point(terminal)
|
||||
assert builder.compile().outcomes == ["ok", "error"]
|
||||
|
||||
|
||||
class _StructuralKeyMap(Mapping[object, object]):
|
||||
def __getitem__(self, key: object) -> object:
|
||||
raise KeyError(key)
|
||||
|
||||
Reference in New Issue
Block a user