diff options
| author | Christian Kolset <christian.kolset@gmail.com> | 2026-06-09 22:35:40 -0600 |
|---|---|---|
| committer | Christian Kolset <christian.kolset@gmail.com> | 2026-06-09 22:35:40 -0600 |
| commit | d396692de571445537e617ac31627d7bd7ab84aa (patch) | |
| tree | c60570493f03addf770b7df5b49e69363fc69b80 /core/signal_processor.py | |
| parent | f8b5e47ffe9a52bd28ad5d953a551ccb92cbbb09 (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/signal_processor.py')
| -rw-r--r-- | core/signal_processor.py | 27 |
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 |
