Fix sync IO primitives unreachable from sx_ref.py evaluator
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m49s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m49s
app-url, asset-url, config, jinja-global, relations-from are declared as IO in boundary.sx but called inline in .sx code (inside let/filter). async_eval_ref.py only intercepts IO at the top level — nested calls fall through to sx_ref.eval_expr which couldn't find them. Register sync bridge wrappers directly in _PRIMITIVES (bypassing @register_primitive validation since they're boundary.sx, not primitives.sx). Both async and sync eval paths now work. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -558,3 +558,55 @@ def prim_merge_styles(*styles: Any) -> Any:
|
||||
if len(valid) == 1:
|
||||
return valid[0]
|
||||
return merge_styles(valid)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Sync IO bridge primitives
|
||||
#
|
||||
# These are declared in boundary.sx (I/O tier), NOT primitives.sx.
|
||||
# They bypass @register_primitive validation because they aren't pure.
|
||||
# But they must be evaluator-visible because they're called inline in .sx
|
||||
# code (inside let, filter, etc.) where the async IO interceptor can't
|
||||
# reach them — particularly in async_eval_ref.py which only intercepts
|
||||
# IO at the top level.
|
||||
#
|
||||
# The async evaluators also intercept these via IO_PRIMITIVES, so the
|
||||
# async path works too. This registration ensures the sync fallback works.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _bridge_app_url(service, *path_parts):
|
||||
from shared.infrastructure.urls import app_url
|
||||
path = str(path_parts[0]) if path_parts else "/"
|
||||
return app_url(str(service), path)
|
||||
|
||||
def _bridge_asset_url(*path_parts):
|
||||
from shared.infrastructure.urls import asset_url
|
||||
path = str(path_parts[0]) if path_parts else ""
|
||||
return asset_url(path)
|
||||
|
||||
def _bridge_config(key):
|
||||
from shared.config import config
|
||||
cfg = config()
|
||||
return cfg.get(str(key))
|
||||
|
||||
def _bridge_jinja_global(key, *default):
|
||||
from quart import current_app
|
||||
d = default[0] if default else None
|
||||
return current_app.jinja_env.globals.get(str(key), d)
|
||||
|
||||
def _bridge_relations_from(entity_type):
|
||||
from shared.sx.relations import relations_from
|
||||
return [
|
||||
{
|
||||
"name": d.name, "from_type": d.from_type, "to_type": d.to_type,
|
||||
"cardinality": d.cardinality, "nav": d.nav,
|
||||
"nav_icon": d.nav_icon, "nav_label": d.nav_label,
|
||||
}
|
||||
for d in relations_from(str(entity_type))
|
||||
]
|
||||
|
||||
_PRIMITIVES["app-url"] = _bridge_app_url
|
||||
_PRIMITIVES["asset-url"] = _bridge_asset_url
|
||||
_PRIMITIVES["config"] = _bridge_config
|
||||
_PRIMITIVES["jinja-global"] = _bridge_jinja_global
|
||||
_PRIMITIVES["relations-from"] = _bridge_relations_from
|
||||
|
||||
Reference in New Issue
Block a user