bursar.expr module
Safe expression evaluator using Python’s ast module.
Allows mathematical expressions with whitelisted variables and functions. Rejects any AST node type not in the allowlist (no eval/exec).
Money safety (REFACTOR_CONTRACT §1):
- All arithmetic is performed in
decimal.Decimal. Numeric literals are
parsed as exact decimals from their source text (never via
float()), so0.1 + 0.2is exactly0.3.
- Exponentiation (
**/ast.Pow) is rejected entirely at validate time – the simplest acceptable DoS fix per the contract (no constant-exponent carve-out). SeeALLOWED_NODES(ast.Powis intentionally absent). - Division / modulo by zero raise
ExpressionError(neverinf/nan). - After evaluation the result is asserted finite; non-finite ->
ExpressionError. OverflowError/ValueError/InvalidOperationare converted toExpressionError.
exception bursar.expr.ExpressionError
Bases: Exception
Raised on invalid or unsafe expressions.
bursar.expr.evaluate_expression(expr: str, variables: dict[str, Any]) → Decimal
Safely evaluate a validated expression in exact Decimal arithmetic.
Args: : expr: Expression string to evaluate. variables: Mapping of variable names to their numeric values.
Returns:
: Exact Decimal result of the expression evaluation. Not quantized –
callers (engine/breakdown) quantize at the cost boundary.
Raises: : ExpressionError: If the expression is invalid, references unknown : variables, divides/mods by zero, overflows, or produces a non-finite result.
bursar.expr.validate_expression(expr: str, known_variables: set[str] | None = None) → None
Validate that an expression string is safe and syntactically valid.
Args:
: expr: Expression string to validate.
known_variables: Optional canonical set of allowed variable names
(the engine’s metric set). When provided, any identifier that is neither a known variable nor an allowed function raises
ExpressionError– so config-author typos fail at config-load time rather than at first runtime evaluation (M5).
Raises: : ExpressionError: If the expression contains disallowed constructs or : references an unknown variable.