From 33f0ed2053a38dbc4fe8bdd0e8a85012552b677c Mon Sep 17 00:00:00 2001 From: Qubitium Date: Sun, 22 Mar 2026 06:10:56 +0000 Subject: [PATCH] add python 3.15 re compat: prefixmatch --- README.md | 5 ++++- pcre/__init__.py | 3 +++ pcre/pcre.py | 7 ++++++- pyproject.toml | 2 +- tests/test_api_parity.py | 15 +++++++++++++++ 5 files changed, 29 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e5ff9aa..c4751e3 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ numbers = pattern.findall(b"line 1\nline 22") ``` `pcre` mirrors the core helpers from Python’s standard library `re` module -`match`, `search`, `fullmatch`, `finditer`, `findall`, and `compile` while +`prefixmatch`, `match`, `search`, `fullmatch`, `finditer`, `findall`, and `compile` while exposing PCRE2’s extended flag set through the Pythonic `Flag` enum (`Flag.CASELESS`, `Flag.MULTILINE`, `Flag.UTF`, ...). @@ -90,6 +90,9 @@ exposing PCRE2’s extended flag set through the Pythonic `Flag` enum - Module-level helpers and the `Pattern` class follow the same call shapes as the standard library `re` module, including `pos`, `endpos`, and `flags` behaviour. +- Python 3.15's `prefixmatch()` alias is available at both the module level + and on compiled `Pattern` objects, and `re.NOFLAG` is re-exported as the + zero-value compatibility alias. - `Pattern` mirrors `re.Pattern` attributes like `.pattern`, `.groupindex`, and `.groups`, while `Match` objects surface the familiar `.re`, `.string`, `.pos`, `.endpos`, `.lastindex`, `.lastgroup`, `.regs`, and `.expand()` API. diff --git a/pcre/__init__.py b/pcre/__init__.py index f94b683..4df02c2 100644 --- a/pcre/__init__.py +++ b/pcre/__init__.py @@ -33,6 +33,7 @@ fullmatch, match, parallel_map, + prefixmatch, search, split, sub, @@ -84,6 +85,7 @@ def escape(pattern: Any) -> Any: # continue referencing familiar names. Prefer `pcre.Flag` for new code. _FLAG_ZERO = Flag(0) _FLAG_COMPAT_ALIASES = { + "NOFLAG": _FLAG_ZERO, "IGNORECASE": Flag.CASELESS, "I": Flag.CASELESS, "MULTILINE": Flag.MULTILINE, @@ -118,6 +120,7 @@ def escape(pattern: Any) -> Any: "set_cache_limit", "get_cache_limit", "compile", + "prefixmatch", "match", "search", "fullmatch", diff --git a/pcre/pcre.py b/pcre/pcre.py index 06fa1be..3a98efe 100644 --- a/pcre/pcre.py +++ b/pcre/pcre.py @@ -252,6 +252,8 @@ def match( raw, resolved_end = _call_with_optional_end(self._pattern.match, subject, pos, endpos, options) return self._wrap_match(raw, subject, pos, resolved_end) + prefixmatch = match + def search( self, subject: Any, @@ -569,10 +571,13 @@ def compile(pattern: Any, flags: FlagInput = 0) -> Pattern: return compiled -def match(pattern: Any, string: Any, flags: FlagInput = 0) -> Match | None: +def prefixmatch(pattern: Any, string: Any, flags: FlagInput = 0) -> Match | None: return compile(pattern, flags=flags).match(string) +match = prefixmatch + + def search(pattern: Any, string: Any, flags: FlagInput = 0) -> Match | None: return compile(pattern, flags=flags).search(string) diff --git a/pyproject.toml b/pyproject.toml index fce54e4..c313d8a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" [project] name = "PyPcre" -version = "0.2.14" +version = "0.2.15" description = "Modern, GIL-friendly, Fast Python bindings for PCRE2 with auto caching and JIT of compiled patterns." readme = "README.md" requires-python = ">=3.9" diff --git a/tests/test_api_parity.py b/tests/test_api_parity.py index 061f38c..b81a7ee 100644 --- a/tests/test_api_parity.py +++ b/tests/test_api_parity.py @@ -20,6 +20,20 @@ def test_purge_aliases_clear_cache(): assert pcre.purge is pcre.clear_cache +def test_prefixmatch_aliases_match(): + assert pcre.match is pcre.prefixmatch + assert "prefixmatch" in pcre.__all__ + + module_match = pcre.prefixmatch(r"ab", "abcd") + assert module_match is not None + assert module_match.span() == re.match(r"ab", "abcd").span() + + compiled = pcre.compile(r"ab") + pattern_match = compiled.prefixmatch("zab", pos=1) + assert pattern_match is not None + assert pattern_match.span() == re.compile(r"ab").match("zab", 1).span() + + def test_error_aliases_and_escape(): assert pcre.error is pcre.PcreError assert pcre.PatternError is pcre.PcreError @@ -38,6 +52,7 @@ def test_error_aliases_and_escape(): def test_stdlib_style_flag_aliases(): + assert pcre.NOFLAG == 0 assert pcre.IGNORECASE == pcre.Flag.CASELESS assert pcre.I == pcre.Flag.CASELESS assert pcre.MULTILINE == pcre.Flag.MULTILINE