Python bindings to Rust's regress ECMA regular expressions library
regress provides Python bindings to the high-performance Rust `regress` crate, offering ECMA regular expression capabilities. The library is actively maintained, with its current version being 2025.10.1, and follows a frequent release cadence, as seen with multiple releases throughout 2024 and 2025. It aims to provide a fast and reliable regular expression engine compliant with the ECMA-262 specification.
Warnings
- breaking The library transitioned its versioning scheme from a `0.x.x` semantic versioning to a calendar-based `YYYY.MM.PATCH` format (e.g., `2024.8.1`). This major change in version numbering from `0.x` to `2024.x` might indicate breaking API changes, although not explicitly detailed in release notes for the major version bump. Users upgrading from `0.x` versions should review their code for compatibility.
- gotcha The `regress` library implements ECMA regular expressions (ECMA-262 standard), which may behave differently from Python's built-in `re` module (which is PCRE-like). Developers accustomed to PCRE syntax might encounter unexpected behavior with certain patterns, lookaheads, or other features not present or differing in ECMA regex.
- gotcha As a Rust-backed Python library using PyO3, `regress` relies on pre-built `manylinux` wheels for easy installation. In environments where compatible wheels are not available (e.g., specific or older Python versions, unusual OS/architecture combinations), installation might fail, requiring users to have a Rust toolchain to compile from source.
Install
-
pip install regress
Imports
- Regex
from regress import Regex
Quickstart
from regress import Regex
# Create a regex object that matches four digits
regex = Regex(r"\\d{4}")
# Test if the pattern is found in a string
match = regex.find("The year is 2024, not 1999.")
print(f"Match found: {match is not None}")
# Find all occurrences
matches = list(regex.find_iter("Years: 1980, 2000, 2020."))
print(f"Number of matches: {len(matches)}")
for m in matches:
print(f" Match at start: {m.start()}, end: {m.end()}, text: {m.as_str()}")
# Another example, with flags (e.g., case-insensitive 'i')
# Flags can be passed as a string or a bitmask.
regex_flags = Regex(r"hello", "i")
print(f"Case-insensitive match: {regex_flags.find('Hello World') is not None}")