refactor: replace jsonata with simpleeval for math evaluation

jsonata PyPI package has critical issues: no Python 3.12/3.13 wheels,
no ARM/Apple Silicon wheels, abandoned (last commit 2023), C extension.

Replace with simpleeval (pure Python, 3.4M downloads/month, MIT,
AST-based security). Add math module functions (sqrt, ceil, floor,
log, sin, cos, tan) and variadic sum() supporting both sum(values)
and sum(a, b, c). Pin version to >=1.0,<2.0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
dante01yoon 2026-02-28 21:16:23 +09:00
parent 245d3fd3d5
commit be3d1d9d5b
2 changed files with 34 additions and 6 deletions

View File

@ -1,24 +1,52 @@
"""Math expression node using JSONata for evaluation.
"""Math expression node using simpleeval for safe evaluation.
Provides a ComfyMathExpression node that evaluates JSONata expressions
Provides a ComfyMathExpression node that evaluates math expressions
against dynamically-grown numeric inputs.
"""
from __future__ import annotations
import jsonata as jsonata_lib
import math
from simpleeval import simple_eval
from typing_extensions import override
from comfy_api.latest import ComfyExtension, io
def _variadic_sum(*args):
"""Support both sum(values) and sum(a, b, c)."""
if len(args) == 1 and hasattr(args[0], "__iter__"):
return sum(args[0])
return sum(args)
MATH_FUNCTIONS = {
"sum": _variadic_sum,
"min": min,
"max": max,
"abs": abs,
"round": round,
"pow": pow,
"sqrt": math.sqrt,
"ceil": math.ceil,
"floor": math.floor,
"log": math.log,
"log2": math.log2,
"log10": math.log10,
"sin": math.sin,
"cos": math.cos,
"tan": math.tan,
}
def _positional_alias(index: int) -> str:
"""Convert 0-based index to single letter: 0->a, 1->b, ..., 25->z."""
return chr(ord("a") + index)
class MathExpressionNode(io.ComfyNode):
"""Evaluates a JSONata expression against dynamically-grown inputs."""
"""Evaluates a math expression against dynamically-grown inputs."""
@classmethod
def define_schema(cls) -> io.Schema:
@ -55,7 +83,7 @@ class MathExpressionNode(io.ComfyNode):
context: dict = dict(values)
context["values"] = list(values.values())
result = jsonata_lib.Jsonata(expression).evaluate(context)
result = simple_eval(expression, names=context, functions=MATH_FUNCTIONS)
if isinstance(result, bool) or not isinstance(result, (int, float)):
raise ValueError(
f"Math Expression '{expression}' must evaluate to a numeric result, "

View File

@ -24,7 +24,7 @@ av>=14.2.0
comfy-kitchen>=0.2.7
comfy-aimdo>=0.2.2
requests
jsonata
simpleeval>=1.0,<2.0
#non essential dependencies:
kornia>=0.7.1