|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
3 | 3 | import re |
4 | | -import threading |
5 | 4 | from collections.abc import Callable, Mapping |
6 | 5 | from dataclasses import dataclass, field |
7 | 6 | from datetime import date |
@@ -196,45 +195,11 @@ def age_in_years( |
196 | 195 | ) |
197 | 196 |
|
198 | 197 |
|
199 | | -_evaluator_local: threading.local = threading.local() |
200 | | - |
201 | | - |
202 | | -def get_evaluator( |
203 | | - allowed_functions: dict[str, Callable[..., Any]] | None = None, |
204 | | -) -> EvalWithCompoundTypes: |
205 | | - """Return a per-thread evaluator for rule expression evaluation. |
206 | | -
|
207 | | - Admin validation and runtime blocking both use this so the evaluator |
208 | | - lifecycle is unified. The evaluator is cached per thread and reused; |
209 | | - :func:`validate_rule_expression` and :func:`evaluate_rule_expression_strict_bool` |
210 | | - clear ``evaluator.names`` after each call so no data leaks between rules. |
211 | | -
|
212 | | - :param allowed_functions: Override the function whitelist. Pass an empty |
213 | | - dict to disallow all functions. Only the first call per thread uses |
214 | | - this; subsequent calls ignore it. |
215 | | - :returns: A configured :class:`~simpleeval.EvalWithCompoundTypes`. |
216 | | - """ |
217 | | - evaluator = getattr(_evaluator_local, "evaluator", None) |
218 | | - if evaluator is None: |
219 | | - functions = ( |
220 | | - allowed_functions |
221 | | - if allowed_functions is not None |
222 | | - else dict(DEFAULT_ALLOWED_FUNCTIONS) |
223 | | - ) |
224 | | - evaluator = EvalWithCompoundTypes(functions=functions, names={}) |
225 | | - _evaluator_local.evaluator = evaluator |
226 | | - return _evaluator_local.evaluator |
227 | | - |
228 | | - |
229 | 198 | def make_evaluator( |
230 | 199 | allowed_functions: dict[str, Callable[..., Any]] | None = None, |
231 | 200 | ) -> EvalWithCompoundTypes: |
232 | 201 | """Create a fresh locked-down :class:`~simpleeval.EvalWithCompoundTypes`. |
233 | 202 |
|
234 | | - Prefer :func:`get_evaluator` for production use so admin and runtime share |
235 | | - the same per-thread evaluator. Use this when you need an isolated |
236 | | - evaluator (e.g. tests, or custom function sets). |
237 | | -
|
238 | 203 | :param allowed_functions: Override the function whitelist. Pass an empty |
239 | 204 | dict to disallow all functions. |
240 | 205 | :returns: A configured :class:`~simpleeval.EvalWithCompoundTypes`. |
@@ -286,8 +251,7 @@ def validate_rule_expression( |
286 | 251 | trial evaluation. For live validation this is the dict returned by |
287 | 252 | ``fetch_live_rule_validation_values``; it contains all raw SIP2 |
288 | 253 | response fields plus the normalised ``fines`` key. |
289 | | - :param evaluator: A locked-down evaluator from :func:`get_evaluator` or |
290 | | - :func:`make_evaluator`. |
| 254 | + :param evaluator: A locked-down evaluator from :func:`make_evaluator`. |
291 | 255 | :raises RuleValidationError: On any validation failure. |
292 | 256 | """ |
293 | 257 | if not expr or not expr.strip(): |
@@ -344,8 +308,7 @@ def evaluate_rule_expression_strict_bool( |
344 | 308 |
|
345 | 309 | :param expr: The raw rule expression string (same as stored). |
346 | 310 | :param values: Mapping of placeholder key → runtime value. |
347 | | - :param evaluator: A locked-down evaluator from :func:`get_evaluator` or |
348 | | - :func:`make_evaluator`. |
| 311 | + :param evaluator: A locked-down evaluator from :func:`make_evaluator`. |
349 | 312 | :param rule_name: Optional identifier for the rule, included in error messages. |
350 | 313 | :returns: ``True`` if the patron should be *blocked*, ``False`` otherwise. |
351 | 314 | :raises RuleEvaluationError: On missing placeholders, parse/eval errors, or |
|
0 commit comments