from __future__ import annotations from collections.abc import Mapping, Sequence from typing import Any from wf_core.errors import WorkflowExecutionError from wf_core.local_paths import LocalPathError, set_local_value from wf_core.models.input_bindings import ( InputExpression, InputExpressionBinding, InputPathBinding, InputValueBinding, StepInputBinding, ) from wf_core.models.json_values import JsonValue from wf_core.runtime.input_sources import ( GraphSourceResolver, SourceResolver, resolve_composed_expression, ) def resolve_input_expression( expression: InputExpression, *, state: Mapping[str, Any], workflow_input: Mapping[str, Any], context: Mapping[str, Any], label: str, location: str, ) -> JsonValue: """Resolve one composite expression while preserving its payload location.""" resolver = GraphSourceResolver( state=state, workflow_input=workflow_input, context=context ) return resolve_composed_expression( expression, resolver=resolver, label=label, location=location ) def resolve_input_expression_with_resolver( expression: InputExpression, *, resolver: SourceResolver, label: str, location: str, ) -> JsonValue: """Resolve one expression through an explicit typed source resolver.""" return resolve_composed_expression( expression, resolver=resolver, label=label, location=location ) def resolve_step_input_bindings_with_resolver( bindings: Sequence[StepInputBinding], *, resolver: SourceResolver, label: str, ) -> dict[str, Any]: """Build one node-local payload through an explicit graph resolver.""" payload: dict[str, Any] = {} for binding in bindings: location = str(binding.target) if isinstance(binding, InputValueBinding): value = binding.value elif isinstance(binding, InputPathBinding): try: value = resolver.resolve_path(binding.path) except (ValueError, WorkflowExecutionError) as exc: raise WorkflowExecutionError(f"{label} {location}: {exc}") from exc elif isinstance(binding, InputExpressionBinding): value = resolve_input_expression_with_resolver( binding.expression, resolver=resolver, label=label, location=location, ) else: raise WorkflowExecutionError(f"unsupported input binding for {label}") try: set_local_value(payload, binding.target, value) except LocalPathError as exc: raise WorkflowExecutionError(f"{label} {location}: {exc}") from exc return payload def resolve_step_input_bindings( bindings: Sequence[StepInputBinding], *, state: Mapping[str, Any], workflow_input: Mapping[str, Any], context: Mapping[str, Any], label: str, ) -> dict[str, Any]: """Build one node-local payload from simple or composite input bindings.""" resolver = GraphSourceResolver( state=state, workflow_input=workflow_input, context=context ) return resolve_step_input_bindings_with_resolver( bindings, resolver=resolver, label=label )