Add pluggable regex engine support#41
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a pluggable regex_engine hook so JSONata regex literals can be compiled by an alternative regex backend (e.g., via an adapter to RE2), while keeping the stdlib re behavior as the default.
Changes:
- Thread a
regex_engineparameter fromJsonata→Parser→Tokenizerto compile regex literals viaregex_engine.compile(pattern, flags). - Generalize “is regex” checks away from
isinstance(x, re.Pattern)to support non-stdlib compiled regex objects. - Add an opt-in RE2-focused test suite and a dedicated nox session to run it.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/re2_engine_test.py | Adds RE2 adapter + end-to-end tests for regex operations under a pluggable engine. |
| src/jsonata/tokenizer.py | Compiles regex literals using an injected regex_engine instead of hardcoding re. |
| src/jsonata/signature.py | Treats compiled regex values as “function-like” via the new regex predicate. |
| src/jsonata/parser.py | Passes regex_engine into the tokenizer during parse. |
| src/jsonata/jsonata.py | Exposes regex_engine on Jsonata and threads it into parsing; updates regex detection. |
| src/jsonata/functions.py | Uses the new regex predicate; makes $eval preserve the current instance’s regex engine. |
| noxfile.py | Adds a test_re2 session to run the optional RE2 engine tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (2)
src/jsonata/functions.py:1863
Functions.is_regex()is referenced elsewhere (e.g., signature/jsonata) but isn't implemented, which will raiseAttributeErrorat runtime. Also,$assert(false, <message>)currently ignores the provided message, which breaks existing tests and user-facing behavior.
@staticmethod
def assert_fn(condition: Optional[bool], message: Optional[str]) -> None:
if condition is utils.Utils.NULL_VALUE:
src/jsonata/functions.py:481
- This padding construction uses repeated string concatenation in a loop, which is significantly less efficient than string multiplication for larger pad sizes. Since
pad_stris normalized to a non-empty string above, the original multiplication approach is safe here.
padding = pad_str * (pads // len(pad_str) + 1)
return Functions.substr(padding, 0, pads) + string
# Source: Jsonata4Java PadFunction
@staticmethod
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/jsonata/functions.py:2237
- In function_eval, Jsonata.CURRENT.jsonata is read after constructing the nested Jsonata instance. Since Jsonata.init overwrites the thread-local CURRENT, this can accidentally pass the nested instance’s environment/bindings (and any other CURRENT-derived state) instead of the enclosing expression’s. Capture the enclosing Jsonata before creating the nested one, use it for regex_engine/environment, and restore CURRENT afterwards.
ast = jsonata.Jsonata(expr, jsonata.Jsonata.CURRENT.jsonata.regex_engine)
except Exception as err:
# error parsing the expression passed to $eval
# populateMessage(err)
raise jexception.JException("D3120", -1)
No description provided.