Source code for dgenerate.eval

# Copyright (c) 2023, Teriks
#
# dgenerate is distributed under the following BSD 3-Clause License
#
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived
#    from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import asteval

__doc__ = """
Safe expression parsing with asteval.
"""


[docs] def safe_builtins() -> dict: """ Return a dictionary / symbol table of basic python builtins that are considered safe and useful with ``asteval``. :return: symbol table """ return { 'abs': abs, 'all': all, 'any': any, 'ascii': ascii, 'bin': bin, 'bool': bool, 'bytearray': bytearray, 'bytes': bytes, 'callable': callable, 'chr': chr, 'complex': complex, 'dict': dict, 'divmod': divmod, 'enumerate': enumerate, 'filter': filter, 'float': float, 'format': format, 'frozenset': frozenset, 'getattr': getattr, 'hasattr': hasattr, 'hash': hash, 'hex': hex, 'int': int, 'iter': iter, 'len': len, 'list': list, 'map': map, 'max': max, 'min': min, 'next': next, 'object': object, 'oct': oct, 'ord': ord, 'pow': pow, 'range': range, 'repr': repr, 'reversed': reversed, 'round': round, 'set': set, 'slice': slice, 'sorted': sorted, 'str': str, 'sum': sum, 'tuple': tuple, 'type': type, 'zip': zip, }
[docs] def standard_interpreter( symtable: dict | None = None, with_listcomp: bool = True, with_dictcomp: bool = True, with_setcomp: bool = True, with_ifexpr: bool = True, use_numpy: bool = False ) -> asteval.Interpreter: """ Return a default safe interpreter from ``asteval``. Nothing that does not exist in symtable will be usable, if you provide no symtable, no functions / variables will be present. All forms of assignment, import, etc. are disabled. :param symtable: Symbol table :param with_listcomp: Allow list comprehension? :param with_dictcomp: Allow dict comprehension? :param with_setcomp: Allow set comprehension? :param with_ifexpr: Allow ternary statements? :param use_numpy: Import numpy functions directly, without namespace? :return: The interpreter """ interpreter = asteval.Interpreter( minimal=True, with_listcomp=with_listcomp, with_dictcomp=with_dictcomp, with_setcomp=with_setcomp, with_ifexp=with_ifexpr, use_numpy=use_numpy, builtins_readonly=True, symtable=symtable if symtable is not None else dict() ) if 'print' in interpreter.symtable: del interpreter.symtable['print'] return interpreter