in the folders 2

ignore next inventors are the best inventors
This commit is contained in:
lda
2026-05-06 22:46:32 +07:00 Verified
parent 9874c295cd
commit cdcbe31583
9 changed files with 261 additions and 178 deletions
+15 -3
View File
@@ -1,7 +1,20 @@
from .builder import WorkflowBuilder from .builder import WorkflowBuilder
from .catalog import NodeCatalog, NodeCatalogEntry from .catalog import NodeCatalog, NodeCatalogEntry
from .conditions import context, exists, expr, input, state from .dsl import (
from .mapping import bind_fields, bind_state, merge_maps GraphPath,
bind_fields,
bind_state,
context,
context_path,
exists,
expr,
graph_path,
input,
input_path,
merge_maps,
state,
state_path,
)
from .ops import ( from .ops import (
BoolOutput, BoolOutput,
CoalesceInput, CoalesceInput,
@@ -19,7 +32,6 @@ from .ops import (
last_item_or_none, last_item_or_none,
length, length,
) )
from .paths import GraphPath, context_path, graph_path, input_path, state_path
from .nodes import ( from .nodes import (
AsyncRegistryHandler, AsyncRegistryHandler,
NodeReturn, NodeReturn,
+1 -3
View File
@@ -16,9 +16,7 @@ from wf_core import (
) )
from wf_core.model import Condition as CoreCondition from wf_core.model import Condition as CoreCondition
from .conditions import Expr, compile_condition from .dsl import Expr, GraphPath, PathArg, compile_condition
from .mapping import PathArg
from .paths import GraphPath
from .spec import NodeSpec from .spec import NodeSpec
StepRef: TypeAlias = str | NodeUse | ConditionNode | ForeachNode | InterruptNode StepRef: TypeAlias = str | NodeUse | ConditionNode | ForeachNode | InterruptNode
+19 -114
View File
@@ -1,116 +1,21 @@
from __future__ import annotations from .dsl.conditions import (
Expr,
from dataclasses import dataclass PathExpr,
from typing import Literal compile_condition,
context,
from wf_core.model import ( exists,
BinaryCondition, expr,
Condition, input,
ExistsCondition, state,
LiteralOperand,
NotCondition,
PathOperand,
VariadicCondition,
) )
from .paths import GraphPath, context_path, input_path, state_path
__all__ = [
def _operand(value: object) -> PathOperand | LiteralOperand: "Expr",
if isinstance(value, PathExpr): "PathExpr",
return PathOperand(path=value.path) "compile_condition",
if isinstance(value, GraphPath): "context",
return PathOperand(path=value.value) "exists",
return LiteralOperand(value=value) "expr",
"input",
"state",
def _path_str(value: PathExpr | GraphPath) -> str: ]
if isinstance(value, PathExpr):
return value.path
return value.value
@dataclass(frozen=True, slots=True)
class Expr:
condition: Condition
def __and__(self, other: object) -> Expr:
if not isinstance(other, Expr):
return NotImplemented
return Expr(VariadicCondition(op="and", args=[self.condition, other.condition]))
def __or__(self, other: object) -> Expr:
if not isinstance(other, Expr):
return NotImplemented
return Expr(VariadicCondition(op="or", args=[self.condition, other.condition]))
def __invert__(self) -> Expr:
return Expr(NotCondition(op="not", arg=self.condition))
def to_condition(self) -> Condition:
return self.condition
@dataclass(frozen=True, slots=True)
class PathExpr:
path: str
def _binary(self, op: Literal["eq", "ne", "gt", "lt"], other: object) -> Expr:
return Expr(
BinaryCondition(
op=op,
left=PathOperand(path=self.path),
right=_operand(other),
)
)
def eq(self, other: object) -> Expr:
return self._binary("eq", other)
def ne(self, other: object) -> Expr:
return self._binary("ne", other)
def gt(self, other: object) -> Expr:
return self._binary("gt", other)
def lt(self, other: object) -> Expr:
return self._binary("lt", other)
def __eq__(self, other: object) -> Expr: # type: ignore[override] # ty: ignore[invalid-method-override]
return self._binary("eq", other)
def __ne__(self, other: object) -> Expr: # type: ignore[override] # ty: ignore[invalid-method-override]
return self._binary("ne", other)
def __gt__(self, other: object) -> Expr:
return self.gt(other)
def __lt__(self, other: object) -> Expr:
return self.lt(other)
def expr(value: PathExpr | GraphPath) -> PathExpr:
if isinstance(value, PathExpr):
return value
return PathExpr(path=value.value)
def state(field: str) -> PathExpr:
return expr(state_path(field))
def input(field: str) -> PathExpr:
return expr(input_path(field))
def context(field: str) -> PathExpr:
return expr(context_path(field))
def exists(value: PathExpr | GraphPath) -> Expr:
return Expr(ExistsCondition(op="exists", path=_path_str(value)))
def compile_condition(value: Condition | Expr) -> Condition:
if isinstance(value, Expr):
return value.to_condition()
return value
+33
View File
@@ -0,0 +1,33 @@
from .conditions import (
Expr,
PathExpr,
compile_condition,
context,
exists,
expr,
input,
state,
)
from .mapping import PathArg, bind_fields, bind_state, merge_maps, normalize_path
from .paths import GraphPath, context_path, graph_path, input_path, state_path
__all__ = [
"Expr",
"GraphPath",
"PathArg",
"PathExpr",
"bind_fields",
"bind_state",
"compile_condition",
"context",
"context_path",
"exists",
"expr",
"graph_path",
"input",
"input_path",
"merge_maps",
"normalize_path",
"state",
"state_path",
]
+117
View File
@@ -0,0 +1,117 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import Literal
from wf_core.model import (
BinaryCondition,
Condition,
ExistsCondition,
LiteralOperand,
NotCondition,
PathOperand,
VariadicCondition,
)
from .paths import GraphPath, context_path, input_path, state_path
def _operand(value: object) -> PathOperand | LiteralOperand:
if isinstance(value, PathExpr):
return PathOperand(path=value.path)
if isinstance(value, GraphPath):
return PathOperand(path=value.value)
return LiteralOperand(value=value)
def _path_str(value: PathExpr | GraphPath) -> str:
if isinstance(value, PathExpr):
return value.path
return value.value
@dataclass(frozen=True, slots=True)
class Expr:
condition: Condition
def __and__(self, other: object) -> Expr:
if not isinstance(other, Expr):
return NotImplemented
return Expr(VariadicCondition(op="and", args=[self.condition, other.condition]))
def __or__(self, other: object) -> Expr:
if not isinstance(other, Expr):
return NotImplemented
return Expr(VariadicCondition(op="or", args=[self.condition, other.condition]))
def __invert__(self) -> Expr:
return Expr(NotCondition(op="not", arg=self.condition))
def to_condition(self) -> Condition:
return self.condition
@dataclass(frozen=True, slots=True)
class PathExpr:
path: str
def _binary(self, op: Literal["eq", "ne", "gt", "lt"], other: object) -> Expr:
return Expr(
BinaryCondition(
op=op,
left=PathOperand(path=self.path),
right=_operand(other),
)
)
def eq(self, other: object) -> Expr:
return self._binary("eq", other)
def ne(self, other: object) -> Expr:
return self._binary("ne", other)
def gt(self, other: object) -> Expr:
return self._binary("gt", other)
def lt(self, other: object) -> Expr:
return self._binary("lt", other)
def __eq__(self, other: object) -> Expr: # pyright: ignore[reportIncompatibleMethodOverride] # type: ignore[override] # ty: ignore[invalid-method-override]
return self._binary("eq", other)
def __ne__(self, other: object) -> Expr: # pyright: ignore[reportIncompatibleMethodOverride] # type: ignore[override] # ty: ignore[invalid-method-override]
return self._binary("ne", other)
def __gt__(self, other: object) -> Expr:
return self.gt(other)
def __lt__(self, other: object) -> Expr:
return self.lt(other)
def expr(value: PathExpr | GraphPath) -> PathExpr:
if isinstance(value, PathExpr):
return value
return PathExpr(path=value.value)
def state(field: str) -> PathExpr:
return expr(state_path(field))
def input(field: str) -> PathExpr:
return expr(input_path(field))
def context(field: str) -> PathExpr:
return expr(context_path(field))
def exists(value: PathExpr | GraphPath) -> Expr:
return Expr(ExistsCondition(op="exists", path=_path_str(value)))
def compile_condition(value: Condition | Expr) -> Condition:
if isinstance(value, Expr):
return value.to_condition()
return value
+33
View File
@@ -0,0 +1,33 @@
from __future__ import annotations
from collections.abc import Mapping
from typing import TypeAlias
from .paths import GraphPath
PathArg: TypeAlias = str | GraphPath
def normalize_path(path: PathArg) -> str:
if isinstance(path, GraphPath):
return path.value
return path
def bind_fields(**mapping: PathArg) -> dict[str, str]:
return {
normalize_path(source): destination for destination, source in mapping.items()
}
def bind_state(**mapping: PathArg) -> dict[str, str]:
return {
destination: normalize_path(target) for destination, target in mapping.items()
}
def merge_maps(*maps: Mapping[str, str]) -> dict[str, str]:
merged: dict[str, str] = {}
for mapping in maps:
merged.update(mapping)
return merged
+27
View File
@@ -0,0 +1,27 @@
from __future__ import annotations
from dataclasses import dataclass
@dataclass(frozen=True, slots=True)
class GraphPath:
value: str
def __str__(self) -> str:
return self.value
def graph_path(value: str) -> GraphPath:
return GraphPath(value)
def input_path(field: str) -> GraphPath:
return GraphPath(f"input.{field}")
def state_path(field: str) -> GraphPath:
return GraphPath(f"state.{field}")
def context_path(field: str) -> GraphPath:
return GraphPath(f"context.{field}")
+8 -32
View File
@@ -1,33 +1,9 @@
from __future__ import annotations from .dsl.mapping import PathArg, bind_fields, bind_state, merge_maps, normalize_path
from collections.abc import Mapping __all__ = [
from typing import TypeAlias "PathArg",
"bind_fields",
from .paths import GraphPath "bind_state",
"merge_maps",
PathArg: TypeAlias = str | GraphPath "normalize_path",
]
def normalize_path(path: PathArg) -> str:
if isinstance(path, GraphPath):
return path.value
return path
def bind_fields(**mapping: PathArg) -> dict[str, str]:
return {
normalize_path(source): destination for destination, source in mapping.items()
}
def bind_state(**mapping: PathArg) -> dict[str, str]:
return {
destination: normalize_path(target) for destination, target in mapping.items()
}
def merge_maps(*maps: Mapping[str, str]) -> dict[str, str]:
merged: dict[str, str] = {}
for mapping in maps:
merged.update(mapping)
return merged
+8 -26
View File
@@ -1,27 +1,9 @@
from __future__ import annotations from .dsl.paths import GraphPath, context_path, graph_path, input_path, state_path
from dataclasses import dataclass __all__ = [
"GraphPath",
"context_path",
@dataclass(frozen=True, slots=True) "graph_path",
class GraphPath: "input_path",
value: str "state_path",
]
def __str__(self) -> str:
return self.value
def graph_path(value: str) -> GraphPath:
return GraphPath(value)
def input_path(field: str) -> GraphPath:
return GraphPath(f"input.{field}")
def state_path(field: str) -> GraphPath:
return GraphPath(f"state.{field}")
def context_path(field: str) -> GraphPath:
return GraphPath(f"context.{field}")