Files
DumiFlex-ComfyUI-Wildcard-P…/tests/wp_nodes/test_assembler_socket_axes.py
T
DumiFlex 934f7dc92d fix(axes): drive constraints by the rolled tag, fix the assembler read, preserve on import
An accepts axis rolls one tag per pick (read as $var.AXIS), but a constraint
sourced from it folded over the option's whole menu instead of that rolled tag,
so $outfit.SHOES and the constrained $shoes could disagree. The source now
sends only the rolled winner; a target accepts axis OR-folds so a multi-tag
option survives when any alternative is allowed, then its own roll is pinned to
the allowed tag -- $source.AXIS == $target.AXIS under a diagonal. Classify
groups are unchanged (multiply).

The assembler also rendered $var.AXIS empty: __wp_axes__ crosses the socket on
ContextPayload.internals but the node only merged the internal-flag map; it now
merges the whole carve-out so the accessor resolves.

Import: the community validators silently dropped tag_group_kinds (and the
constraint target_select) because the lenient payload object never listed them,
degrading a shared accepts axis to classify. Both are now in the v2/v1
validators + the engine-parity fixtures, with preservation tests. Engine math
mirrored in TS via the shared corpus.
2026-08-20 23:58:44 +03:00

50 lines
2.0 KiB
Python

"""The assembler must resolve `$var.AXIS` when the axis table arrives via the
SOCKET — i.e. on `ContextPayload.internals`, not pre-merged into the ctx.
`tests/engine/test_assembler_accessor.py` covers the resolver helper with
`__wp_axes__` already present in the ctx; it never exercised the NODE. The node
reads a socket payload where `build_payload` files the table under `internals`
(the `__`-prefixed key is stripped from the user-facing `context`). The node
merged only `__wp_internal_flags__` back, so `$outfit.SHOES` rendered "" across
the socket while the identical read resolved one node upstream — a green helper
test over a broken node. These tests exercise the node's socket path directly.
"""
from wp_nodes.assembler_node import WPPromptAssembler
from wp_nodes.types import ContextPayload
def _payload() -> ContextPayload:
# Exactly the shape build_payload emits: axes stripped from `context`,
# carried on `internals`.
return ContextPayload(
context={"outfit": "a white t-shirt and denim skirt"},
internals={
"__wp_axes__": {"outfit": {"SHOES": "sandals"}},
"__wp_picks__": {},
},
)
def test_axis_read_resolves_from_socket_internals():
out = WPPromptAssembler.execute(_payload(), "wearing $outfit.SHOES")
assert out.values[0] == "wearing sandals"
def test_plain_var_still_resolves():
out = WPPromptAssembler.execute(_payload(), "wearing $outfit")
assert out.values[0] == "wearing a white t-shirt and denim skirt"
def test_internal_flagged_var_still_hidden_after_merge():
# The flag map also rides on internals; merging the WHOLE carve-out must not
# regress the hide-from-prompt filter.
p = ContextPayload(
context={"outfit": "tee", "secret": "hidden"},
internals={
"__wp_internal_flags__": {"secret": True},
"__wp_axes__": {},
},
)
out = WPPromptAssembler.execute(p, "$outfit $secret")
assert out.values[0].strip() == "tee"