diff --git a/source/safe_eval/__init__.py b/source/safe_eval/__init__.py index 77babdb..aca6197 100644 --- a/source/safe_eval/__init__.py +++ b/source/safe_eval/__init__.py @@ -1,2 +1,15 @@ -from source.safe_eval.safe_eval import safe_eval -from source.safe_eval.multiple_safe_eval import multiple_safe_eval +from typing import Callable +from source.translation import translate as _ + + +class BetterSafeEvalError(Exception): + def __init__(self, template: str): + super().__init__(_("SAFE_EVAL_ERROR", " (", "TEMPLATE_USED", " : ", repr(template), ")")) + + +def better_safe_eval_error(func: Callable, template: str): + def wrapped(*args, **kwargs): + try: return func(*args, **kwargs) + except Exception as exc: raise BetterSafeEvalError(template) from exc + + return wrapped diff --git a/source/safe_eval/multiple_safe_eval.py b/source/safe_eval/multiple_safe_eval.py index 39e1927..c68a53f 100644 --- a/source/safe_eval/multiple_safe_eval.py +++ b/source/safe_eval/multiple_safe_eval.py @@ -1,6 +1,7 @@ from typing import TYPE_CHECKING, Iterable, Callable -from source.safe_eval import safe_eval +from source.safe_eval.safe_eval import safe_eval +from source.safe_eval import better_safe_eval_error if TYPE_CHECKING: from source import TemplateMultipleSafeEval, TemplateSafeEval, Env @@ -40,9 +41,9 @@ def multiple_safe_eval(template: "TemplateMultipleSafeEval", env: "Env" = None, )) template = template[token_end:] - return lambda *args, **kwargs: "".join([ + return better_safe_eval_error(lambda *args, **kwargs: "".join([ str(part(*args, **kwargs)) if callable(part) else part for part in lambda_templates - ]) + ]), template=template) diff --git a/source/safe_eval/safe_eval.py b/source/safe_eval/safe_eval.py index effef6d..5b3d210 100644 --- a/source/safe_eval/safe_eval.py +++ b/source/safe_eval/safe_eval.py @@ -2,6 +2,7 @@ import ast import copy from typing import TYPE_CHECKING, Iterable, Callable +from source.safe_eval import better_safe_eval_error from source.safe_eval.macros import replace_macro from source.safe_eval.safe_function import get_all_safe_functions from source.translation import translate as _ @@ -126,7 +127,7 @@ def safe_eval(template: "TemplateSafeEval", env: "Env" = None, macros: dict[str, # return the evaluated formula lambda_template = eval(compile(expression, "", "eval"), globals_, locals_) self.safe_eval_cache[template_key] = lambda_template # cache the callable for potential latter call - return lambda_template + return better_safe_eval_error(lambda_template, template=template) # TODO: disable some method and function call. for example, mod_config.path.unlink() is dangerous !