The preview tokenizer never carried the axis accessor, so every consumer rendered the variable and left ".SHOES" beside it as text — which is why both the PREVIEW and RESOLVED lines read "a white t-shirt and denim skirt.SHOES". It now carries `axis` the same way it already carried `index`, and the combine editor resolves an axis read to a tag rather than to the variable's value. An axis the producer does not declare stays verbatim: swallowing it would delete text the user typed. Also undoes the leak from the previous commit. strip_internals' result IS the variable surface — the assembler's variables panel enumerates it, so keeping __wp_axes__ / __wp_picks__ there listed them as $__wp_axes__ chips. The tables are re-attached by with_resolver_tables at the one call site that needs them.
60 lines
2.0 KiB
Python
60 lines
2.0 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, with_resolver_tables
|
|
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_does_not_leak_the_tables_as_variables():
|
|
# The stripped dict IS the variable surface — the assembler's variables
|
|
# panel enumerates it, so a `__wp_axes__` key there renders as a chip
|
|
# named `$__wp_axes__`.
|
|
kept = strip_internals(_ctx())
|
|
assert not any(k.startswith("__") for k in kept)
|
|
|
|
|
|
def test_with_resolver_tables_reattaches_them_for_a_resolver_call():
|
|
kept = with_resolver_tables(strip_internals(_ctx()), _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", with_resolver_tables(strip_internals(_ctx()), _ctx())
|
|
)
|
|
assert out == "wearing sneakers"
|
|
|
|
|
|
def test_assembler_still_resolves_the_plain_var():
|
|
out = resolve_variables(
|
|
"wearing $outfit", with_resolver_tables(strip_internals(_ctx()), _ctx())
|
|
)
|
|
assert out == "wearing a white t-shirt and denim skirt"
|