fix: quote dotted aliases and offer root foreach in inventory
This commit is contained in:
@@ -202,7 +202,9 @@ def context_path_options(
|
|||||||
reason = raw_reason if isinstance(raw_reason, str) else None
|
reason = raw_reason if isinstance(raw_reason, str) else None
|
||||||
|
|
||||||
option: AuthoringPathOptionPayload = {
|
option: AuthoringPathOptionPayload = {
|
||||||
"path": f"context.{name}",
|
# Field names are literal path segments: dotted foreach aliases
|
||||||
|
# must stay quoted as one segment, never split on ".".
|
||||||
|
"path": str(GraphSourcePath("context", (name,))),
|
||||||
"label": name.replace("_", " ").replace("-", " ").title(),
|
"label": name.replace("_", " ").replace("-", " ").title(),
|
||||||
"origin": "runtime_context",
|
"origin": "runtime_context",
|
||||||
"schema": deepcopy(dict(schema)),
|
"schema": deepcopy(dict(schema)),
|
||||||
|
|||||||
@@ -510,3 +510,79 @@ def test_structured_foreach_paths_appear_in_authoring_inventory() -> None:
|
|||||||
if option["path"].startswith("context.foreach."):
|
if option["path"].startswith("context.foreach."):
|
||||||
assert option["origin"] == "runtime_context"
|
assert option["origin"] == "runtime_context"
|
||||||
assert option["uses"] == ["step_input"]
|
assert option["uses"] == ["step_input"]
|
||||||
|
|
||||||
|
|
||||||
|
def _ref_inventory_workflow(*, alias: str = "order"):
|
||||||
|
from wf_core import END, Edge, ForeachNode, NodeUse, SchemaRef, Workflow
|
||||||
|
from wf_core.models.schemas import StateSchema
|
||||||
|
|
||||||
|
return Workflow(
|
||||||
|
name="inventory_nested_ref",
|
||||||
|
input_schema=SchemaRef(type="object"),
|
||||||
|
state_schema=StateSchema.model_validate(
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"orders": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {"$ref": "#/$defs/Order"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"$defs": {
|
||||||
|
"Order": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"sku": {"type": "string"},
|
||||||
|
"detail": {"$ref": "#/$defs/Detail"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Detail": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {"name": {"type": "string"}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
),
|
||||||
|
output_schema=SchemaRef(type="object"),
|
||||||
|
start="orders",
|
||||||
|
nodes=[
|
||||||
|
ForeachNode.model_validate(
|
||||||
|
{"id": "orders", "type": "foreach", "over": "state.orders", "as": alias}
|
||||||
|
),
|
||||||
|
NodeUse(id="body", type="node", node="noop"),
|
||||||
|
],
|
||||||
|
edges=[
|
||||||
|
Edge.model_validate({"from": "orders", "outcome": "loop", "to": "body"}),
|
||||||
|
Edge.model_validate({"from": "body", "outcome": "ok", "to": "orders"}),
|
||||||
|
Edge.model_validate({"from": "orders", "outcome": "done", "to": END}),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_nested_ref_item_children_appear_in_authoring_inventory() -> None:
|
||||||
|
from wf_api.authoring_contracts import context_path_options_for_node
|
||||||
|
|
||||||
|
options = context_path_options_for_node(_ref_inventory_workflow(), "body")
|
||||||
|
paths = {option["path"] for option in options}
|
||||||
|
assert "context.foreach.orders.item.sku" in paths
|
||||||
|
assert "context.foreach.orders.item.detail.name" in paths
|
||||||
|
|
||||||
|
|
||||||
|
def test_dotted_alias_produces_quoted_authoring_path() -> None:
|
||||||
|
from wf_api.authoring_contracts import context_path_options_for_node
|
||||||
|
|
||||||
|
options = context_path_options_for_node(
|
||||||
|
_ref_inventory_workflow(alias="item.alias"), "body"
|
||||||
|
)
|
||||||
|
paths = {option["path"] for option in options}
|
||||||
|
assert 'context."item.alias"' in paths
|
||||||
|
assert "context.item.alias" not in paths
|
||||||
|
|
||||||
|
|
||||||
|
def test_root_inventory_offers_foreach_map() -> None:
|
||||||
|
from wf_api.authoring_contracts import context_path_options_for_node
|
||||||
|
|
||||||
|
options = context_path_options_for_node(_ref_inventory_workflow(), "orders")
|
||||||
|
paths = {option["path"] for option in options}
|
||||||
|
assert "context.foreach" in paths
|
||||||
|
assert "context.prior_outcome" in paths
|
||||||
|
|||||||
Reference in New Issue
Block a user