Skip to content

Support swappable regular expression engines - #1561

Open
kurtmckee wants to merge 1 commit into
python-jsonschema:mainfrom
kurtmckee:swappable-re-engines
Open

Support swappable regular expression engines#1561
kurtmckee wants to merge 1 commit into
python-jsonschema:mainfrom
kurtmckee:swappable-re-engines

Conversation

@kurtmckee

Copy link
Copy Markdown
Contributor

This PR introduces a "regular expression provider".

The feature allows alternate regular expression engines -- with different regex features, or with linear complexity guarantees, or other desirable attributes -- to be swapped out in place of Python's re parser.

Closes #1142

Note

I didn't see a way to neatly address the existing is_regex() format checker. It's hard-coded to use Python's re module and has no ability to access the validator instance on whose behalf it's running. This creates to distinct failure modes.

First, it's possible for Validator.check_schema() to pass but for validator.validate() to fail with an uncaught exception when the configured regex engine rejects an unsupported regex feature. No re.* usage in jsonschema uses try/except clauses to guard against this, and I didn't introduce anything to address this failure mode.

The other failure mode is that a regex feature supported by the configured regex engine would be rejected as invalid when .check_schema() is called.

I chose to address this via documentation for the time being, as the work in this PR is sufficient to address the core security need that I have, as well as the core feature need seen in #1142.

Example usage

This example uses Google's re2 package, which allows me to close a serious denial of service issue in a web service I maintain.

import jsonschema
import re2


class Re2Provider(jsonschema.protocols.RegexProvider):
    raises = (re2.error,)
    compile = staticmethod(re2.compile)
    search = staticmethod(re2.search)


SafeValidator = jsonschema.validators.extend(
    jsonschema.validators.Draft202012Validator,
    regex_provider=Re2Provider(),
)


def is_regex(_instance: str) -> bool:
    if not isinstance(_instance, str):
        return True
    return bool(re2.compile(_instance))


SafeValidator.FORMAT_CHECKER.checkers["regex"] = (is_regex, Re2Provider.raises)

# SafeValidator is now configured for use.

@read-the-docs-community

read-the-docs-community Bot commented Aug 20, 2026

Copy link
Copy Markdown

@kurtmckee

kurtmckee commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

The CI failure is due to an existing issue with Slack blocking the link-checker. It is unrelated to this PR.

Update: The CI error was fixed in main; this branch was rebased and force-pushed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Injecting custom regex implementations

1 participant