Skip to content
Closed
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 @@ -93,7 +93,7 @@ HELP_TEXT += "\n"
HELP_TEXT += " format runs code formatting\n"
.PHONY: format
format:
uv run ruff format src tools
uv run ruff format src tools tests

HELP_TEXT += " coverage generates code coverage reports\n"
.PHONY: coverage
Expand Down
2 changes: 1 addition & 1 deletion features/json_query.feature
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ And JSON document '1.0'
And JSON document '"1"'
And JSON document '"banana"'
When echo document | celpy --json-document=_ '_ == 1' is run
Then stdout is 'true\nnull\nnull\nnull\n'
Then stdout is 'true\ntrue\nfalse\nfalse\n'
And stderr is ''
And exit status is 0

Expand Down
8 changes: 4 additions & 4 deletions features/logic.feature
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ Scenario: AND/short_circuit_error_right
Scenario: AND/error_right

When CEL expression 'true && 1/0 != 0' is evaluated
Then eval_error is 'no matching overload'
Then value is celpy.celtypes.BoolType(source=True)

Scenario: AND/error_left

When CEL expression '1/0 != 0 && true' is evaluated
Then eval_error is 'no matching overload'
Then value is celpy.celtypes.BoolType(source=True)

Scenario: AND/no_overload

Expand Down Expand Up @@ -141,12 +141,12 @@ Scenario: OR/short_circuit_error_right
Scenario: OR/error_right

When CEL expression 'false || 1/0 != 0' is evaluated
Then eval_error is 'no matching overload'
Then value is celpy.celtypes.BoolType(source=True)

Scenario: OR/error_left

When CEL expression '1/0 != 0 || false' is evaluated
Then eval_error is 'no matching overload'
Then value is celpy.celtypes.BoolType(source=True)

Scenario: OR/no_overload

