Skip to content

Commit

Permalink
Add support for isNan and isInf (#64)
Browse files Browse the repository at this point in the history
And update to protovaldiate v0.4.0
  • Loading branch information
Alfus authored Aug 23, 2023
1 parent dda35af commit 084944d
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 56 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ LICENSE_HEADER := $(BIN)/license-header \
--license-type apache \
--copyright-holder "Buf Technologies, Inc." \
--year-range "$(COPYRIGHT_YEARS)"
PROTOVALIDATE_VERSION ?= v0.3.1
PROTOVALIDATE_VERSION ?= v0.4.0

.PHONY: help
help: ## Describe useful make targets
Expand Down
92 changes: 46 additions & 46 deletions gen/buf/validate/validate_pb2.py

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions protovalidate/internal/extra_func.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import math
from ipaddress import IPv4Address, IPv6Address, ip_address
from urllib import parse as urlparse

Expand Down Expand Up @@ -105,6 +106,31 @@ def is_hostname(string: celtypes.Value) -> celpy.Result:
return celtypes.BoolType(_validate_hostname(string))


def is_nan(val: celtypes.Value) -> celpy.Result:
if not isinstance(val, celtypes.DoubleType):
msg = "invalid argument, expected double"
raise celpy.EvalError(msg)
return celtypes.BoolType(math.isnan(val))


def is_inf(val: celtypes.Value, sign: None | celtypes.Value = None) -> celpy.Result:
if not isinstance(val, celtypes.DoubleType):
msg = "invalid argument, expected double"
raise celpy.EvalError(msg)
if sign is None:
return celtypes.BoolType(math.isinf(val))

if not isinstance(sign, celtypes.IntType):
msg = "invalid argument, expected int"
raise celpy.EvalError(msg)
if sign > 0:
return celtypes.BoolType(math.isinf(val) and val > 0)
elif sign < 0:
return celtypes.BoolType(math.isinf(val) and val < 0)
else:
return celtypes.BoolType(math.isinf(val))


def unique(val: celtypes.Value) -> celpy.Result:
if not isinstance(val, celtypes.ListType):
msg = "invalid argument, expected list"
Expand All @@ -115,7 +141,11 @@ def unique(val: celtypes.Value) -> celpy.Result:
def make_extra_funcs(locale: str) -> dict[str, celpy.CELFunction]:
string_fmt = string_format.StringFormat(locale)
return {
# Missing standard functions
"format": string_fmt.format,
# protovalidate specific functions
"isNan": is_nan,
"isInf": is_inf,
"isIp": is_ip,
"isEmail": is_email,
"isUri": is_uri,
Expand Down
5 changes: 0 additions & 5 deletions tests/conformance/nonconforming.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,3 @@ standard_constraints/well_known_types/duration:
standard_constraints/well_known_types/timestamp:
- gte_lte/invalid/above
- lte/invalid
# celpy cannot divide by zero
standard_constraints/float:
- finite/neginf
standard_constraints/double:
- finite/neginf
6 changes: 2 additions & 4 deletions tests/validate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ def test_ninf(self):
msg = numbers_pb2.DoubleFinite()
msg.val = float("-inf")
violations = protovalidate.collect_violations(msg)
# TODO: update celpy to support divide by zero (which returns inf or -inf)
self.assertEqual(len(violations.violations), 0)
# self.assertEqual(len(violations.violations), 1)
# self.assertEqual(violations.violations[0].field_path, "val")
self.assertEqual(len(violations.violations), 1)
self.assertEqual(violations.violations[0].constraint_id, "double.finite")

def test_map_key(self):
msg = maps_pb2.MapKeys()
Expand Down

0 comments on commit 084944d

Please sign in to comment.