A class to evaluate logical expressions using context variables.
PARAMETER | DESCRIPTION |
expression | A string containing a logical expression with context variable references. - Variable references use ${var_name} syntax: ${logged_in}, ${attempts} - String literals can use normal quotes: 'hello', "world" - Supported operators: - Logical: not/!, and/&, or/| - Comparison: >, <, >=, <=, ==, != - Supported functions: - len(${var_name}): Gets the length of a list, string, or other collection - Parentheses can be used for grouping - Examples: - "not ${logged_in} and ${is_admin} or ${guest_checkout}" - "!${logged_in} & ${is_admin} | ${guest_checkout}" - "len(${orders}) > 0 & ${user_active}" - "len(${cart_items}) == 0 | ${checkout_started}" TYPE: str |
RAISES | DESCRIPTION |
SyntaxError | If the expression cannot be parsed |
ValueError | If the expression contains disallowed operations |
expression instance-attribute
evaluate
evaluate(context_variables)
Evaluate the expression using the provided context variables.
PARAMETER | DESCRIPTION |
context_variables | Dictionary of context variables to use for evaluation TYPE: ContextVariables |
RETURNS | DESCRIPTION |
bool | The result of evaluating the expression TYPE: bool |
RAISES | DESCRIPTION |
KeyError | If a variable referenced in the expression is not found in the context |
Source code in autogen/agentchat/group/context_expression.py
| def evaluate(self, context_variables: ContextVariables) -> bool:
"""Evaluate the expression using the provided context variables.
Args:
context_variables: Dictionary of context variables to use for evaluation
Returns:
bool: The result of evaluating the expression
Raises:
KeyError: If a variable referenced in the expression is not found in the context
"""
# Create a modified expression that we can safely evaluate
eval_expr = self._python_expr # Use the Python-syntax version
# First, handle len() functions with variable references inside
len_pattern = r"len\(\${([^}]*)}\)"
len_matches = list(re.finditer(len_pattern, eval_expr))
# Process all len() operations first
for match in len_matches:
var_name = match.group(1)
# Check if variable exists in context, raise KeyError if not
if not context_variables.contains(var_name):
raise KeyError(f"Missing context variable: '{var_name}'")
var_value = context_variables.get(var_name)
# Calculate the length - works for lists, strings, dictionaries, etc.
try:
length_value = len(var_value) # type: ignore[arg-type]
except TypeError:
# If the value doesn't support len(), treat as 0
length_value = 0
# Replace the len() expression with the actual length
full_match = match.group(0)
eval_expr = eval_expr.replace(full_match, str(length_value))
# Then replace remaining variable references with their values
for var_name in self._variable_names:
# Skip variables that were already processed in len() expressions
if any(m.group(1) == var_name for m in len_matches):
continue
# Check if variable exists in context, raise KeyError if not
if not context_variables.contains(var_name):
raise KeyError(f"Missing context variable: '{var_name}'")
# Get the value from context
var_value = context_variables.get(var_name)
# Format the value appropriately based on its type
if isinstance(var_value, (bool, int, float)):
formatted_value = str(var_value)
elif isinstance(var_value, str):
formatted_value = f"'{var_value}'" # Quote strings
elif isinstance(var_value, (list, dict, tuple)):
# For collections, convert to their boolean evaluation
formatted_value = str(bool(var_value))
else:
formatted_value = str(var_value)
# Replace the variable reference with the formatted value
eval_expr = eval_expr.replace(f"${{{var_name}}}", formatted_value)
try:
return eval(eval_expr) # type: ignore[no-any-return]
except Exception as e:
raise ValueError(
f"Error evaluating expression '{self.expression}' (are you sure you're using ${{my_context_variable_key}}): {str(e)}"
)
|