Expand Down
16 changes: 4 additions & 12 deletions features/logic.textproto
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,12 @@ section {
test {
name: "error_right"
expr: "true && 1/0 != 0"
eval_error: {
errors: { message: "no matching overload" }
}
value: { bool_value: true }
}
test {
name: "error_left"
expr: "1/0 != 0 && true"
eval_error: {
errors: { message: "no matching overload" }
}
value: { bool_value: true }
}
test {
name: "no_overload"
Expand Down Expand Up @@ -154,16 +150,12 @@ section {
test {
name: "error_right"
expr: "false || 1/0 != 0"
eval_error: {
errors: { message: "no matching overload" }
}
value: { bool_value: true }
}
test {
name: "error_left"
expr: "1/0 != 0 || false"
eval_error: {
errors: { message: "no matching overload" }
}
value: { bool_value: true }
}
test {
name: "no_overload"
Expand Down
3 changes: 1 addition & 2 deletions features/steps/cli_binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ def step_impl(context, arguments):

context.data['arguments'] = shlex.split(arguments)

env = context.config.userdata['env']
test_dir = Path.cwd() / ".test" / env
test_dir = Path.cwd() / ".test"
test_dir.mkdir(exist_ok=True, parents=True)
temp = test_dir / "test.json"
temp.write_text("\n".join(context.data['json']) + "\n")
Expand Down
1 change: 1 addition & 0 deletions features/steps/integration_binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

- error_case: ``"2 / 0 > 4 ? 'baz' : 'quux'"`` --> "division by zero"

TODO: update this example; this no longer results in "no matching overload".
- error_right: ``"true && 1/0 != 0"`` --> "no matching overload"

Sometimes (``2 / 0 > 4``) the first exception is preserved.
Expand Down
37 changes: 15 additions & 22 deletions src/celpy/celtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@
import logging
import re
from functools import reduce, wraps
from math import fsum
from math import fsum, trunc
from typing import (
Any,
Callable,
Expand All @@ -210,9 +210,8 @@
)

import pendulum
from pendulum import timezone
import pendulum.tz.exceptions

from pendulum import timezone

logger = logging.getLogger(f"celpy.{__name__}")

Expand Down Expand Up @@ -350,12 +349,6 @@ def logical_or(x: Value, y: Value) -> Value:

Example 1::

false || 1/0 != 0

is a "no matching overload" error.

Example 2::

(2 / 0 > 3 ? false : true) || true

is a "True"
Expand Down Expand Up @@ -398,6 +391,12 @@ def __new__(cls: Type["BoolType"], source: Any) -> "BoolType":
return source
elif isinstance(source, MessageType):
return super().__new__(cls, cast(int, source.get(StringType("value"))))
elif isinstance(source, (str, StringType)):
if source in ("False", "f", "FALSE", "false"):
return super().__new__(cls, 0)
if source in ("True", "t", "TRUE", "true"):
return super().__new__(cls, 1)
return super().__new__(cls, source)
else:
return super().__new__(cls, source)

Expand Down Expand Up @@ -495,11 +494,9 @@ def __rtruediv__(self, other: Any) -> "DoubleType":
else:
return DoubleType(super().__rtruediv__(other))

@type_matched
def __eq__(self, other: Any) -> bool:
return super().__eq__(other)

@type_matched
def __ne__(self, other: Any) -> bool:
return super().__ne__(other)

Expand Down Expand Up @@ -545,7 +542,7 @@ class IntType(int):
ValueError: overflow

>>> IntType(DoubleType(1.9))
IntType(2)
IntType(1)
>>> IntType(DoubleType(-123.456))
IntType(-123)
"""
Expand All @@ -562,7 +559,7 @@ def __new__(
# Used by protobuf.
return super().__new__(cls, cast(int, source.get(StringType("value"))))
elif isinstance(source, (float, DoubleType)):
convert = int64(round)
convert = int64(trunc)
elif isinstance(source, TimestampType):
convert = int64(lambda src: src.timestamp())
elif isinstance(source, (str, StringType)) and source[:2] in {"0x", "0X"}:
Expand Down Expand Up @@ -642,27 +639,21 @@ def __rmod__(self, other: Any) -> "IntType":
go_mod = left_sign * (abs(other) % abs(self))
return IntType(go_mod)

@type_matched
def __eq__(self, other: Any) -> bool:
return super().__eq__(other)

@type_matched
def __ne__(self, other: Any) -> bool:
return super().__ne__(other)

@type_matched
def __lt__(self, other: Any) -> bool:
return super().__lt__(other)

@type_matched
def __le__(self, other: Any) -> bool:
return super().__le__(other)

@type_matched
def __gt__(self, other: Any) -> bool:
return super().__gt__(other)

@type_matched
def __ge__(self, other: Any) -> bool:
return super().__ge__(other)

Expand Down Expand Up @@ -729,7 +720,7 @@ def __new__(
if isinstance(source, UintType):
return source
elif isinstance(source, (float, DoubleType)):
convert = uint64(round)
convert = uint64(trunc)
elif isinstance(source, TimestampType):
convert = uint64(lambda src: src.timestamp())
elif isinstance(source, (str, StringType)) and source[:2] in {"0x", "0X"}:
Expand Down Expand Up @@ -799,11 +790,9 @@ def __rtruediv__(self, other: Any) -> "UintType":
def __rmod__(self, other: Any) -> "UintType":
return UintType(super().__rmod__(cast(IntType, other)))

@type_matched
def __eq__(self, other: Any) -> bool:
return super().__eq__(other)

@type_matched
def __ne__(self, other: Any) -> bool:
return super().__ne__(other)

Expand Down Expand Up @@ -841,6 +830,8 @@ def __ge__(self, other: Any) -> NoReturn:
raise TypeError("no such overload")

def __eq__(self, other: Any) -> bool:
if other is None:
return False
if not isinstance(other, (list, ListType)):
raise TypeError(f"no such overload: ListType == {type(other)}")

Expand Down Expand Up @@ -928,6 +919,8 @@ def __getitem__(self, key: Any) -> Any:
return super().__getitem__(key)

def __eq__(self, other: Any) -> bool:
if other is None:
return False
if not isinstance(other, (Mapping, MapType)):
raise TypeError(f"no such overload: MapType == {type(other)}")

Expand Down
25 changes: 14 additions & 11 deletions tests/test_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"""
C7N Type Adapter Test Cases.
"""

import datetime

import celpy.adapter
Expand All @@ -28,30 +29,32 @@ def test_json_to_cel():
assert str(celpy.adapter.json_to_cel(False)) == str(celpy.celtypes.BoolType(False))
assert celpy.adapter.json_to_cel(2.5) == celpy.celtypes.DoubleType(2.5)
assert celpy.adapter.json_to_cel(42) == celpy.celtypes.IntType(42)
assert celpy.adapter.json_to_cel("Hello, world!") == celpy.celtypes.StringType("Hello, world!")
assert celpy.adapter.json_to_cel("Hello, world!") == celpy.celtypes.StringType(
"Hello, world!"
)
assert celpy.adapter.json_to_cel(None) is None
assert celpy.adapter.json_to_cel(["Hello", "world!"]) == celpy.celtypes.ListType(
[
celpy.celtypes.StringType("Hello"),
celpy.celtypes.StringType("world!"),
]
)
assert celpy.adapter.json_to_cel(tuple(["Hello", "world!"])) == celpy.celtypes.ListType(
assert celpy.adapter.json_to_cel(
tuple(["Hello", "world!"])
) == celpy.celtypes.ListType(
[
celpy.celtypes.StringType("Hello"),
celpy.celtypes.StringType("world!"),
]
)
assert celpy.adapter.json_to_cel({"Hello": "world!"}) == celpy.celtypes.MapType(
{
celpy.celtypes.StringType("Hello"):
celpy.celtypes.StringType("world!"),
celpy.celtypes.StringType("Hello"): celpy.celtypes.StringType("world!"),
}
)
assert (
celpy.adapter.json_to_cel(datetime.datetime(2020, 9, 10, 11, 12, 13, tzinfo=datetime.timezone.utc))
== celpy.celtypes.TimestampType("2020-09-10T11:12:13Z")
)
assert (
celpy.adapter.json_to_cel(datetime.timedelta(days=42)) == celpy.celtypes.DurationType("42d")
)
assert celpy.adapter.json_to_cel(
datetime.datetime(2020, 9, 10, 11, 12, 13, tzinfo=datetime.timezone.utc)
) == celpy.celtypes.TimestampType("2020-09-10T11:12:13Z")
assert celpy.adapter.json_to_cel(
datetime.timedelta(days=42)
) == celpy.celtypes.DurationType("42d")
Loading
Loading