expression
expression ¤
AST-restricted Python expression compiler.
Lambda-rule triggers are written as short Python-syntax expressions
("(torque > 75) & (state == 'run')"). To run them safely we parse
with :func:ast.parse in mode="eval" and walk the tree, rejecting
any node that is not on a small allowlist.
Operator gotcha: Python's bitwise & / | (the vectorized ones
pandas understands) bind tighter than comparison operators, so you
must wrap each comparison in parentheses:
"(x > 1) & (y < 0)" — not "x > 1 & y < 0". This matches the
convention used by pandas.eval and DataFrame.query.
Why an AST whitelist over pandas.eval or polars.expr?
- Full control over error messages.
- Reliable Int64 / nullable-bool handling.
- Zero extra dependencies — stdlib :mod:
astonly. - The whitelist refuses dunders, attribute access (except the
.isin([...])method), imports, comprehensions, and any function call outside ofabs,min,max— so an LLM-proposed expression cannot exfiltrate or mutate state. - Python's
and/or/not/inare not element-wise on columns; they are rejected at compile time with a hint to&,|,~and.isin(...).
UnsafeExpression ¤
Bases: ValueError
Raised when a trigger expression contains a disallowed AST node.
compile_expression ¤
compile_expression(
expression: str,
) -> Callable[[pd.DataFrame], pd.Series]
Compile a trigger expression to a vectorized boolean mask function.
Python's and / or / not / in, chained comparisons and
min / max over columns are rejected here, with a hint to the
element-wise &, |, ~ and column.isin([...]).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
expression
|
str
|
The trigger, e.g. |
required |
Returns:
| Type | Description |
|---|---|
Callable[[DataFrame], Series]
|
A callable that takes a DataFrame and returns a boolean Series |
Callable[[DataFrame], Series]
|
aligned with its rows (missing -> False). |
Raises:
| Type | Description |
|---|---|
UnsafeExpression
|
For disallowed or non-element-wise syntax. The
callable raises :class: |