Skip to content
Merged
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: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,5 @@ type_check/lineprecision.txt
# PyCharm Stuff
.idea/*
demo/issue_41.py
demo/issue_80.py
setup.sh
2 changes: 1 addition & 1 deletion demo/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ and examine the notebooks. We'll look at this from a Cloud Custodian (C7N) persp
- `demo/complex_policy.ipynb`_ shows a complex policy and how we can build -- and debug -- the policy
filter expression.

These should help youo build an understanding of
These should help you build an understanding of how to develop complex filters.
31 changes: 24 additions & 7 deletions src/celpy/evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1417,7 +1417,8 @@ def expr(self, tree: lark.Tree) -> Result:
expr : conditionalor ["?" conditionalor ":" expr]

The default implementation short-circuits
and can ignore an CELEvalError in a sub-expression.
and can ignore a CELEvalError in the two alternative sub-expressions.
The conditional sub-expression CELEvalError is propogated out as the result.

See https://github.com/google/cel-spec/blob/master/doc/langdef.md#logical-operators

Expand Down Expand Up @@ -2030,15 +2031,25 @@ def member_dot_arg(self, tree: lark.Tree) -> Result:
Tuple[lark.Tree, lark.Token], tree.children[:2]
)

if method_name_token.value in {"map", "filter", "all", "exists", "exists_one", "reduce", "min"}:
if method_name_token.value in {
"map",
"filter",
"all",
"exists",
"exists_one",
"reduce",
"min",
}:
member_list = cast(celpy.celtypes.ListType, self.visit(member_tree))

if isinstance(member_list, CELEvalError):
return member_list

if method_name_token.value == "map":
sub_expr = self.build_macro_eval(tree)
mapping = cast(Iterable[celpy.celtypes.Value], map(sub_expr, member_list))
mapping = cast(
Iterable[celpy.celtypes.Value], map(sub_expr, member_list)
)
result = celpy.celtypes.ListType(mapping)
return result

Expand All @@ -2052,19 +2063,25 @@ def member_dot_arg(self, tree: lark.Tree) -> Result:
and_oper = cast(
CELBoolFunction,
eval_error("no such overload", TypeError)(
celpy.celtypes.logical_and)
celpy.celtypes.logical_and
),
)
reduction = reduce(
and_oper, map(sub_expr, member_list), celpy.celtypes.BoolType(True)
)
reduction = reduce(and_oper, map(sub_expr, member_list), celpy.celtypes.BoolType(True))
return reduction

elif method_name_token.value == "exists":
sub_expr = self.build_ss_macro_eval(tree)
or_oper = cast(
CELBoolFunction,
eval_error("no such overload", TypeError)(
celpy.celtypes.logical_or)
celpy.celtypes.logical_or
),
)
reduction = reduce(
or_oper, map(sub_expr, member_list), celpy.celtypes.BoolType(False)
)
reduction = reduce(or_oper, map(sub_expr, member_list), celpy.celtypes.BoolType(False))
return reduction

elif method_name_token.value == "exists_one":
Expand Down
18 changes: 17 additions & 1 deletion tests/test_evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,8 +548,24 @@ def bad_condition(a, b, c):
activation,
functions={"_?_:_": bad_condition}
)
with raises(celpy.evaluation.CELEvalError):
with raises(celpy.evaluation.CELEvalError) as exc_info:
evaluator.evaluate()
assert exc_info.value.args == ("found no matching overload for _?_:_ applied to '(<class 'celpy.celtypes.BoolType'>, <class 'celpy.celtypes.IntType'>, <class 'celpy.celtypes.BoolType'>)'", TypeError, ())

def test_eval_expr_3_bad_cond_value(mock_left_expr_tree):
def bad_condition(a, b, c):
raise celpy.evaluation.CELEvalError("Baseline Error")
activation = Mock()
evaluator = Evaluator(
mock_left_expr_tree,
activation,
functions={"_?_:_": bad_condition}
)
with raises(celpy.evaluation.CELEvalError) as exc_info:
evaluator.evaluate()
print(repr(exc_info.value.args))
assert exc_info.value.args == ('Baseline Error',)


@fixture
def mock_right_expr_tree():
Expand Down
3 changes: 2 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

[tox]
skipsdist = true
envlist = py38,py39,py310,py311,py312,lint
envlist = py39,py310,py311,py312,py313,lint
minversion = 4.15.0

[testenv]
Expand All @@ -36,6 +36,7 @@ commands =
poetry run mypy --show-error-codes src

[testenv:lint]
usedevelop = true
depends = py312
basepython = python3.12
commands =
Expand Down
16 changes: 8 additions & 8 deletions type_check/lineprecision.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
Name Lines Precise Imprecise Any Empty Unanalyzed
-------------------------------------------------------------------
celpy 293 76 0 4 213 0
celpy.__main__ 465 172 7 42 244 0
celpy.adapter 137 35 3 9 85 5
celpy.c7nlib 1584 340 15 154 1075 0
celpy.celparser 401 207 2 22 170 0
celpy.celtypes 1503 438 14 221 791 39
celpy.evaluation 2472 835 33 177 1411 16
celpy 306 76 0 4 226 0
celpy.__main__ 508 204 8 42 254 0
celpy.adapter 141 34 3 9 89 6
celpy.c7nlib 1663 351 14 149 1149 0
celpy.celparser 388 199 3 22 164 0
celpy.celtypes 1504 417 14 224 812 37
celpy.evaluation 2595 872 38 177 1490 18
xlate 0 0 0 0 0 0
xlate.c7n_to_cel 1730 377 102 145 1101 5
xlate.c7n_to_cel 1755 385 103 146 1115 6
Loading