Skip to content

Commit 4a3be80

Browse files
author
Steve Ayers
committed
Override matches with re2 implementation
1 parent 182d1ab commit 4a3be80

File tree

7 files changed

+101
-16
lines changed

7 files changed

+101
-16
lines changed

.github/CONTRIBUTING.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,12 @@ git clone [email protected]:bufbuild/protovalidate-python.git
1919
cd protovalidate-python
2020
```
2121

22-
Then, make any changes you'd like. We use a Makefile to test and lint our code,
23-
so you'll need a few non-Python tools:
22+
Next, install dependencies. You will need:
23+
24+
* Python >=v3.9
25+
* [Pipenv](https://pipenv.pypa.io/en/latest/index.html)
26+
27+
We use a Makefile to test and lint our code, so you'll also need a few non-Python tools:
2428

2529
* GNU Make (to use the Makefile): part of the `build-essential` package on
2630
Debian-derived Linux distributions (including Ubuntu), and part of

Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ lint: install ## Lint code
6262

6363
.PHONY: install
6464
install: ## Install dependencies
65-
$(PYTHON) -m pip install --upgrade pip pipenv
6665
pipenv --python $(PYTHON) sync --dev
6766

6867
.PHONY: checkgenerate

Pipfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ name = "pypi"
66
[packages]
77
cel-python = "==0.2.*"
88
protobuf = "==6.*"
9+
google-re2 = "*"
910

1011
[dev-packages]
1112
pytest = "*"

Pipfile.lock

Lines changed: 59 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

protovalidate/internal/extra_func.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,19 @@
2929
)
3030

3131

32+
# Currently cel-python does not support re2. So we are overriding their `matches`
33+
# function with our own that leverages re2. Note there is a PR in cel-python to
34+
# add re2 support. See https://github.com/cloud-custodian/cel-python/pull/67.
35+
# Once that lands, this `matches` override can be removed.
36+
def cel_matches(text: str, pattern: str) -> celpy.Result:
37+
try:
38+
m = re2.search(pattern, text)
39+
except re2.error as ex:
40+
msg = "match error"
41+
raise celpy.CELEvalError(msg, ex.__class__, ex.args) from ex
42+
return celtypes.BoolType(m is not None)
43+
44+
3245
def cel_get_field(message: celtypes.Value, field_name: celtypes.Value) -> celpy.Result:
3346
if not isinstance(message, MessageType):
3447
msg = "invalid argument, expected message"
@@ -1553,22 +1566,14 @@ def __peek(self, char: str) -> bool:
15531566
return self._index < len(self._string) and self._string[self._index] == char
15541567

15551568

1556-
def matches(text: str, pattern: str) -> celpy.Result:
1557-
try:
1558-
m = re2.search(pattern, text)
1559-
except re2.error as ex:
1560-
return celpy.CELEvalError("match error", ex.__class__, ex.args)
1561-
return celtypes.BoolType(m is not None)
1562-
1563-
15641569
def make_extra_funcs(locale: str) -> dict[str, celpy.CELFunction]:
15651570
# TODO(#257): Fix types and add tests for StringFormat.
15661571
# For now, ignoring the type.
15671572
string_fmt = string_format.StringFormat(locale) # type: ignore
15681573
return {
15691574
# Missing standard functions
15701575
"format": string_fmt.format,
1571-
"matches": matches,
1576+
"matches": cel_matches,
15721577
# protovalidate specific functions
15731578
"getField": cel_get_field,
15741579
"isNan": cel_is_nan,

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ build-backend = "hatchling.build"
66
name = "protovalidate"
77
description = "Protocol Buffer Validation for Python"
88
readme = "README.md"
9-
license = { file = "LICENSE" }
9+
license-expression = "Apache 2.0"
10+
license-file = "LICENSE"
1011
keywords = ["validate", "protobuf", "protocol buffer"]
1112
requires-python = ">=3.9"
1213
classifiers = [
@@ -15,12 +16,11 @@ classifiers = [
1516
"Programming Language :: Python :: 3.11",
1617
"Programming Language :: Python :: 3.12",
1718
"Programming Language :: Python :: 3.13",
18-
"License :: OSI Approved :: Apache Software License",
1919
"Operating System :: OS Independent",
2020
"Typing :: Typed",
2121
]
2222
dynamic = ["version"]
23-
dependencies = ["protobuf", "cel-python"]
23+
dependencies = ["protobuf", "cel-python", "google-re2"]
2424

2525
[project.urls]
2626
Homepage = "https://github.com/bufbuild/protovalidate-python"

tests/matches_test.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,21 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
15+
import unittest
16+
17+
import pytest
18+
from celpy import CELEvalError, celtypes
19+
20+
from protovalidate.internal.extra_func import cel_matches
21+
22+
23+
class TestMatches(unittest.TestCase):
24+
def test_re2_end_of_string(self):
25+
empty_string = celtypes.StringType("")
26+
self.assertTrue(cel_matches(empty_string, "^\\z"))
27+
28+
def test_re2_invalid_end_of_string(self):
29+
empty_string = celtypes.StringType("")
30+
with pytest.raises(CELEvalError):
31+
self.assertTrue(cel_matches(empty_string, "^\\Z"))

0 commit comments

Comments
 (0)