Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ conformance: $(BIN)/protovalidate-conformance generate install ## Run conformanc
lint: install $(BIN)/buf ## Lint code
buf format -d --exit-code
uv run -- ruff format --check --diff protovalidate test
uv run -- mypy protovalidate
uv run -- ty check protovalidate
uv run -- ruff check protovalidate test
uv lock --check

Expand Down
6 changes: 5 additions & 1 deletion protovalidate/internal/cel_field_presence.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@
# limitations under the License.

import threading
from typing import TYPE_CHECKING

import celpy

if TYPE_CHECKING:
import celpy.celtypes

_has_state = threading.local()


Expand All @@ -32,7 +36,7 @@ def in_has() -> bool:


class InterpretedRunner(celpy.InterpretedRunner):
def evaluate(self, context):
def evaluate(self, context: celpy.Context) -> celpy.celtypes.Value:
class Evaluator(celpy.Evaluator):
def macro_has_eval(self, exprlist):
_has_state.in_has = True
Expand Down
28 changes: 15 additions & 13 deletions protovalidate/internal/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,14 @@ def __init__(self, msg: message.Message):
continue
self[field.name] = field_to_cel(self.msg, field)

def __getitem__(self, name):
field = self.desc.fields_by_name[name]
if field.has_presence and not self.msg.HasField(name):
def __getitem__(self, key):
field = self.desc.fields_by_name[key]
if field.has_presence and not self.msg.HasField(key):
if in_has():
raise KeyError()
else:
return _zero_value(field)
return super().__getitem__(name)
return super().__getitem__(key)


def _msg_to_cel(msg: message.Message) -> celtypes.Value:
Expand Down Expand Up @@ -303,7 +303,7 @@ def sub_context(self) -> "RuleContext":
class Rules:
"""The rules associated with a single 'rules' message."""

def validate(self, ctx: RuleContext, _: message.Message):
def validate(self, ctx: RuleContext, message: message.Message): # noqa: ARG002
"""Validate the message against the rules in this rule."""
ctx.add(Violation(rule_id="unimplemented", message="Unimplemented"))

Expand Down Expand Up @@ -415,8 +415,8 @@ def __init__(self, fields: list[descriptor.FieldDescriptor], *, required: bool):
self._fields = fields
self._required = required

def validate(self, ctx: RuleContext, msg: message.Message):
num_set_fields = sum(1 for field in self._fields if not _is_empty_field(msg, field))
def validate(self, ctx: RuleContext, message: message.Message):
num_set_fields = sum(1 for field in self._fields if not _is_empty_field(message, field))
Comment on lines +418 to +419
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ty wants the names of the arguments to match when over-riding from a superclass.

if num_set_fields > 1:
ctx.add(
Violation(
Expand Down Expand Up @@ -561,8 +561,8 @@ def __init__(
# For each set field in the message, look for the private rule
# extension.
for list_field, _ in rules.ListFields():
if validate_pb2.predefined in list_field.GetOptions().Extensions: # type: ignore
for cel in list_field.GetOptions().Extensions[validate_pb2.predefined].cel: # type: ignore
if validate_pb2.predefined in list_field.GetOptions().Extensions:
for cel in list_field.GetOptions().Extensions[validate_pb2.predefined].cel:
self.add_rule(
env,
funcs,
Expand Down Expand Up @@ -617,11 +617,13 @@ def validate(self, ctx: RuleContext, message: message.Message):
sub_ctx.add_field_path_element(element)
ctx.add_errors(sub_ctx)

def validate_item(self, ctx: RuleContext, val: typing.Any, *, for_key: bool = False):
self._validate_value(ctx, val, for_key=for_key)
self._validate_cel(ctx, this_value=val, this_cel=_scalar_field_value_to_cel(val, self._field), for_key=for_key)
def validate_item(self, ctx: RuleContext, value: typing.Any, *, for_key: bool = False):
self._validate_value(ctx, value, for_key=for_key)
self._validate_cel(
ctx, this_value=value, this_cel=_scalar_field_value_to_cel(value, self._field), for_key=for_key
)

def _validate_value(self, ctx: RuleContext, val: typing.Any, *, for_key: bool = False):
def _validate_value(self, ctx: RuleContext, value: typing.Any, *, for_key: bool = False):
Comment on lines +620 to +626
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed to value here

pass


Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ Issues = "https://github.com/bufbuild/protovalidate-python/issues"
[dependency-groups]
dev = [
"google-re2-stubs>=0.1.1",
"mypy>=1.17.1",
"pytest>=8.4.1",
"ruff>=0.12.0",
"ty>=0.0.12",
"types-protobuf>=5.29.1.20250315",
]

Expand Down
Loading