summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorChristian Kolset <christian.kolset@gmail.com>2026-06-09 22:35:40 -0600
committerChristian Kolset <christian.kolset@gmail.com>2026-06-09 22:35:40 -0600
commitd396692de571445537e617ac31627d7bd7ab84aa (patch)
treec60570493f03addf770b7df5b49e69363fc69b80 /core
parentf8b5e47ffe9a52bd28ad5d953a551ccb92cbbb09 (diff)
Fix custom_script execution + add templates for expression/function kinds
- custom_script now uses exec-style (assign to `result`) matching the built-in templates — previously auto-wrapped in def compute() which had no return statement, causing state and channel vars to silently fail - function kind unchanged: auto-wraps body as def compute(x,t); use return - Add SCRIPT_TEMPLATES for expression, function, custom_script kinds; shown automatically when user switches to a script kind (replacing stale code from previous kind) - New channels default to template when no saved code exists Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'core')
-rw-r--r--core/signal_processor.py27
1 files changed, 22 insertions, 5 deletions
diff --git a/core/signal_processor.py b/core/signal_processor.py
index 8ac4d8c..e2752cd 100644
--- a/core/signal_processor.py
+++ b/core/signal_processor.py
@@ -286,7 +286,8 @@ class DerivedChannel:
self._fn = _expr_fn
- elif self.kind in ("function", "custom_script"):
+ elif self.kind == "function":
+ # Auto-wrap body as def compute(x, t): ... return <value>
src = self.script
if not src.strip().startswith("def compute"):
src = "def compute(x, t):\n" + "\n".join(
@@ -297,9 +298,8 @@ class DerivedChannel:
_fn_ref = _exec_ns["compute"]
_state = self._exec_state
- def _script_fn(inputs, t, sv,
- _f=_fn_ref, _ns=_exec_ns, _st=_state, _names=src_names):
- # refresh mutable globals before each call so scripts see live values
+ def _fn_fn(inputs, t, sv,
+ _f=_fn_ref, _ns=_exec_ns, _st=_state, _names=src_names):
_ns["vars"] = sv
_ns["state"] = _st
for i, name in enumerate(_names):
@@ -307,7 +307,24 @@ class DerivedChannel:
_ns[name] = inputs[i]
return float(_f(inputs, t))
- self._fn = _script_fn
+ self._fn = _fn_fn
+
+ elif self.kind == "custom_script":
+ # Exec-style: script assigns to `result`
+ code = compile(self.script, "<custom_script>", "exec")
+ _state = self._exec_state
+
+ def _cs_fn(inputs, t, sv, _code=code, _names=src_names, _st=_state):
+ ns = {"x": inputs, "t": t, "math": math, "vars": sv, "state": _st}
+ for i, name in enumerate(_names):
+ if i < len(inputs):
+ ns[name] = inputs[i]
+ exec(_code, ns)
+ if "result" not in ns:
+ raise NameError("custom_script must assign to 'result'")
+ return float(ns["result"])
+
+ self._fn = _cs_fn
else:
# Built-in kinds handled in SignalProcessor._compute_derived