Files
DumiFlex-ComfyUI-Wildcard-P…/tests/engine/test_assembler_accessor.py
T
DumiFlex c4e1663210 fix(axes): carry axes across writers, resolve them in previews and the assembler
Three separate places dropped an axis read on the floor:

- The producer map replaced a variable's record wholesale on every later
  write, so a derivation or injector rebinding $outfit erased the wildcard's
  axes. The engine keys __wp_axes__ by binding at pick time and a rebind
  never clears it, so the axes must survive the override. Carried forward in
  both the graph walk and the same-node sibling merge.

- The static preview resolver knew only the numeric .K accessor, so
  "$outfit.SHOES" substituted $outfit and stranded ".SHOES" — the preview and
  resolved lines both read "a white t-shirt and denim skirt.SHOES". It now
  resolves an axis to its first tag, the same deterministic convention @{uuid}
  expansion already uses, and leaves an accessor it cannot resolve verbatim
  rather than deleting text.

- strip_internals runs at the prompt-render boundary and dropped every
  __-prefixed key, __wp_axes__ and __wp_picks__ included. The assembler
  therefore rendered "$outfit.SHOES" and "$outfit.0" as literal text while the
  identical template resolved one node upstream. Those two tables are read by
  key, never as variables, so keeping them cannot leak a $var.
2026-08-19 00:51:50 +03:00

48 lines
1.5 KiB
Python

"""The assembler must resolve the same accessor grammar a Combine does.
`$var.AXIS` and `$var.N` read tables the engine keeps under `__`-prefixed
keys. `strip_internals` runs at the prompt-render boundary and dropped every
such key, so the assembler rendered the accessor as literal text while the
identical template resolved correctly one node upstream.
"""
import random
from engine.context import strip_internals
from engine.template import resolve_variables
def _ctx() -> dict:
return {
"outfit": "a white t-shirt and denim skirt",
"__wp_rng__": random.Random(0),
"__wp_warnings__": [],
"__wp_axes__": {"outfit": {"SHOES": "sneakers"}},
"__wp_picks__": {},
}
def test_strip_internals_keeps_the_accessor_tables():
kept = strip_internals(_ctx())
assert kept["__wp_axes__"] == {"outfit": {"SHOES": "sneakers"}}
assert "__wp_picks__" in kept
def test_strip_internals_still_drops_bookkeeping_and_internal_vars():
ctx = _ctx()
ctx["__wp_trace__"] = ["noise"]
ctx["secret"] = "hidden"
ctx["__wp_internal_flags__"] = {"secret": True}
kept = strip_internals(ctx)
assert "__wp_trace__" not in kept
assert "secret" not in kept
def test_assembler_resolves_an_axis_read():
out = resolve_variables("wearing $outfit.SHOES", strip_internals(_ctx()))
assert out == "wearing sneakers"
def test_assembler_still_resolves_the_plain_var():
out = resolve_variables("wearing $outfit", strip_internals(_ctx()))
assert out == "wearing a white t-shirt and denim skirt"