pure-eval

raw JSON →
0.2.3 verified Tue May 12 auth: no python install: verified quickstart: stale

pure-eval is a Python library (current version 0.2.3) designed to safely evaluate Abstract Syntax Tree (AST) nodes without allowing arbitrary code execution or unwanted side effects. It provides a controlled way to inspect and compute values from Python expressions, making it suitable for static analysis and secure evaluation contexts. The library is actively maintained, with updates released periodically.

pip install pure-eval
error CannotEval
cause The `pure-eval` library raised this exception because it encountered an AST node or operation that it deems unsafe or cannot evaluate according to its strict safety rules, such as attempting to execute arbitrary code or access forbidden attributes.
fix
Review the AST node being evaluated and ensure it consists only of safe expressions and operations that pure-eval is designed to handle. Avoid attempting to evaluate statements (like import, def, class) or expressions that access potentially unsafe attributes or functions.
error ModuleNotFoundError: No module named 'pure_eval'
cause The `pure-eval` library is not installed in the current Python environment, or the Python interpreter cannot find it.
fix
Install the library using pip: pip install pure-eval or ensure your virtual environment is activated and the dependency is correctly listed and installed.
error SyntaxError: invalid syntax
cause This typically occurs when trying to use Python's built-in `eval()` function (not `pure-eval`) with a string that contains a statement (e.g., `import`, `def`, `class`) instead of a pure expression. `eval()` can only evaluate expressions, not statements.
fix
If you are trying to evaluate expressions, ensure the input string to eval() or the AST node passed to pure-eval's evaluator is a valid expression. If you intend to execute statements, consider using exec() (with extreme caution due to security risks) or parse the code into an AST and process it using pure-eval's capabilities, understanding that pure-eval will likely raise CannotEval for inherently unsafe statement nodes.
gotcha pure-eval is explicitly designed to raise a `CannotEval` exception when it encounters expressions that could have side effects, such as calling functions, accessing properties with getters that modify state, or modifying variables. It is not a drop-in replacement for Python's built-in `eval()` function for arbitrary code.
fix Ensure that the AST nodes you intend to evaluate represent genuinely pure expressions. Anticipate and handle `CannotEval` exceptions for any expressions that might involve non-pure operations.
gotcha By default, `pure-eval`'s `Evaluator` might inherit built-in functions and names from the execution environment. For maximum security and a truly 'pure' evaluation context, explicitly pass an empty dictionary `{}` or a carefully curated whitelist of safe built-ins to the `__builtins__` key in the `global_context` dictionary when initializing `Evaluator`.
fix Initialize `Evaluator` with `Evaluator(global_context={'__builtins__': {}})` or a custom safe dictionary for `__builtins__`.
gotcha The `Evaluator` class in `pure-eval` does not have an `evaluate` method. The primary method for evaluating AST nodes is `eval` (or `exec`). Attempting to call `evaluator.evaluate()` will result in an `AttributeError`.
fix Ensure you are using the correct method for evaluation, typically `evaluator.eval(ast_node)`.
gotcha The `Evaluator` class in `pure-eval` does not expose a method named `evaluate`. Attempting to call `evaluator.evaluate(...)` will result in an `AttributeError`.
fix Instead of `evaluator.evaluate(node)`, use `evaluator.eval_ast(node)` to evaluate an AST node, or `evaluator.eval_expr(expression_string)` to evaluate a Python expression string. Consult the `pure-eval` library's documentation for the correct method signature and usage based on your input type.
python os / libc status wheel install import disk
3.10 alpine (musl) - - 0.03s 17.9M
3.10 slim (glibc) - - 0.01s 18M
3.11 alpine (musl) - - 0.06s 19.7M
3.11 slim (glibc) - - 0.03s 20M
3.12 alpine (musl) - - 0.04s 11.6M
3.12 slim (glibc) - - 0.04s 12M
3.13 alpine (musl) - - 0.04s 11.2M
3.13 slim (glibc) - - 0.03s 12M
3.9 alpine (musl) - - 0.02s 17.4M
3.9 slim (glibc) - - 0.03s 18M

This example demonstrates how to use `pure-eval` to safely evaluate an AST node representing a pure mathematical expression. It also shows how the library prevents evaluation of expressions that might cause side effects, such as accessing a property that modifies internal state, by raising a `CannotEval` exception. For security, `__builtins__` are explicitly disabled in the evaluator context.

import ast
from pure_eval import Evaluator, CannotEval

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.area_computed = False

    @property
    def area(self):
        self.area_computed = True # This is a side effect
        return self.width * self.height

# Create an AST node representing a pure expression
rect_node = ast.parse("rect.width * rect.height").body[0].value
rect_instance = Rectangle(10, 5)

# Initialize Evaluator with the context. Disable builtins for security.
evaluator = Evaluator({
    "rect": rect_instance,
    "__builtins__": {} 
})

try:
    result = evaluator.evaluate(rect_node)
    print(f"Evaluated pure result: {result}")
except CannotEval as e:
    print(f"Could not evaluate pure expression: {e}")

# Create an AST node representing an expression with a potential side effect
side_effect_node = ast.parse("rect.area").body[0].value

try:
    evaluator.evaluate(side_effect_node)
except CannotEval as e:
    print(f"Refused to evaluate expression with potential side effect: {e}")

# Verify no side effect occurred from the attempted evaluation
print(f"Area computed flag: {rect_instance.area_computed}")