From de323aa58b963d38e20e138461176d6f9022db2c Mon Sep 17 00:00:00 2001 From: elijahbenizzy Date: Tue, 21 May 2024 21:58:57 -0700 Subject: [PATCH] Fixes regression in which builtins were detected as variables for expr transition In the case of `cond.expr("len(foo) > d"), it would expect both len and foo as keys to the condition. This ignores all builtins. --- burr/core/action.py | 8 +++++++- tests/core/test_action.py | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/burr/core/action.py b/burr/core/action.py index 7014254e..b69be5aa 100644 --- a/burr/core/action.py +++ b/burr/core/action.py @@ -1,5 +1,6 @@ import abc import ast +import builtins import copy import inspect import sys @@ -204,6 +205,7 @@ def expr(expr: str) -> "Condition": :return: A condition that evaluates the given expression """ tree = ast.parse(expr, mode="eval") + all_builtins = builtins.__dict__ # Visitor class to collect variable names class NameVisitor(ast.NodeVisitor): @@ -211,7 +213,8 @@ def __init__(self): self.names = set() def visit_Name(self, node): - self.names.add(node.id) + if node.id not in all_builtins: + self.names.add(node.id) # Visit the nodes and collect variable names visitor = NameVisitor() @@ -261,6 +264,9 @@ def condition_func(state: State) -> bool: name = f"{', '.join(f'{key}={value}' for key, value in sorted(kwargs.items()))}" return Condition(keys, condition_func, name=name) + def __repr__(self): + return f"condition: {self._name}" + @classmethod @property def default(self) -> "Condition": diff --git a/tests/core/test_action.py b/tests/core/test_action.py index 02747163..5647b16b 100644 --- a/tests/core/test_action.py +++ b/tests/core/test_action.py @@ -120,8 +120,8 @@ def test_condition_expr(): def test_condition_expr_complex(): - cond = Condition.expr("foo == 'bar' and baz == 'qux'") - assert cond.name == "foo == 'bar' and baz == 'qux'" + cond = Condition.expr("foo == 'bar' and len(baz) == 3") + assert cond.name == "foo == 'bar' and len(baz) == 3" assert sorted(cond.reads) == ["baz", "foo"] assert cond.run(State({"foo": "bar", "baz": "qux"})) == {Condition.KEY: True} assert cond.run(State({"foo": "baz", "baz": "qux"})) == {Condition.KEY: False}