add the thing formally
This commit is contained in:
@@ -43,10 +43,12 @@ from .nodes import (
|
||||
AsyncRegistryHandler,
|
||||
NodeReturn,
|
||||
NodeSpec,
|
||||
Nothing,
|
||||
SyncRegistryHandler,
|
||||
build_async_registry,
|
||||
build_registry,
|
||||
node,
|
||||
outcome,
|
||||
)
|
||||
from .schemas import StateFieldMetadata, state_field
|
||||
from .subgraph import subgraph_node
|
||||
@@ -64,6 +66,7 @@ __all__ = [
|
||||
"PickKeyInput",
|
||||
"NodeReturn",
|
||||
"NodeSpec",
|
||||
"Nothing",
|
||||
"AsyncRegistryHandler",
|
||||
"SyncRegistryHandler",
|
||||
"SequenceInput",
|
||||
@@ -95,6 +98,7 @@ __all__ = [
|
||||
"length",
|
||||
"pick_key",
|
||||
"node",
|
||||
"outcome",
|
||||
"state",
|
||||
"state_field",
|
||||
"state_path",
|
||||
|
||||
@@ -13,7 +13,7 @@ from .callables import (
|
||||
from .inference import accepts_context, infer_models, is_basemodel_subclass
|
||||
from .decorator import node
|
||||
from .registry import build_async_registry, build_registry
|
||||
from .result import NodeReturn
|
||||
from .result import NodeReturn, Nothing, outcome
|
||||
from .schema import schema_ref_for
|
||||
from .spec import NodeSpec
|
||||
|
||||
@@ -27,6 +27,7 @@ __all__ = [
|
||||
"NodeCallable",
|
||||
"NodeReturn",
|
||||
"NodeSpec",
|
||||
"Nothing",
|
||||
"OutputT",
|
||||
"PlainNodeCallable",
|
||||
"SyncRegistryHandler",
|
||||
@@ -36,5 +37,6 @@ __all__ = [
|
||||
"infer_models",
|
||||
"is_basemodel_subclass",
|
||||
"node",
|
||||
"outcome",
|
||||
"schema_ref_for",
|
||||
]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Generic, TypeVar
|
||||
from typing import Generic, TypeVar, overload
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
@@ -14,3 +14,25 @@ class NodeReturn(Generic[OutputT_co]):
|
||||
|
||||
outcome: str
|
||||
output: OutputT_co
|
||||
|
||||
|
||||
class Nothing(BaseModel):
|
||||
"""Empty output model for nodes that only choose an outcome."""
|
||||
|
||||
|
||||
@overload
|
||||
def outcome(name: str) -> NodeReturn[Nothing]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def outcome(name: str, output: OutputT_co) -> NodeReturn[OutputT_co]: ...
|
||||
|
||||
|
||||
def outcome(
|
||||
name: str,
|
||||
output: OutputT_co | None = None,
|
||||
) -> NodeReturn[OutputT_co] | NodeReturn[Nothing]:
|
||||
"""Create a node result with an optional output model."""
|
||||
if output is None:
|
||||
return NodeReturn(outcome=name, output=Nothing())
|
||||
return NodeReturn(outcome=name, output=output)
|
||||
|
||||
@@ -8,12 +8,14 @@ from .nodes import (
|
||||
NodeCallable,
|
||||
NodeReturn,
|
||||
NodeSpec,
|
||||
Nothing,
|
||||
OutputT,
|
||||
PlainNodeCallable,
|
||||
SyncRegistryHandler,
|
||||
build_async_registry,
|
||||
build_registry,
|
||||
node,
|
||||
outcome,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
@@ -26,10 +28,12 @@ __all__ = [
|
||||
"NodeCallable",
|
||||
"NodeReturn",
|
||||
"NodeSpec",
|
||||
"Nothing",
|
||||
"OutputT",
|
||||
"PlainNodeCallable",
|
||||
"SyncRegistryHandler",
|
||||
"build_async_registry",
|
||||
"build_registry",
|
||||
"node",
|
||||
"outcome",
|
||||
]
|
||||
|
||||
@@ -21,10 +21,9 @@ from pydantic import BaseModel, Field
|
||||
from wf_authoring import node
|
||||
from wf_authoring import NodeReturn
|
||||
from wf_authoring.dsl.conditions import expr, state
|
||||
from wf_authoring.nodes.registry import build_registry
|
||||
from wf_authoring.nodes.result import Nothing, outcome
|
||||
from wf_authoring.schemas import state_field
|
||||
from wf_core.run_state import RunStatus
|
||||
from wf_core.runtime.engine import execute_workflow
|
||||
from wf_core.tokens import END
|
||||
|
||||
# i copy things over, not the greatest design but im not doing deep fixes.
|
||||
@@ -64,7 +63,7 @@ class ContextInput(BaseModel):
|
||||
|
||||
|
||||
class how_do_i_explain_this(BaseModel):
|
||||
pity_120_available: bool = True
|
||||
pity_120_available: bool = Field(default=True)
|
||||
|
||||
|
||||
class Input(Counters, ContextInput, Countdown, how_do_i_explain_this):
|
||||
@@ -160,9 +159,6 @@ class State(
|
||||
# context: Context
|
||||
|
||||
|
||||
class Nothing(BaseModel): ... # variance shit IDC
|
||||
|
||||
|
||||
# to the functions
|
||||
# @node(outcomes=("ok", "end")) # breaks because of input | nothing
|
||||
@node
|
||||
@@ -209,12 +205,8 @@ def rate_booster(c: Counters) -> NodeReturn[Nothing]:
|
||||
rate_guarantee, which is no op.
|
||||
"""
|
||||
if c.counter["c_80"] >= 65:
|
||||
return NodeReturn("65", Nothing())
|
||||
return NodeReturn("0", Nothing())
|
||||
|
||||
|
||||
def s(o: str) -> NodeReturn[Nothing]:
|
||||
return NodeReturn(o, Nothing())
|
||||
return outcome("65")
|
||||
return outcome("0")
|
||||
|
||||
|
||||
def _popped(storage: list[Entity]) -> bool:
|
||||
@@ -223,7 +215,7 @@ def _popped(storage: list[Entity]) -> bool:
|
||||
|
||||
@node
|
||||
def popped(s: Storage) -> how_do_i_explain_this:
|
||||
return how_do_i_explain_this(pity_120_available=_popped(s.storage))
|
||||
return how_do_i_explain_this(pity_120_available=not _popped(s.storage))
|
||||
|
||||
|
||||
@node(outcomes=("240", "80", "10", "1"))
|
||||
@@ -238,12 +230,12 @@ def pre_roll_router(c: CountersContextOutputInputAhhModelType) -> NodeReturn[Not
|
||||
if c.context["type"] == "banner" and (
|
||||
(sc == 120 and c.pity_120_available) or (sc > 0 and sc % 240 == 0)
|
||||
):
|
||||
return NodeReturn("240", Nothing())
|
||||
return outcome("240")
|
||||
if ct.get("c_80", 0) % 80 == 0:
|
||||
return s("80")
|
||||
return outcome("80")
|
||||
if ct.get("c_10", 0) % 10 == 0:
|
||||
return s("10")
|
||||
return s("1")
|
||||
return outcome("10")
|
||||
return outcome("1")
|
||||
|
||||
|
||||
# now to the weeds of it. a Class!
|
||||
@@ -398,7 +390,7 @@ def tick(state: Countdown) -> Countdown:
|
||||
|
||||
@node(outcomes=("tick", END))
|
||||
def keep_rolling(state: Countdown) -> NodeReturn[Nothing]:
|
||||
return s("tick") if (state.countdown or 0) > 0 else s(END)
|
||||
return outcome("tick") if (state.countdown or 0) > 0 else outcome(END)
|
||||
|
||||
|
||||
gacha = WorkflowBuilder(
|
||||
@@ -549,34 +541,25 @@ def build_input(context: Context):
|
||||
return dec
|
||||
|
||||
|
||||
def execute(graph: WorkflowBuilder, input: Input):
|
||||
c = graph.compile()
|
||||
r = build_registry(*(graph.node_specs.values()))
|
||||
i = input.model_dump()
|
||||
pprint(i)
|
||||
pprint(c)
|
||||
pprint(r)
|
||||
return execute_workflow(c, i, r)
|
||||
|
||||
|
||||
# twice in a row! it took 100+ and a miss tho
|
||||
|
||||
|
||||
def test():
|
||||
assert 240 - 135 + 20 >= 120, "my math!"
|
||||
d = execute(
|
||||
gacha,
|
||||
d = gacha.execute(
|
||||
build_input(context)(
|
||||
20,
|
||||
20, # lets be optimistic
|
||||
rolled_previously=240 - 135,
|
||||
until_5=5,
|
||||
until_6=73,
|
||||
good_stuff=False, # lets pretend
|
||||
),
|
||||
).model_dump()
|
||||
)
|
||||
assert d.status == RunStatus.COMPLETED, "oops"
|
||||
state = State.model_validate(d.state)
|
||||
assert any(i["name"] in context["pool"]["n_240"] for i in state.storage)
|
||||
assert any(
|
||||
i["name"] in context["pool"]["n_240"] for i in state.storage
|
||||
), "pity logic failed"
|
||||
pprint(state.storage)
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from wf_authoring import build_registry, node
|
||||
from wf_authoring import Nothing, build_registry, node, outcome
|
||||
from wf_core import RuntimeContext
|
||||
|
||||
|
||||
@@ -60,3 +60,19 @@ def test_node_can_alias_spec_with_direct_metadata_call() -> None:
|
||||
assert alias.fn is echo.fn
|
||||
assert alias.input_model is AliasInput
|
||||
assert alias.output_model is AliasOutput
|
||||
|
||||
|
||||
def test_outcome_returns_nothing_output_by_default() -> None:
|
||||
result = outcome("skip")
|
||||
|
||||
assert result.outcome == "skip"
|
||||
assert isinstance(result.output, Nothing)
|
||||
|
||||
|
||||
def test_outcome_can_wrap_explicit_output() -> None:
|
||||
output = AliasOutput(value="hello")
|
||||
|
||||
result = outcome("ok", output)
|
||||
|
||||
assert result.outcome == "ok"
|
||||
assert result.output is output
|
||||
|
||||
Reference in New Issue
Block a user