Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-asteval for openSUSE:Factory checked in at 2026-01-22 15:18:03 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-asteval (Old) and /work/SRC/openSUSE:Factory/.python-asteval.new.1928 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-asteval" Thu Jan 22 15:18:03 2026 rev:23 rq:1328623 version:1.0.8 Changes: -------- --- /work/SRC/openSUSE:Factory/python-asteval/python-asteval.changes 2025-11-14 16:14:08.815382415 +0100 +++ /work/SRC/openSUSE:Factory/.python-asteval.new.1928/python-asteval.changes 2026-01-22 15:19:31.623601881 +0100 @@ -1,0 +2,12 @@ +Thu Jan 22 08:37:51 UTC 2026 - Dirk Müller <[email protected]> + +- update to 1.0.8: + * fix bug (#146) so that `return` from a Procedure does not + interrupt the calling code block + * remove numpy.memmap from default methods + * add discussion of numpy functions/objects that can open files + * add support and tests for `lambda` expressions + * add default permissions to github actions + * update README, doc, remove cruft + +------------------------------------------------------------------- Old: ---- asteval-1.0.7.tar.gz New: ---- asteval-1.0.8.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-asteval.spec ++++++ --- /var/tmp/diff_new_pack.u2yJCu/_old 2026-01-22 15:19:32.239627506 +0100 +++ /var/tmp/diff_new_pack.u2yJCu/_new 2026-01-22 15:19:32.239627506 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-asteval # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-asteval -Version: 1.0.7 +Version: 1.0.8 Release: 0 Summary: Safe, minimalistic evaluator of python expression using ast module License: MIT ++++++ asteval-1.0.7.tar.gz -> asteval-1.0.8.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/.gitattributes new/asteval-1.0.8/.gitattributes --- old/asteval-1.0.7/.gitattributes 2025-11-06 22:41:41.000000000 +0100 +++ new/asteval-1.0.8/.gitattributes 1970-01-01 01:00:00.000000000 +0100 @@ -1 +0,0 @@ -asteval/_version.py export-subst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/.github/workflows/macos_numpy.yml new/asteval-1.0.8/.github/workflows/macos_numpy.yml --- old/asteval-1.0.7/.github/workflows/macos_numpy.yml 2025-11-06 22:41:41.000000000 +0100 +++ new/asteval-1.0.8/.github/workflows/macos_numpy.yml 2025-12-11 22:40:31.000000000 +0100 @@ -1,4 +1,7 @@ name: test on macos, with numpy +permissions: + contents: read + pull-requests: write on: [push] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/.github/workflows/ubuntu_nonumpy.yml new/asteval-1.0.8/.github/workflows/ubuntu_nonumpy.yml --- old/asteval-1.0.7/.github/workflows/ubuntu_nonumpy.yml 2025-11-06 22:41:41.000000000 +0100 +++ new/asteval-1.0.8/.github/workflows/ubuntu_nonumpy.yml 2025-12-11 22:40:31.000000000 +0100 @@ -1,4 +1,7 @@ name: test on ubuntu, without numpy +permissions: + contents: read + pull-requests: write on: push: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/.github/workflows/ubuntu_numpy.yml new/asteval-1.0.8/.github/workflows/ubuntu_numpy.yml --- old/asteval-1.0.7/.github/workflows/ubuntu_numpy.yml 2025-11-06 22:41:41.000000000 +0100 +++ new/asteval-1.0.8/.github/workflows/ubuntu_numpy.yml 2025-12-11 22:40:31.000000000 +0100 @@ -1,4 +1,7 @@ name: test on ubuntu, with numpy and numpy_financial +permissions: + contents: read + pull-requests: write on: push: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/.github/workflows/windows_numpy.yml new/asteval-1.0.8/.github/workflows/windows_numpy.yml --- old/asteval-1.0.7/.github/workflows/windows_numpy.yml 2025-11-06 22:41:41.000000000 +0100 +++ new/asteval-1.0.8/.github/workflows/windows_numpy.yml 2025-12-11 22:40:31.000000000 +0100 @@ -1,4 +1,7 @@ name: test on windows, with numpy +permissions: + contents: read + pull-requests: write on: [push] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/PKG-INFO new/asteval-1.0.8/PKG-INFO --- old/asteval-1.0.7/PKG-INFO 2025-11-06 22:41:52.521916200 +0100 +++ new/asteval-1.0.8/PKG-INFO 2025-12-17 21:54:33.178054800 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: asteval -Version: 1.0.7 +Version: 1.0.8 Summary: Safe, minimalistic evaluator of python expression using ast module Author-email: Matthew Newville <[email protected]> License-Expression: MIT @@ -77,45 +77,77 @@ Use ``pip install asteval`` to install the asteval library. -Asteval requires Python 3.8 or higher. If installed, many functions and -constants from Numpy will be used by default. - -About ASTEVAL --------------- - -ASTEVAL is a safe(ish) evaluator of Python expressions and statements, -using Python's ast module. The idea is to provide a simple, safe, and -robust miniature mathematical language that can handle user input. The -emphasis here is on mathematical expressions so that many functions from -``numpy`` are imported and used if available. - -Many Python language constructs are supported by default, These include -slicing, subscripting, list comprehension, conditionals (if-elif-else -blocks and if expressions), flow control (for loops, while loops, and -try-except-finally blocks). All data are Python objects and built-in data -structures (dictionaries, tuples, lists, Numpy arrays, strings) are fully -supported by default. - -Many of the standard built-in Python functions are available, as are all -mathematical functions from the math module. If the Numpy module is -installed, many of its functions will also be available. Users can define -and run their own functions within the confines of the limitations of -Asteval. - -There are several absences and differences with Python, and Asteval is by -no means an attempt to reproduce Python with its own ast module. Some of -the most important differences and absences are: - - 1. Variable and function symbol names are held in a simple symbol - table (a single dictionary), giving a flat namespace. - 2. creating classes is not supported. - 3. importing modules is not supported by default - it can be enabled. - 4. function decorators, yield, lambda, exec, and eval are not supported. - 5. files can only be opened in read-only mode. - -In addition, accessing many internal methods and classes of objects is -forbidden in order to strengthen Asteval against malicious user code. +Asteval supports Python 3.10 or higher. No modules outside of the +standard library are required, though if `NumPy` is installed, many +functions from it will be used by default. + +About Asteval +---------------- + +Asteval is a safe(ish) evaluator of Python expressions and statements, +using Python's ast module. It provides an easy-to-use restricted +Python interpreter that supports a pretty complete subset of the +Python language and can handle user input more safely than Python's +``eval()``. Asteval emphasizes mathematical expressions so that many +functions from ``NumPy`` are imported and used if available, but also +provides a pretty complete subset of the Python language. It can be +used as an embedded macro language within a large application or as a +simple calculator for mathematical calculations. + +Asteval supports many Python language constructs by default, including +conditionals (if-elif-else blocks and if expressions), flow control +(for loops, while loops, with blocks, and try-except-finally blocks), +list comprehension, slicing, subscripting, and f-strings. All data +are Python objects and the standard built-in data structures +(dictionaries, tuples, lists, sets, strings, functions, and ``Numpy`` +nd-arrays) are well supported, and most public attributes and methods +of these objects are available. Asteval does place some limitations +on "looking under the hood" to get private and potentially unsafe +methods. + +Many of the standard built-in Python functions are available, as are +the functions from the ``math`` module. Some built-in operators and +functions, such as `getattr`, and `setattr` are not allowed, and some +including `open` and `**` are replaced with versions intended to make +them safer for user input. If the ``NumPy`` is installed, many of its +functions will also be available. Programmers can add custom +functions and data of their own into each Asteval session. Users can +define and run their own functions within the confines of the +limitations of the Asteval language. + +Asteval converts user input into Python's own abstract syntax tree +(AST) representation and determines the result by walking through that +tree. This approach guarantees the parsing of input will be identical +to that of Python, eliminating many lexing and parsing challenges and +generating a result that is straightforward to interpret. This makes +"correctness" easy to test and verify with high confidence, so that +the emphasis can be placed on balancing functionality with safety. + +There are several absences and differences with Python, and Asteval is +by no means an attempt to reproduce Python with its own ``ast`` +module. While, it does support a large subset of Python, the +following features found in Python are not supported in Asteval: + + 1. creating classes is not supported + 2. many internal methods and classes of Python objects, + especially ``__dunder__`` methods cannot be accessed. + 3. `eval`, `exec`, `yield`, `async`, `match/case`, function + decorators, generators, and type annotations are not supported. + 4. `f-strings` are supported, but `t-strings` are not supported. + 5. importing modules is not supported by default, though it can be + enabled. + +Most of these omissions and limitations are intentional, and aimed to +strengthen Asteval against dangerous user code. A few of these (say, +`match/case` and `t-strings`) omissions may simply be viewed as not +particularly compelling need for an embedded interpreter exposed to +user input. + +Even with these restrictions, Asteval provides a pretty complete and +usable scripting or "macro" language that can easily be embedded into +a larger GUI or Web application that can handle user input without +many of the risks associated with using Python's `eval()`. Matt Newville <[email protected]> -Last Update: 30-June-2024 +Last Update: 17-Dec-2025 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/README.rst new/asteval-1.0.8/README.rst --- old/asteval-1.0.7/README.rst 2025-11-06 22:41:41.000000000 +0100 +++ new/asteval-1.0.8/README.rst 2025-12-17 20:39:37.000000000 +0100 @@ -42,45 +42,77 @@ Use ``pip install asteval`` to install the asteval library. -Asteval requires Python 3.8 or higher. If installed, many functions and -constants from Numpy will be used by default. - -About ASTEVAL --------------- - -ASTEVAL is a safe(ish) evaluator of Python expressions and statements, -using Python's ast module. The idea is to provide a simple, safe, and -robust miniature mathematical language that can handle user input. The -emphasis here is on mathematical expressions so that many functions from -``numpy`` are imported and used if available. - -Many Python language constructs are supported by default, These include -slicing, subscripting, list comprehension, conditionals (if-elif-else -blocks and if expressions), flow control (for loops, while loops, and -try-except-finally blocks). All data are Python objects and built-in data -structures (dictionaries, tuples, lists, Numpy arrays, strings) are fully -supported by default. - -Many of the standard built-in Python functions are available, as are all -mathematical functions from the math module. If the Numpy module is -installed, many of its functions will also be available. Users can define -and run their own functions within the confines of the limitations of -Asteval. - -There are several absences and differences with Python, and Asteval is by -no means an attempt to reproduce Python with its own ast module. Some of -the most important differences and absences are: - - 1. Variable and function symbol names are held in a simple symbol - table (a single dictionary), giving a flat namespace. - 2. creating classes is not supported. - 3. importing modules is not supported by default - it can be enabled. - 4. function decorators, yield, lambda, exec, and eval are not supported. - 5. files can only be opened in read-only mode. - -In addition, accessing many internal methods and classes of objects is -forbidden in order to strengthen Asteval against malicious user code. +Asteval supports Python 3.10 or higher. No modules outside of the +standard library are required, though if `NumPy` is installed, many +functions from it will be used by default. + +About Asteval +---------------- + +Asteval is a safe(ish) evaluator of Python expressions and statements, +using Python's ast module. It provides an easy-to-use restricted +Python interpreter that supports a pretty complete subset of the +Python language and can handle user input more safely than Python's +``eval()``. Asteval emphasizes mathematical expressions so that many +functions from ``NumPy`` are imported and used if available, but also +provides a pretty complete subset of the Python language. It can be +used as an embedded macro language within a large application or as a +simple calculator for mathematical calculations. + +Asteval supports many Python language constructs by default, including +conditionals (if-elif-else blocks and if expressions), flow control +(for loops, while loops, with blocks, and try-except-finally blocks), +list comprehension, slicing, subscripting, and f-strings. All data +are Python objects and the standard built-in data structures +(dictionaries, tuples, lists, sets, strings, functions, and ``Numpy`` +nd-arrays) are well supported, and most public attributes and methods +of these objects are available. Asteval does place some limitations +on "looking under the hood" to get private and potentially unsafe +methods. + +Many of the standard built-in Python functions are available, as are +the functions from the ``math`` module. Some built-in operators and +functions, such as `getattr`, and `setattr` are not allowed, and some +including `open` and `**` are replaced with versions intended to make +them safer for user input. If the ``NumPy`` is installed, many of its +functions will also be available. Programmers can add custom +functions and data of their own into each Asteval session. Users can +define and run their own functions within the confines of the +limitations of the Asteval language. + +Asteval converts user input into Python's own abstract syntax tree +(AST) representation and determines the result by walking through that +tree. This approach guarantees the parsing of input will be identical +to that of Python, eliminating many lexing and parsing challenges and +generating a result that is straightforward to interpret. This makes +"correctness" easy to test and verify with high confidence, so that +the emphasis can be placed on balancing functionality with safety. + +There are several absences and differences with Python, and Asteval is +by no means an attempt to reproduce Python with its own ``ast`` +module. While, it does support a large subset of Python, the +following features found in Python are not supported in Asteval: + + 1. creating classes is not supported + 2. many internal methods and classes of Python objects, + especially ``__dunder__`` methods cannot be accessed. + 3. `eval`, `exec`, `yield`, `async`, `match/case`, function + decorators, generators, and type annotations are not supported. + 4. `f-strings` are supported, but `t-strings` are not supported. + 5. importing modules is not supported by default, though it can be + enabled. + +Most of these omissions and limitations are intentional, and aimed to +strengthen Asteval against dangerous user code. A few of these (say, +`match/case` and `t-strings`) omissions may simply be viewed as not +particularly compelling need for an embedded interpreter exposed to +user input. + +Even with these restrictions, Asteval provides a pretty complete and +usable scripting or "macro" language that can easily be embedded into +a larger GUI or Web application that can handle user input without +many of the risks associated with using Python's `eval()`. Matt Newville <[email protected]> -Last Update: 30-June-2024 +Last Update: 17-Dec-2025 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/asteval/asteval.py new/asteval-1.0.8/asteval/asteval.py --- old/asteval-1.0.7/asteval/asteval.py 2025-11-06 22:41:41.000000000 +0100 +++ new/asteval-1.0.8/asteval/asteval.py 2025-12-11 22:40:31.000000000 +0100 @@ -44,18 +44,19 @@ import time from sys import exc_info, stderr, stdout -from .astutils import (HAS_NUMPY, - ExceptionHolder, ReturnedNone, Empty, make_symbol_table, - numpy, op2func, safe_getattr, safe_format, valid_symbol_name, Procedure) +from .astutils import (HAS_NUMPY, ExceptionHolder, ReturnedNone, + Empty, make_symbol_table, op2func, + safe_getattr, safe_format, valid_symbol_name, + Procedure) ALL_NODES = ['arg', 'assert', 'assign', 'attribute', 'augassign', 'binop', 'boolop', 'break', 'call', 'compare', 'constant', 'continue', 'delete', 'dict', 'dictcomp', 'excepthandler', 'expr', 'extslice', 'for', 'functiondef', 'if', 'ifexp', 'import', 'importfrom', - 'index', 'interrupt', 'list', 'listcomp', 'module', - 'name', 'pass', 'raise', 'repr', 'return', 'set', - 'setcomp', 'slice', 'subscript', 'try', 'tuple', + 'index', 'interrupt', 'lambda', 'list', 'listcomp', + 'module', 'name', 'pass', 'raise', 'repr', 'return', + 'set', 'setcomp', 'slice', 'subscript', 'try', 'tuple', 'unaryop', 'while', 'with', 'formattedvalue', 'joinedstr'] @@ -64,8 +65,9 @@ DEFAULT_CONFIG = {'import': False, 'importfrom': False} for _tnode in ('assert', 'augassign', 'delete', 'if', 'ifexp', 'for', - 'formattedvalue', 'functiondef', 'print', 'raise', 'listcomp', - 'dictcomp', 'setcomp', 'try', 'while', 'with'): + 'formattedvalue', 'functiondef', 'print', 'raise', + 'lambda', 'listcomp', 'dictcomp', 'setcomp', 'try', + 'while', 'with'): MINIMAL_CONFIG[_tnode] = False DEFAULT_CONFIG[_tnode] = True @@ -102,7 +104,7 @@ ----- 1. setting `minimal=True` is equivalent to setting a config with the following nodes disabled: ('import', 'importfrom', 'if', 'for', 'while', 'try', 'with', - 'functiondef', 'ifexp', 'listcomp', 'dictcomp', 'setcomp', 'augassign', + 'functiondef', 'ifexp', 'lambda', 'listcomp', 'dictcomp', 'setcomp', 'augassign', 'assert', 'delete', 'raise', 'print') 2. by default 'import' and 'importfrom' are disabled, though they can be enabled. """ @@ -275,7 +277,7 @@ out = ast.parse(text) except SyntaxError: self.raise_exception(None, exc=SyntaxError, expr=text) - except: + except Exception: self.raise_exception(None, exc=RuntimeError, expr=text) out = ast.fix_missing_locations(out) return out @@ -317,7 +319,7 @@ if isinstance(ret, enumerate): ret = list(ret) return ret - except: + except Exception: if with_raise and self.expr is not None: self.raise_exception(node, expr=self.expr) @@ -419,7 +421,7 @@ try: __import__(name) thismod = sys.modules[name] - except: + except Exception: self.raise_exception(None, exc=ImportError, msg='Import Error') if fromlist is None: @@ -650,8 +652,8 @@ while tnode.__class__ == ast.Attribute: children.append(tnode.attr) tnode = tnode.value - if (tnode.__class__ == ast.Name and not - tnode.id in self.readonly_symbols): + if (tnode.__class__ == ast.Name and + tnode.id not in self.readonly_symbols): children.append(tnode.id) children.reverse() sname = '.'.join(children) @@ -950,18 +952,24 @@ """Arg for function definitions.""" return node.arg - def on_functiondef(self, node): + def on_functiondef(self, node, is_lambda=False): """Define procedures.""" # ('name', 'args', 'body', 'decorator_list') - if node.decorator_list: - raise Warning("decorated procedures not supported!") - kwargs = [] + if is_lambda: + name = 'lambda' + body = [node.body] + else: + name = node.name + body = node.body - if (not valid_symbol_name(node.name) or - node.name in self.readonly_symbols): - errmsg = f"invalid function name (reserved word?) {node.name}" - self.raise_exception(node, exc=NameError, msg=errmsg) + if node.decorator_list: + raise Warning("decorated procedures not supported!") + if (not valid_symbol_name(name) or + name in self.readonly_symbols): + errmsg = f"invalid function name (reserved word?) {name}" + self.raise_exception(node, exc=NameError, msg=errmsg) + kwargs = [] offset = len(node.args.args) - len(node.args.defaults) for idef, defnode in enumerate(node.args.defaults): defval = self.run(defnode) @@ -970,7 +978,7 @@ args = [tnode.arg for tnode in node.args.args[:offset]] doc = None - nb0 = node.body[0] + nb0 = body[0] if isinstance(nb0, ast.Expr) and isinstance(nb0.value, ast.Constant): doc = nb0.value varkws = node.args.kwarg @@ -979,11 +987,19 @@ vararg = vararg.arg if isinstance(varkws, ast.arg): varkws = varkws.arg - self.symtable[node.name] = Procedure(node.name, self, doc=doc, - lineno=self.lineno, - body=node.body, - text=ast.unparse(node), - args=args, kwargs=kwargs, - vararg=vararg, varkws=varkws) - if node.name in self.no_deepcopy: - self.no_deepcopy.remove(node.name) + + proc = Procedure(name, self, doc=doc, lineno=self.lineno, + body=body, text=ast.unparse(node), + args=args, kwargs=kwargs, vararg=vararg, + varkws=varkws, is_lambda=is_lambda) + + if is_lambda: + return proc + else: + self.symtable[name] = proc + if name in self.no_deepcopy: + self.no_deepcopy.remove(name) + + def on_lambda(self, node): + """Lambda.""" + return self.on_functiondef(node, is_lambda=True) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/asteval/astutils.py new/asteval-1.0.8/asteval/astutils.py --- old/asteval-1.0.7/asteval/astutils.py 2025-11-06 22:41:41.000000000 +0100 +++ new/asteval-1.0.8/asteval/astutils.py 2025-12-11 22:40:31.000000000 +0100 @@ -42,8 +42,8 @@ try: from _string import formatter_field_name_split except ImportError: - formatter_field_name_split = lambda \ - x: x._formatter_field_name_split() + def formatter_field_name_split(x): + return x._formatter_field_name_split() @@ -141,7 +141,7 @@ 'little_endian', 'loadtxt', 'log', 'log10', 'log1p', 'log2', 'logaddexp', 'logaddexp2', 'logical_and', 'logical_not', 'logical_or', 'logical_xor', 'logspace', 'longdouble', 'longlong', 'mask_indices', 'matrix', 'maximum', - 'may_share_memory', 'mean', 'median', 'memmap', 'meshgrid', 'minimum', + 'may_share_memory', 'mean', 'median', 'meshgrid', 'minimum', 'mintypecode', 'mod', 'modf', 'msort', 'multiply', 'nan', 'nan_to_num', 'nanargmax', 'nanargmin', 'nanmax', 'nanmin', 'nansum', 'ndarray', 'ndenumerate', 'ndim', 'ndindex', 'negative', 'nextafter', 'nonzero', @@ -391,7 +391,7 @@ self.lineno = node.lineno self.end_lineno = node.end_lineno self.col_offset = node.col_offset - except: + except Exception: pass self.exc_info = sys.exc_info() if self.exc is None and self.exc_info[0] is not None: @@ -409,12 +409,12 @@ exc_name = 'UnknownError' out = [] - self.code = [f'{l}' for l in self.text.split('\n')] - self.codelines = [f'{i+1}: {l}' for i, l in enumerate(self.code)] + self.code = [f'{word}' for word in self.text.split('\n')] + self.codelines = [f'{i+1}: {word}' for i, word in enumerate(self.code)] try: out.append('\n'.join(self.code[self.lineno-1:self.end_lineno])) - except: + except Exception: out.append(f"{self.expr}") if self.col_offset > 0: out.append(f"{self.col_offset*' '}^^^^") @@ -571,7 +571,7 @@ def __init__(self, name, interp, doc=None, lineno=None, body=None, text=None, args=None, kwargs=None, - vararg=None, varkws=None): + vararg=None, varkws=None, is_lambda=False): """TODO: docstring in public method.""" self.__ininit__ = True self.name = name @@ -586,6 +586,10 @@ self.__varkws__ = varkws self.lineno = lineno self.__text__ = text + self.__is_lambda__ = is_lambda + if is_lambda: + self.name = self.__name__ = 'lambda' + if text is None: self.__text__ = f'{self.__signature__()}\n' + ast.unparse(self.__body__) self.__ininit__ = False @@ -732,9 +736,12 @@ # evaluate script of function self.__asteval__.code_text.append(self.__text__) for node in self.__body__: - self.__asteval__.run(node, lineno=node.lineno) + out = self.__asteval__.run(node, lineno=node.lineno) if len(self.__asteval__.error) > 0: break + if self.__is_lambda__: + retval = out + break if self.__asteval__.retval is not None: retval = self.__asteval__.retval self.__asteval__.retval = None @@ -745,5 +752,6 @@ self.__asteval__.symtable = save_symtable self.__asteval__.code_text.pop() self.__asteval__._calldepth -= 1 + self.__asteval__._interrupt = None symlocals = None return retval diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/asteval/version.py new/asteval-1.0.8/asteval/version.py --- old/asteval-1.0.7/asteval/version.py 2025-11-06 22:41:52.000000000 +0100 +++ new/asteval-1.0.8/asteval/version.py 2025-12-17 21:54:32.000000000 +0100 @@ -28,7 +28,7 @@ commit_id: COMMIT_ID __commit_id__: COMMIT_ID -__version__ = version = '1.0.7' -__version_tuple__ = version_tuple = (1, 0, 7) +__version__ = version = '1.0.8' +__version_tuple__ = version_tuple = (1, 0, 8) -__commit_id__ = commit_id = 'gc9991033e' +__commit_id__ = commit_id = 'gabf86adfa' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/asteval.egg-info/PKG-INFO new/asteval-1.0.8/asteval.egg-info/PKG-INFO --- old/asteval-1.0.7/asteval.egg-info/PKG-INFO 2025-11-06 22:41:52.000000000 +0100 +++ new/asteval-1.0.8/asteval.egg-info/PKG-INFO 2025-12-17 21:54:32.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: asteval -Version: 1.0.7 +Version: 1.0.8 Summary: Safe, minimalistic evaluator of python expression using ast module Author-email: Matthew Newville <[email protected]> License-Expression: MIT @@ -77,45 +77,77 @@ Use ``pip install asteval`` to install the asteval library. -Asteval requires Python 3.8 or higher. If installed, many functions and -constants from Numpy will be used by default. - -About ASTEVAL --------------- - -ASTEVAL is a safe(ish) evaluator of Python expressions and statements, -using Python's ast module. The idea is to provide a simple, safe, and -robust miniature mathematical language that can handle user input. The -emphasis here is on mathematical expressions so that many functions from -``numpy`` are imported and used if available. - -Many Python language constructs are supported by default, These include -slicing, subscripting, list comprehension, conditionals (if-elif-else -blocks and if expressions), flow control (for loops, while loops, and -try-except-finally blocks). All data are Python objects and built-in data -structures (dictionaries, tuples, lists, Numpy arrays, strings) are fully -supported by default. - -Many of the standard built-in Python functions are available, as are all -mathematical functions from the math module. If the Numpy module is -installed, many of its functions will also be available. Users can define -and run their own functions within the confines of the limitations of -Asteval. - -There are several absences and differences with Python, and Asteval is by -no means an attempt to reproduce Python with its own ast module. Some of -the most important differences and absences are: - - 1. Variable and function symbol names are held in a simple symbol - table (a single dictionary), giving a flat namespace. - 2. creating classes is not supported. - 3. importing modules is not supported by default - it can be enabled. - 4. function decorators, yield, lambda, exec, and eval are not supported. - 5. files can only be opened in read-only mode. - -In addition, accessing many internal methods and classes of objects is -forbidden in order to strengthen Asteval against malicious user code. +Asteval supports Python 3.10 or higher. No modules outside of the +standard library are required, though if `NumPy` is installed, many +functions from it will be used by default. + +About Asteval +---------------- + +Asteval is a safe(ish) evaluator of Python expressions and statements, +using Python's ast module. It provides an easy-to-use restricted +Python interpreter that supports a pretty complete subset of the +Python language and can handle user input more safely than Python's +``eval()``. Asteval emphasizes mathematical expressions so that many +functions from ``NumPy`` are imported and used if available, but also +provides a pretty complete subset of the Python language. It can be +used as an embedded macro language within a large application or as a +simple calculator for mathematical calculations. + +Asteval supports many Python language constructs by default, including +conditionals (if-elif-else blocks and if expressions), flow control +(for loops, while loops, with blocks, and try-except-finally blocks), +list comprehension, slicing, subscripting, and f-strings. All data +are Python objects and the standard built-in data structures +(dictionaries, tuples, lists, sets, strings, functions, and ``Numpy`` +nd-arrays) are well supported, and most public attributes and methods +of these objects are available. Asteval does place some limitations +on "looking under the hood" to get private and potentially unsafe +methods. + +Many of the standard built-in Python functions are available, as are +the functions from the ``math`` module. Some built-in operators and +functions, such as `getattr`, and `setattr` are not allowed, and some +including `open` and `**` are replaced with versions intended to make +them safer for user input. If the ``NumPy`` is installed, many of its +functions will also be available. Programmers can add custom +functions and data of their own into each Asteval session. Users can +define and run their own functions within the confines of the +limitations of the Asteval language. + +Asteval converts user input into Python's own abstract syntax tree +(AST) representation and determines the result by walking through that +tree. This approach guarantees the parsing of input will be identical +to that of Python, eliminating many lexing and parsing challenges and +generating a result that is straightforward to interpret. This makes +"correctness" easy to test and verify with high confidence, so that +the emphasis can be placed on balancing functionality with safety. + +There are several absences and differences with Python, and Asteval is +by no means an attempt to reproduce Python with its own ``ast`` +module. While, it does support a large subset of Python, the +following features found in Python are not supported in Asteval: + + 1. creating classes is not supported + 2. many internal methods and classes of Python objects, + especially ``__dunder__`` methods cannot be accessed. + 3. `eval`, `exec`, `yield`, `async`, `match/case`, function + decorators, generators, and type annotations are not supported. + 4. `f-strings` are supported, but `t-strings` are not supported. + 5. importing modules is not supported by default, though it can be + enabled. + +Most of these omissions and limitations are intentional, and aimed to +strengthen Asteval against dangerous user code. A few of these (say, +`match/case` and `t-strings`) omissions may simply be viewed as not +particularly compelling need for an embedded interpreter exposed to +user input. + +Even with these restrictions, Asteval provides a pretty complete and +usable scripting or "macro" language that can easily be embedded into +a larger GUI or Web application that can handle user input without +many of the risks associated with using Python's `eval()`. Matt Newville <[email protected]> -Last Update: 30-June-2024 +Last Update: 17-Dec-2025 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/asteval.egg-info/SOURCES.txt new/asteval-1.0.8/asteval.egg-info/SOURCES.txt --- old/asteval-1.0.7/asteval.egg-info/SOURCES.txt 2025-11-06 22:41:52.000000000 +0100 +++ new/asteval-1.0.8/asteval.egg-info/SOURCES.txt 2025-12-17 21:54:33.000000000 +0100 @@ -1,5 +1,4 @@ .codecov.yml -.gitattributes .gitignore LICENSE README.rst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/doc/api.rst new/asteval-1.0.8/doc/api.rst --- old/asteval-1.0.7/doc/api.rst 2025-11-06 22:41:41.000000000 +0100 +++ new/asteval-1.0.8/doc/api.rst 2025-12-11 22:40:31.000000000 +0100 @@ -80,6 +80,8 @@ +----------------+----------------------+-------------------+-------------------+ | raise | raise statements | True | False | +----------------+----------------------+-------------------+-------------------+ + | lambda | lambda expressions | True | False | + +----------------+----------------------+-------------------+-------------------+ | listcomp | list comprehension | True | False | +----------------+----------------------+-------------------+-------------------+ | dictcomp | dict comprehension | True | False | @@ -105,6 +107,7 @@ * with blocks * augmented assignments: ``x += 1`` * if-expressions: ``x = a if TEST else b`` + * lambda expressions: ``dist = lambda x,y: sqrt(x**2 + y**2)`` * list comprehension: ``out = [sqrt(i) for i in values]`` * set and dict comprehension, too. * print formatting with ``%``, ``str.format()``, or f-strings. @@ -133,11 +136,13 @@ >>> >>> aeval_min = Interpreter(minimal=True) >>> aeval_min.config - {'import': False, 'importfrom': False, 'assert': False, 'augassign': False, - 'delete': False, 'if': False, 'ifexp': False, 'for': False, - 'formattedvalue': False, 'functiondef': False, 'print': False, - 'raise': False, 'listcomp': False, 'dictcomp': False, 'setcomp': False, - 'try': False, 'while': False, 'with': False} + {'import': False, 'importfrom': False, 'assert': False, + 'augassign': False, 'delete': False, 'if': False, 'ifexp': False, + 'for': False, 'formattedvalue': False, 'functiondef': False, + 'print': False, 'raise': False, 'lambda': False, + 'listcomp': False, 'dictcomp': False, 'setcomp': False, + 'try': False, 'while': False, 'with': False, + 'nested_symtable': False} As shown above, importing Python modules with ``import module`` or ``from module import method`` can be enabled, but is disabled by default. To enable @@ -146,12 +151,13 @@ >>> from asteval import Interpreter >>> aeval_max = Interpreter(with_import=True, with_importfrom=True) -or by setting the config dictionary as described above: +or by setting the config dictionary passed to ``Interpreter`` as +described above. Interpreter methods and attributes ==================================== -An Interpreter instance has many methods, but most of them are +The Asteval Interpreter instance has many methods, but most of them are implementation details for how to handle particular AST nodes, and should not be considered as part of the usable API. The methods described below, and the examples elsewhere in this documentation should be used as the @@ -312,8 +318,6 @@ .. autofunction:: valid_symbol_name - - .. autofunction:: make_symbol_table diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/doc/basics.rst new/asteval-1.0.8/doc/basics.rst --- old/asteval-1.0.7/doc/basics.rst 2025-11-06 22:41:41.000000000 +0100 +++ new/asteval-1.0.8/doc/basics.rst 2025-12-11 22:40:31.000000000 +0100 @@ -155,7 +155,8 @@ >>> from asteval import Interpreter >>> aeval = Interpreter() - >>> code = """def func(a, b, norm=1.0): + >>> code = """ + ... def func(a, b, norm=1.0): ... return (a + b)/norm ... """ >>> aeval(code) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/doc/index.rst new/asteval-1.0.8/doc/index.rst --- old/asteval-1.0.7/doc/index.rst 2025-11-06 22:41:41.000000000 +0100 +++ new/asteval-1.0.8/doc/index.rst 2025-12-11 22:40:31.000000000 +0100 @@ -41,7 +41,7 @@ access can also be used. 2. creating classes is not allowed. 3. importing modules is not allowed, unless specifically enabled. - 4. decorators, generators, type hints, and ``lambda`` are not supported. + 4. decorators, generators, and type hints are not supported. 5. ``yield``, ``await``, and async programming are not supported. 6. Many builtin functions (:py:func:`eval`, :py:func:`getattr`, :py:func:`hasattr`, :py:func:`setattr`, and :py:func:`delattr`) are not allowed. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/doc/motivation.rst new/asteval-1.0.8/doc/motivation.rst --- old/asteval-1.0.7/doc/motivation.rst 2025-11-06 22:41:41.000000000 +0100 +++ new/asteval-1.0.8/doc/motivation.rst 2025-12-17 20:44:56.000000000 +0100 @@ -20,7 +20,7 @@ code cannot access the :py:mod:`os` and :py:mod:`sys` modules or any functions or classes outside those provided in the symbol table. -Many of the other missing features (modules, classes, lambda, yield, +Many of the other missing features (modules, classes, yield, generators) are similarly motivated by a desire for a safer version of :py:func:`eval`. The idea for asteval is to make a simple procedural, mathematically-oriented language that can be embedded into larger applications. @@ -102,12 +102,14 @@ known to be able to seg-fault the Python interpreter or give access to the operating system. -An important caveat is that a typical use of asteval will import and -expose numpy ``ufuncs`` from the numpy module. Several of these can -seg-fault Python without too much trouble. If you safety from user -input causing segmentation fault is a primary concern, you may want to -consider disabling the use of numpy, or take extra care to specify -what numpy functions can be used. +An important caveat is that by default asteval will use ``numpy`` and +import and expose numpy ``ufuncs`` from the numpy module. Several of +these can seg-fault Python without much difficulty. In addition, +several numpy objects, including the basic `ndarray` have methods to +write data to disk. If you safety from user input causing segmentation +fault is a primary concern, you may want to consider disabling the use +of numpy, or take extra care to specify what numpy functions can be +used. In 2024, an independent security audit of asteval done by Andrew Effenhauser, Ayman Hammad, and Daniel Crowley in the X-Force Security @@ -182,19 +184,22 @@ File access -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~ By default, the list of supported functions does include Python's -``open()`` -- in read-only mode -- which will allow disk access to the -untrusted user. If ``numpy`` is supported, its ``load()`` and -``loadtxt()`` functions will also normally be supported. By itself, -including these functions does not elevate permissions, and access is -restricted to 'read-only mode'. Still, the user of the asteval -interpreter would be able to read files with the privileges of the -calling program. In some cases, this may not be desirable, and you -may want to remove some of these functions from the symbol table, -re-implement them, or ensure that your program cannot access -information on disk that should be kept private. +``open()`` which will allow disk access to the untrusted user. By +default, Asteval limits ``open()`` to work in read-only mode, and with +the permissions of the calling program. + +When ``numpy`` is supported, its ``load()`` and ``loadtxt()`` functions +will also normally be supported to read data. But it should be noted +that ``numpy`` ndarrays do have a ``tofile()`` method that will write to +disk, limited by the permissions of the calling program. + +If writing to disk is a concern, ``numpy`` should be disabled. If +reading from disk must be forbidden, you will want to overwrite the +``open()`` function from the symbol table, or re-implement this to +restrict access. to information on disk that should be kept private. Monitoring Runtime and interrupting processes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/asteval-1.0.7/tests/test_asteval.py new/asteval-1.0.8/tests/test_asteval.py --- old/asteval-1.0.7/tests/test_asteval.py 2025-11-06 22:41:41.000000000 +0100 +++ new/asteval-1.0.8/tests/test_asteval.py 2025-12-11 22:40:31.000000000 +0100 @@ -1150,6 +1150,19 @@ isvalue(interp, 'o2', 1.5) @pytest.mark.parametrize("nested", [False, True]) +def test_lambda(nested): + """test using lambda definitions""" + interp = make_interpreter(nested_symtable=nested) + + interp(textwrap.dedent(""" + my_func = lambda x: 2 + 3*x + out = my_func(3) + """)) + assert len(interp.error) == 0 + isvalue(interp, 'out', 11.0) + + [email protected]("nested", [False, True]) def test_astdump(nested): """test ast parsing and dumping""" interp = make_interpreter(nested_symtable=nested) @@ -1231,7 +1244,7 @@ interp("""(lambda fc=(lambda n: [c for c in ().__class__.__bases__[0].__subclasses__() if c.__name__ == n][0]): fc("function")(fc("code")(0,0,0,0,"KABOOM",(),(),(),"","",0,""),{})() )()""") - check_error(interp, 'NotImplementedError') # Safe, lambda is not supported + check_error(interp, 'AttributeError') # Safe, unassigned lambda is not supported interp("""[print(c) for c in ().__class__.__bases__[0].__subclasses__()]""") # Try a portion of the kaboom... @@ -1689,5 +1702,41 @@ check_error(interp, 'ZeroDivisionError', 'x /= 0') assert interp.error[0].lineno == 3 [email protected]("nested", [False, True]) +def test_unreachable_statement_while_loop(nested): + """unreachable statement inside while loop""" + + interp = make_interpreter(nested_symtable=nested) + interp(""" +def f(): + return "ok" + +x_before = 0 +x_after = 0 +while True: + x_before += 1 + _ = f() + x_after += 1 + if x_after >= 10: + break + +result = (x_before, x_after) + +xa = xb = 0 +for i in range(4): + xb += 1 + _ = f() + xa += 1 +result2 = (xb, xa) + +""") + + (x, y) = interp("result") + assert x == 10 + assert y == 10 + (x, y) = interp("result2") + assert x == 4 + assert y == 4 + if __name__ == '__main__': pytest.main(['-v', '-x', '-s'])
